Perfect-HTTPServer icon indicating copy to clipboard operation
Perfect-HTTPServer copied to clipboard

Content-Length header is incorrect for some responses generated with .setBody()

Open ghost opened this issue 7 years ago • 3 comments

We're seeing an issue with Perfect-HTTP 3.1.6 where the Content-Length header is set incorrectly for some limited amount of responses (generated using response.setBody() ). In each case the reported content length is larger by 8 (for an empty response Content-Length was 8, for an empty json "{}" the reported length was 10).

We use the following code for success and failure cases, unfortunately the issue is very sporadic, hard to reproduce but nonetheless worrisome and trips up the client parsing.

response.setBody(string: error).completed(status: .badRequest)

try response.setBody(json: responseData)
if let responseETag = responseETag {
    response.addHeader(.eTag, value: "\"\(responseETag)\"")
}
response.completed(status: toReponseStatus())

Example client parsing issue:

NetworkManager.swift:141 WARNING: > Server Request Error: Response could not be serialized, input data was nil or zero length.
NetworkManager.swift:142 WARNING: > Request: GET (redacted)
NetworkManager.swift:143 WARNING: > Headers:
NetworkManager.swift:147 WARNING: > Body: 
NetworkManager.swift:148 WARNING: > Response: 200
NetworkManager.swift:149 WARNING: > Headers:
NetworkManager.swift:151 WARNING: >   Date: (redacted)
NetworkManager.swift:151 WARNING: >   Server: (redacted)
NetworkManager.swift:151 WARNING: >   Content-Encoding: deflate
NetworkManager.swift:151 WARNING: >   x-request-id: (redacted)
NetworkManager.swift:151 WARNING: >   Content-Length: 8
NetworkManager.swift:153 WARNING: > Body: (empty)
NetworkManager.swift:688 WARNING: Request failed: responseSerializationFailed(reason: Alamofire.AFError.ResponseSerializationFailureReason.inputDataNilOrZeroLength)

ghost avatar Dec 05 '18 00:12 ghost

It looks like a conflict with the response compression filter. If you disable that does the problem resolve? If so, can you paste in your code for adding the routes & compression filter?

kjessup avatar Dec 05 '18 19:12 kjessup

I appreciate the response. I wonder if you guys have a stress testing code that could be used to tease this out? Unfortunately the issue is very sporadic on our side so it's hard to reproduce/confirm.

Here are the snippets of code that we use on the server, based on one of the past revisions of https://perfect.org/docs/

allRoutes.forEach {
    routes.add(method: $0.method, uri: $0.uri, handler: $0.getHandler())
}
routes.add(routes)
let compressFilter = try PerfectHTTPServer.HTTPFilter.contentCompression(data: [:])
httpServer.setRequestFilters([(httplogger, .high)])
httpServer.setResponseFilters([(httplogger, .low), (compressFilter, .high)])

Thanks!

ghost avatar Dec 05 '18 21:12 ghost

The compressor running for empty and very small response bodies is problematic. I have corrected this in HTTPServer 3.0.19 (just now). I'm not sure if this is the cause of your problem, but it may help make things clearer. 8 bytes is the proper length for a "compressed" empty body, but you should no longer see that if you update the package.

Please let me know if you see any change after updating.

kjessup avatar Dec 06 '18 16:12 kjessup