Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HttpClient removes Content-Length and causes 411 #656

Open
sherwinzadeh opened this issue Jan 19, 2023 · 2 comments
Open

HttpClient removes Content-Length and causes 411 #656

sherwinzadeh opened this issue Jan 19, 2023 · 2 comments

Comments

@sherwinzadeh
Copy link

When attempting to make GET calls with Django based server, I'm getting a 411 Length Required. Looking at the code in RequestValidation.swift, it is removing Content-Length from headers for GET calls. This may be according to specs but it appears that some servers still require this (probably set to 0). There should be some way to override this behavior or to cause it to force Content-Length to appear in the headers.

I have worked around this by implementing my own networking code using URLSession and the calls do work since I can control the headers exactly.

For reference, the code that is causing the problem is here:

    private mutating func setTransportFraming(
        method: HTTPMethod,
        bodyLength: RequestBodyLength
    ) {
        self.remove(name: "Content-Length")
        self.remove(name: "Transfer-Encoding")

        switch bodyLength {
        case .known(0):
            // if we don't have a body we might not need to send the Content-Length field
            // https://tools.ietf.org/html/rfc7230#section-3.3.2
            switch method {
            case .GET, .HEAD, .DELETE, .CONNECT, .TRACE:
                // A user agent SHOULD NOT send a Content-Length header field when the request
                // message does not contain a payload body and the method semantics do not
                // anticipate such a body.
                break
            default:
                // A user agent SHOULD send a Content-Length in a request message when
                // no Transfer-Encoding is sent and the request method defines a meaning
                // for an enclosed payload body.
                self.add(name: "Content-Length", value: "0")
            }
        case .known(let length):
            self.add(name: "Content-Length", value: String(length))
        case .unknown:
            self.add(name: "Transfer-Encoding", value: "chunked")
        }
    }
@Lukasa
Copy link
Collaborator

Lukasa commented Jan 19, 2023

Wow, that's pretty wild. This is a Django-based server? It's news to me that Django misbehaves in this way.

We'd certainly be happy to accept a patch to add a configuration option to disable the transport framing validation.

@sherwinzadeh
Copy link
Author

sherwinzadeh commented Jan 19, 2023

Just a little more insight, I tried adding a body using code like this (this is a Vapor project):

	let headers = HTTPHeaders([
		("Authorization", authorization),
		("User-Agent", "Zohar/1.0"),
		("Content-Type", "application/json"),
		("Accept", "application/json")
	])
	let clientResponse = try await req.client.get(uri, headers: headers, beforeSend: { clientRequest in
		clientRequest.body = ByteBuffer(string: "{}")
	})

And it went from returning a 411 to returning a 400 and complaining about the body.

The odd thing is that in URLSession, it works if I don't pass Content-Length either. I wonder if URLSession is adding it? What could be the difference between how HttpClient does it and URLSession does it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants