Giter Club home page Giter Club logo

http's Introduction

http's People

Contributors

0xtim avatar artkay avatar brettrtoomey avatar bygri avatar calebkleveter avatar czechboy0 avatar damuellen avatar evertt avatar givip avatar grundoon avatar gwynne avatar harlanhaskins avatar jdmcd avatar joannis avatar ketzusaka avatar kylebshr avatar loganwright avatar mura-admin avatar obbut avatar p4t5h3 avatar rugaard avatar sarbogast avatar shnhrrsn avatar steffendsommer avatar svanimpe avatar tanner0101 avatar timominous avatar vkill avatar vzsg avatar yikandel avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

http's Issues

websocket ping api

Add an easy API for pinging an open websocket to keep it from timing out.

try ws.ping(every: 10)
    try background { [weak ws] in
        if ws?.state == .open {
            print("ping")
            try? ws?.ping()
            drop.console.wait(seconds: 10)
        }
    }

String has no content type

String's conformance to HTTPResponseRepresentable should set the text/plain content type.

This will get rid of this error in Vapor:

Response had no 'Content-Type' header.

Tests fail when ran in a different timezone

I'm based in the Czech Republic (UTC+2 now in the summer) and I have Engine tests failing because the date formatters are using specific timestamps, which translate to different dates here. Specifically those are:

Failing because of timezone:

SMTPDateTests.testSMTPDate()

Because of getting different response to google.com:

SockStreamTests.testTCPInternetSocket()
SockStreamTests.testFoundationStream()

I get: HTTP/1.0 302 Found\r\nCache-Control: private\r\nContent-Type: text/html; charset=UTF-8\r\nLocation: http://www.google.cz/?gfe_rd=cr&ei=WYG8V_CHBtDR8geml7zYAg\r\nContent-Length: 258\r\nDate: Tue, 23 Aug 2016 17:01:13 GMT\r\n\r\n<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n<TITLE>302 Moved</TITLE></HEAD><BODY>\n<H1>302 Moved</H1>\nThe document has moved\n<A HREF=\"http://www.google.cz/?gfe_rd=cr&amp;ei=WYG8V_CHBtDR8geml7zYAg\">here</A>.\r\n</BODY></HTML>\r\n

We just need to find a way to ensure the timezone tests work around the world (probably by setting the timezone in tests to a set one), and pick a different URL than google.com which responds the same way to all locations.

A large response body gets cut off when using EngineClient

Environment

Vapor version: 2.0.0-beta.1
Engine version: 2.0.0-beta.1
macOS version: 10.12.4
Swift version: 3.1
Xcode version: 8.3

When using the default droplet client (EngineClient) to make a request that has a large response body, the body will get cut off in the response.

e.g.

let response = try drop.client.get("https://api.github.com/repos/octokit/octokit.rb/releases")
response.json // nil

Upon further investigation dumping the response dump(response) I get the following:

Response
- HTTP/1.1 200 OK
- Headers:
    Access-Control-Expose-Headers: ETag, Link, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval
    X-GitHub-Media-Type: github.v3; format=json
    X-RateLimit-Reset: 1490911130
    ETag: "a1fc205783d327be17f7eafbf3f96002"
    X-Served-By: eef8b8685a106934dcbb4b7c59fba0bf
    Date: Thu, 30 Mar 2017 21:10:37 GMT
    Content-Type: application/json; charset=utf-8
    Content-Length: 59035
    X-Content-Type-Options: nosniff
    Status: 200 OK
    Link: <https://api.github.com/repositories/417862/releases?page=2>; rel="next", <https://api.github.com/repositories/417862/releases?page=2>; rel="last"
    X-GitHub-Request-Id: D6FD:64DE:73E781:93C62B:58DD744D
    Cache-Control: public, max-age=60, s-maxage=60
    Server: GitHub.com
    Vary: Accept-Encoding
    Content-Security-Policy: default-src 'none'
    X-XSS-Protection: 1; mode=block
    X-RateLimit-Limit: 60
    X-RateLimit-Remaining: 58
    Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
    X-Frame-Options: deny
    Access-Control-Allow-Origin: *
- Body:
    [{"url":"https://api.github.com/repos/octokit/octokit.rb/releases/4549630","assets_url":"https://api.github.com/repos/octokit/octokit.rb/releases/4549630/assets","upload_url":"https://uploads.github.com/repos/octokit/octokit.rb/releases/4549630/assets{?name,label}","html_url":"https://github.com/octokit/octokit.rb/releases/tag/v4.6.0","id":4549630,"tag_name":"v4.6.0","target_commitish":"master","name":"","draft":false,"author":{"login":"joeyw","id":478247,"avatar_url":"https://avatars1.githubusercontent.com/u/478247?v=3","gravatar_id":"","url":"https://api.github.com/users/joeyw","html_url":"https://github.com/joeyw","followers_url":"https://api.github.com/users/joeyw/followers","following_url":"https://api.github.com/users/joeyw/following{/other_user}","gists_url":"https://api.github.com/users/joeyw/gists{/gist_id}","starred_url":"https://api.github.com/users/joeyw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/joeyw/subscriptions","organizations_url":"https://api.github.com/users/joeyw/orgs","repos_url":"https://api.github.com/users/joeyw/repos","events_url":"https://api.github.com/users/joeyw/events{/privacy}","received_events_url":"https://api.github.com/users/joeyw/received_events","type":"User","site_admin":false},"prerelease":false,"created_at":"2016-11-08T16:22:37Z","published_at":"2016-11-09T08:37:49Z","assets":[],"tarball_url":"https://api.github.com/repos/octokit/octokit.rb/tarball/v4.6.0","zipball_url":"https://api.github.com/repos/octokit/octokit.rb/zipball/v4.6.0","body":"### Library Changes\n\n#829 Sawyer dependency loosened to support new release `'sawyer', '>= 0.5.3', '~> 0.8.0'` Tha

Also trying to parse body.bytes into JSON throws JayError.unexpectedEnd

I was able to get things working by using the FoundationClient instead:

extension FoundationClient: ClientProtocol {
    public convenience init(hostname: String, port: Port, _ securityLayer: SecurityLayer) throws {
        self.init(scheme: "https", hostname: hostname, port: port)
    }
}
drop.client = FoundationClient.self

let response = try drop.client.get("https://api.github.com/repos/octokit/octokit.rb/releases")
response.json // not nil YAAAAYYYY!!!

URI Parser doesn't allow hostname containing _

I am having issues in connecting to a server with an hostname containing _:

try EngineClientFactory().get("http://test_server-02:8080/my/path")

The problem is in the URIParser class, which crops the hostname to test rather than test_server-02.

Conform FoundationClient to ClientProtocol

To workaround the Issue #119 I replaced the Droplets default EngineClient with the FoundationClient like so:

extension FoundationClient: ClientProtocol {
    public convenience init(hostname: String, port: Port, _ securityLayer: SecurityLayer) throws {
        self.init(scheme: "https", hostname: hostname, port: port)
    }
}
drop.client = FoundationClient.self

But I feel like since the FoundationClient should already conform to this protocol so I can easily interchange the two without having to do this myself.

Server stalls if the GCD thread pool is exhausted

Grand Central Dispatch is spawning a limited amount of threads (my tests indicated number of virtual CPU cores * 5, but at minimum 64).

Since Server responds to requests on a GCD queue, the server stalls if that pool is exhausted. New requests get queued but may wait for processing forever โ€“ for example if all threads are waiting for data on sockets that are not connected anymore (there is currently no read timeout set on server sockets).

When running behind nginx, this is irrelevant as long as the connection between nginx and Vapor is good.
When exposed directly, the server stalls within minutes or hours.

I think it's reasonable to only process 64 parallel requests; however, waiting on (potentially dead) sockets shouldn't happen in this queue. A read timeout on the socket would help, but not solve the problem.

In the end, the socket should be non-blocking. Unfortunately, I currently don't see an easy way to get there.

Client / Server parity

The server currently takes 3 generic arguments to be created, but client only takes 1. Is it possible to have them both take 3?

Add back heroku builds

Add back app.json file (even though it's a little annoying). We no longer use executables, but heroku is still another system that can compile and spit out errors quickly. I think it's useful to know when we've introduced a breaking change on a PR.

[SMTP.SMTPClientError: invalidGreeting(code: -1, greeting: "")]

Bugs

Introduction

in V1 it was working with:

let client = try SMTPClient<TCPClientStream>.init(host: host, port: port, securityLayer: SecurityLayer.tls(nil))
try client.send(email, using: credentials)

In V2 I'm trying to send a Mail over SMTP using smpt.zoho.com.

Got the credentials and client conf in a smtpzoho.json file:

{
        "client": {
        "scheme": "smtps",
        "host": "smtp.zoho.eu",
        "port": 465
}

Code

        let credentials = SMTPCredentials(user: user, pass: pass)
        let from = EmailAddress(name: name, address: emailAddress)
        let to = EmailAddress(name: name, address: emailAddress)
        let emailBody = EmailBody(content: "\(nameRequest) - \(emailRequest) : \(messageRequest)")
        
        let email = Email(from: from,
                          to: to,
                          subject: "Contact form \(name)",
                          body: emailBody)
        
        
        let portConverted = Port(port)
                
        let mailer = SMTPMailer.init(scheme: scheme, hostname: host, port: portConverted, credentials: credentials)
        try mailer.send(email)

Mostly the last two lines have changed, and now a scheme has to be provided. I've tried with several schemes like "ssl", "smtps", ssmtp", "http", "https" but all give me the same error:

[SMTP.SMTPClientError: invalidGreeting(code: -1, greeting: "")]
Conform 'SMTP.SMTPClientError' to Debugging.Debuggable to provide more debug information.

WebSocket crashes during key negotiation on server side

Bugs

When building with Xcode 8.2 and running the Vapor WebClient (under XCTest) communicating with the WebServer under Vapor (running using startServers() to run it in the background), I get an Error: Array out of bounds error.

I have tracked it down to the code:
let combination = requestKey.bytes.trimmed([.space]).array + hashKey

Apparently, this generates an [Byte] and the next line of code then crashes. Changing this to create a Data instance from the [Byte] allows the Hash code to call the ByteRepresentable code that allocates a new block and avoids this error.

The new line then reads:
let combination = Data(requestKey.bytes.trimmed([.space]).array + hashKey)

client not closing sockets

It appears that the client does not close the stream after it connects.

This is causing servers to be unable to open views or make new connections after a number of client calls.

Updating the TCPClientStream with a deinit might fix this:

public final class TCPClientStream: TCPProgramStream, ClientStream  {
    public func connect() throws -> Stream {
        switch securityLayer {
        case .none:
            try stream.connect()
            return stream
        case .tls(let provided):
            let config: Config
            if let c = provided {
                config = c
            } else {
                config = try defaultClientConfig()
            }
            let secure = try TLS.Socket(config: config, socket: stream)
            try secure.connect(servername: host)
            return secure
        }
    }

    deinit {
        try? stream.close()
    }
}

SMTP: Message-Id is not valid, according to RFC 2822

Message-Id header generated by NSUUID.smtpMessageId does not conform to RFC 2822 3.6.4.

The header should look like Message-Id: <id-left@id-right>, but it looks like Message-Id: some-id.

Example of a proper header:
Message-Id: <[email protected]>

Example of a malformed Vapor header:
Message-Id: 96A48F682B3B46C28A3F208C9BD4F356

Example of a Vapor header automatically fixed by Gmail during delivery:
Message-Id: <[email protected]>

Motivation

I have noticed this issue because any emails sent using Vapor SMTP get an INVALID_MSGID penalty from SpamAssassin.

Proposed solution

Conform to RFC by appending @hostname and adding angular brackets to the message ID. The current host name can be retrieved using gethostname function as seen here. I can create a pull request with appropriate changes, but I'm not sure how to properly attribute a relevant code snippet from Swift repo.

Impact

Actual Message ID value is not used within Vapor, so the change will not affect anything except SMTPUUIDTests.swift

Response code for redirect helper should use 307 (Temporary Redirect) instead of 302 (Found)

Bug

When using redirects and the helper function in HTTP/Models/Response/Response.swift:
public convenience init(headers: [HeaderKey: String] = [:], redirect location: String, permanently: Bool = false)

I noticed that the code uses .Found (302). I believe that the industry has moved from using 302 (which was ambiguous in its meeting) to TemporaryRedirect (307).

Can a change be made to change from:
let status: Status = permanently ? .movedPermanently : .found

to:
let status: Status = permanently ? .movedPermanently : .temporaryRedirect

Feature request: Allow custom User-Agent header in HTTP client

Feature, Enhancement, or Optimization

Allow custom User-Agent header in HTTP client

Introduction

HTTP Client currently has a hard-coded User-Agent.

Motivation

While User-Agents should not be used as some sort of security mechanism, some API's/services may treat a client differently when it is not what they expect. I'm not aware of any other HTTP clients that do not allow you to modify your User-Agent.

Proposed solution

Let the existing Vapor client User-Agent be the default value if one is not provided to the client like other headers.

Impact

There should be no impact as long as the current User-Agent is still provided as a default.

http client sending body twice

Bug

Introduction

When sending a PUT request to a Node.js REST service on my local machine that takes on average 700ms to 1s to resolve, the Vapor application fails the client request almost immediately before the request even touches the starting breakpoint of the Node.js route handler. I've only seen this issue occur when using the Vapor Engine 2.0.3 as the client framework; when the framework is switched to Foundation the error disappeared completely and the REST request would resolve normally.

I've tracked the issue down to a specific block of code in the HTTP+Client.swift file of the Vapor Engine 2.0.3 package. From what I can tell the stream sends the bytes to the Node.js REST service on line 69 of my screenshot below but attempts to read from the stream too quickly on line 88 despite the fact that my service hasn't completed its operation yet. As a result, the read constant is set to 0 and the response stream appears to be empty which triggers the guard to break the while loop; causing the empty Response object to throw the StreamError.closed error.

vapor http client request - no breakpoint blocking

When a breakpoint is set on line 81 of the screenshot below and the client request is made, the breakpoint is hit and execution is blocked for roughly 2-3 seconds before I allow the program to continue execution. Given the brief pause, my Node.js service is able to complete it's operation and the stream can successfully read the response from my service. As a result the read constant is now set to 2048 instead and the Response object is successfully initialized.

vapor http client request - breakpoint blocking

unsupportedURICharacter(60) error when running on Linux

I have a simple websocket client that uses Vapor Engine. The client connects to a wss:// endpoint.
The client works fine on macOS.

However, when I compile and run it on Ubuntu, it doesn't connect and I get the following cryptic error:

unsupportedURICharacter(60)

Any ideas what might be the problem?

Unexpected new behavior of Response(redirect:)

Introduction

(Continuing from vapor/vapor#1018.)

#88 incorrectly assumed that the HTTP 307 status is the de facto replacement of the old 302 status code.

Changing the code returned introduced a sneaky breaking behavioral change, making a common use case impossible without dropping down to manually creating redirect responses.

This comes down to a wrong idea: there are not just two kinds of redirects (permanent or temporary).

Previously in Vapor 1

A very common pattern in web apps is redirecting the browser after a form POST request to a result or list page, which would be loaded using a GET request. (By using this, the chance of duplicated POST requests happening on a page refresh is close to zero.)

In V1, using Response.redirect in a post handler achieved exactly that.

In V2 with #88 in place, this is not readily available and migrated apps will break.

History lesson

The industry moved from 302 because the browser's expected behavior was not explicitly defined. The de facto behavior eventually became that the new request uses the GET method โ€” allowing for the forementioned pattern.

Instead, the status codes 303 and 307 allow for explicit control over the new request. 303 forces the user agent to use GET, and 307 forces it to use the original method again.

These two distinct behaviors, along with 301 โ€” which is exposed via the permanently parameter โ€” are valid choices that should all be available easily.

Proposed solution

  1. Undo #88 and make 302 (or 303) the default temporary redirect again to avoid projects breaking.
  2. (Optionally) add another convenience initializer that either takes a HTTP status code, or an enum to select one of the three behaviors.

Workaround

Manually building the redirect response works:

return Response(status: .seeOther, headers: [.location: "url"])

Crash while serializing request URI (ubuntu only)

Bugs

If you find a bug, please submit a pull request with a failing test case displaying the bug or just create an issue with as much information as possible.


*** Error in `.build/debug/App': corrupted double-linked list: 0x00007f3864027f60 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7f387c7827e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x7e6f8)[0x7f387c7896f8]
/lib/x86_64-linux-gnu/libc.so.6(+0x813be)[0x7f387c78c3be]
/lib/x86_64-linux-gnu/libc.so.6(__libc_malloc+0x54)[0x7f387c78e5d4]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(+0x32a9d4)[0x7f387e2d39d4]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(CFCharacterSetAddCharactersInString+0x144)[0x7f387e2cdb64]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(CFCharacterSetCreateWithCharactersInString+0x159)[0x7f387e2cdfc9]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(+0x36d330)[0x7f387e316330]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libdispatch.so(dispatch_once_f+0x3b)[0x7f387f48c00b]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(_CFURLComponentsGetURLQueryAllowedCharacterSet+0x2a)[0x7f387e3140fa]
/home/xxx/.swiftenv/versions/3.1/usr/lib/swift/linux/libFoundation.so(_TZFC10Foundation14NSCharacterSetg15urlQueryAllowedVS_12CharacterSet+0xc)[0x7f387e5f329c]

call is coming from Request at let encoded = q.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)

Not really sure what to do about this, since it's probably a swift bug. Does anyone have a reference to a reported bug or a workaround?

The query string that is crashing :

โ–ฟ 5 elements
  โ–ฟ 0 : 2 elements
    - key : "legal_entity[type]"
    - value : "company"
  โ–ฟ 1 : 2 elements
    - key : "managed"
    - value : true
  โ–ฟ 2 : 2 elements
    - key : "metadata[id]"
    - value : "28"
  โ–ฟ 3 : 2 elements
    - key : "email"
    - value : "[email protected]"
  โ–ฟ 4 : 2 elements
    - key : "country"
    - value : "US"

Helpers for Authentication Headers

Feature, Enhancement, or Optimization

Helpers for Authentication Headers

Introduction

Add helpers for setting authentication headers (Basic, Bearer)

Motivation

Eliminate the need for making Authentication Header strings from scratch when unit testing or doing outbound requests.

Proposed solution

Extend Request with something like this:

    func setBasicAuth(username: String, password: String) {
        let encoded = "\(username):\(password)".makeBytes().base64Encoded.makeString()
        headers[.authorization] = "Basic \(encoded)"
    }
    
    func setBearerAuth(token: String) {
        headers[.authorization] = "Bearer \(token)"
    }

Code snippets

func testUserRegister() throws {
    
    let username = "testUserRegister_username"
    let password = "testUserRegister_password"
    
    let req = Request(method: .post, uri: "/user/register/")
    req.setBasicAuth(username: username, password: password)
    
    _ = try drop.respond(to: req)
    
    let user = try User.first(with: [("username", username)])
    
    XCTAssertNotNil(user, "user not registered")
}

Alternatives considered

Other classes/protocols in other modules could be modified to similar effect, like Credentials in Authentication with Password and Token conforming.

req[.authorization] = password.makeAuthString()

If agreed, i can make a pull request.

Docs are now incorrect after renaming

On the README:

import Engine

let response = try HTTPClient<TCPClientStream>.get("http://pokeapi.co/api/v2/pokemon/")
print(response)

In the example:

import HTTP
import Transport

let response = try Client<TCPClientStream>.get("http://pokeapi.co/api/v2/pokemon/")
print(response)

URI should be CustomStringConvertible

I'd like to print out a full URI object, or use it as a string. Currently I can't without an extension. URI should store the original string used to create it, or be able to output its representation in a way.

Update to eliminate deprecation warning

I'm just trying Vapor for the first time today. Xcode 8.1 (not that I think the version matters) pops a deprecation warning for line 27 of Transport/Streams/Socks+Stream.swift. For fear of stepping on someone's toes, I offer this issue here rather than submitting a pull request. Changing the line to read:

try setSendingTimeout(timeval(seconds: timeout))

fixes the problem. I'm happy to submit it as a PR if that helps, but again don't want to step on anyone's toes. Thanks!

Percent Encoding in URL Path

I have an API with a URI like this:

let uri = "http://vapor.com/api/users/P%2BXCW4asdfa%2FOljlkH90/image?size=small&color=blue"

I then call:

let result = drop.client.get(uri)

Vapor then calls URIParser.parse(...) to decode the URI including the path:
https://github.com/vapor/engine/blob/master/Sources/URI/Parser/Parser.swift#L66

Unfortunately, Vapor will decode, then re-encode the ENTIRE path.
In this case, when it decodes and re-encodes the path component (in Request.swift), "P%2BXCW4asdfa%2FOljlkH90" gets "malformed" and creates/interprets it as a new path component:ย "P+XCW4asdfa/OljlkH90".

The correct solution is for Vapor to faithfully reproduce my original URL, but I think Vapor is trying to be "correct" and build a "model" of what my URL looks like. But it's not accommodating for percent encoding in the URL path.

TLS handshake doesn't work with startAsync on TCPServerStream

Take the following server with a security layer config launched on macOS:

let tlsConfig = try TLS.Config(
            mode: .server,
            certificates: .files(
                certificateFile: publicCert,
                privateKeyFile: privateKey,
                signature: .selfSigned
            ),
            verifyHost: true,
            verifyCertificates: true
        )
self.server = try Server<TCPServerStream, Parser<Request>, Serializer<Response>>(
                host:"127.0.0.1",
                port: port,
                securityLayer: SecurityLayer.tls(self.tlsConfig)
            )

When I start with the synchronous method start, the handshake with the client is done without any issue. But if I start the server with the asynchronous method startAsync, the handshake fails. By digging into LibreSSL I found that the handshake fails with the following error SSL_ERROR_WANT_READ => TLS_WANT_POLLIN.

[WebSocket] Sec-WebSocket-Key Hashing Incorrectly

Platform: Ubuntu 16.04
Toolchain: Swift 3.1-DEVELOPMENT-SNAPSHOT-2017-03-13
Engine version: 1.3.11

On Ubuntu 16.04, exchange(requestKey) consistently removes the third character from the end of the key, causing incorrect invalidSecAcceptHeader errors.

Correct: 7VcW5v8fw9RuwsCtndDDs+VmQus=
After hashing: 7VcW5v8fw9RuwsCtndDDs+Vmus=

Correct: tlfzFb2mOM86dj/ZWpxF0VCvy6s=
After hashing: tlfzFb2mOM86dj/ZWpxF0VCv6s=

set-cookie parity

In Vapor/Cookie we are using a hack like "set-cookie": "cookie=42; Path=/\r\nset-cookie:hi=1337" to work with setting cookies for response serialization.

We need to accept the same format for response parsing. I think this can be achieved with 1 simple rule: if we already have this header key, then append it with /r/nkey:

Once this is done, we'll have full cookie support in Vapor.

Sending email via SMTP causes Illegal Instruction when running in a Docker image

When running the vapor image in an Ubuntu 14.04 Docker image w/ the Swift 3.0.2 RELEASE toolchain, and error "Illegal Instruction" gets thrown when trying to create the SMTP client.

let client = try SMTPClient<TCPClientStream>.makeGmailClient()

The packages installed in the Docker images are:
build-essential wget clang-3.6 curl libedit-dev python2.7 python2.7-dev libicu52 rsync libxml2 git

[BUG] Query parameters are not included in Requests

Query parameters are not included in the requests when uri doesn't have any.

  • Create a request: client.request(.get, "http://localhost", query: ["key": "value"])

Expected Behaviour:

  • Request query should contain ["key": "value"].

Current Behaviour:

  • Request query is nil.

Code involved:

Responder+Helpers.swift

public func request(
        _ method: Method,
        _ uri: String,
        query: [String: NodeRepresentable] = [:],
        _ headers: [HeaderKey: String] = [:],
        _ body: BodyRepresentable? = nil,
        through middleware: [Middleware] = []
    ) throws  -> Response {
        let uri = try URI(uri)
    
        let req = Request(method: method, uri: uri)
        req.headers = headers
        
        for (key, value) in query {
            try req.query?.set(key, value)
        }
        
        if let body = body {
            req.body = body.makeBody()
        }
        return try respond(to: req, through: middleware)
    }

Note:

This works if the uri contains already a query parameter (for example: client.request(.get, "http://localhost?foo=bar", query: ["key": "value"])), because of the Request extension in:

Request+FormURLEncoded.swift

public var query: Node?

WebSocket error with multiple client over SSL

We encounter an openssl error that kill all sockets when a second web socket client connect to our server:

Transport Layer Security Error: 123145522679880:error:140C5042:SSL routines:ssl_undefined_function:called a function you should not call:ssl_lib.c:2799:

The server is initialized as follow:

        let publicCert = Bundle.main.path(forResource: "publicCert", ofType: "pem")!
        let privateKey = Bundle.main.path(forResource: "privateKey", ofType: "pem")!
        
        self.tlsContext = try! TLS.Context(
            .server,
            .files(
                certificateFile: publicCert,
                privateKeyFile: privateKey,
                signature: .selfSigned
            ),
            verifyHost: true,
            verifyCertificates: false
        )
        let tcp = try TCPInternetSocket(scheme: "https", hostname:"127.0.0.1", port: port)
        let tls = TLS.InternetSocket(tcp, self.tlsContext)
        let  server = try TLSServer(tls, listenMax: 128)

And we upgrade to a web socket as follow:

    func respond(to request: Request) throws -> Response {
            return try request.upgradeToWebSocket {  ws in
                ....
            }
    }

If we use a Async server, the server crashed in AsyncServerWorker.swift at line 36:

       readSource.setEventHandler {
            try! self.onDataAvailable(client)
        }
  • platform: macOS 10.12.6
  • xcode: Version 9.0 beta 6
  • openssl: 1.0.2l
  • vapor: 2.2

Headers should be lowercase

As per the HTTP 2.0 spec, header names should be lowercased. Currently all headers in Vapor's HeaderKey class are CamelCase.

Whilst Vapor does not currently support HTTP 2.0, if run behind Nginx or something that does, headers may be forwarded and will be invalid, so they should be made lowercase. In HTTP 1 header keys are case-insensitive so this won't introduce any issues.

(You could argue it is the responsibility of the proxy to lowercase everything but better to be safe!)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.