izqui / Taylor

A lightweight library for writing HTTP web servers with Swift
MIT License
926 stars 79 forks source link

Request Body is empty when using Safari #2

Closed izqui closed 9 years ago

izqui commented 9 years ago

Continues happening...

robertoseidenberg commented 9 years ago

This also happens when sending data from iOS to a Taylor instance using the below code. The body data seems to get lost on CocoaAsyncSocket level already. Sending body data using Paw REST client seem to work fine, though. Paw uses a "Connection": "close" header when sending a request while NSMutableURLRequest appends "Connection": "keep-alive". Don't know if that is the reason though.

    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: configuration)
    let endpoint = NSURL(string: "http://127.0.0.1:3000")!
    let request = NSMutableURLRequest(URL: endpoint)

    request.HTTPMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.addValue("application/json", forHTTPHeaderField: "Accept")
    request.HTTPBody = try! NSJSONSerialization.dataWithJSONObject(["mykey": "myvalue"], options: [])

    let task = session.dataTaskWithRequest(request) { data, response, error in
      print(error)
      print(response)
      if let d = data { print(NSString(data: d, encoding: NSUTF8StringEncoding)) }
    }

    task.resume()
Danappelxx commented 9 years ago

have you tested this with the swiftsockets implementation? @izqui

izqui commented 9 years ago

Just tested it and it works just fine.

Seems to be a problem with GCDAsyncSocket.

kevinup7 commented 9 years ago

I was running into this issue in Safari when using both SwiftSockets and GCDAsyncSocket. I think I figured out what the problem is. It appears the request body is arriving later than the headers, and so the initial data being read by the socket doesn't include the request body.

This was easy to fix in GCDAsyncSocket by reading just the headers to start with, and then checking the headers and reading the body if it exists. This feels like the better approach anyway, as it's more flexible in terms of adding support for additional request body types in the future.

The issue is a little more difficult with SwiftSockets, as there's no way that I could see to read data up to a specific delimiter. I'm sure there's a better way to handle it than how I did in my pull request, but both methods appear to be working correctly now.

izqui commented 9 years ago

Thanks for the contribution @kevinup7. It appears to be working now :)