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

Misleading early response warning on HTTP/1.1 HEAD/OPTIONS requests with Transfer-Encoding: chunked #4462

Open
samerdokas opened this issue Jan 30, 2025 · 3 comments
Labels
1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted t:server Issues related to the HTTP server

Comments

@samerdokas
Copy link

Consider a no-body OPTIONS request, as could be sent via curl:

curl -v -i -X OPTIONS -H 'Host: example.com' -H 'Access-Control-Request-Method: POST' -H 'Access-Control-Request-Headers: content-type' -H 'sec-fetch-mode: cors' -H 'sec-fetch-site: cross-site' -H 'sec-fetch-dest: empty' -H 'transfer-encoding: chunked' --http1.1 https://example.com/example

This request does satisfy the OPTIONS requirement of not having a body:

  • no body (--data or similar) is specified in the curl invocation
  • the client, be it curl (in this simple example), Safari or whatever else, will immediately send a chunk data size of 0.

As described in RFC9112

The chunked transfer coding is complete when a chunk with a chunk-size of zero is received, possibly followed by a trailer section, and finally terminated by an empty line.

or MDN HTTP Reference:

The terminating chunk is a zero-length chunk.

As such, any application that does HEAD/OPTIONS handling will typically not attempt to read the request body when handling these methods. Unfortunately, doing complete() on this kind of a request will generate the

Sending an 2xx 'early' response before end of request for https://example.com/example received... Note that the connection will be closed after this response. Also, many clients will not read early responses! Consider only issuing this response after the request data has been completely read!

every time, essentially generating worthless warnings. Note that there is no method logged, so there is no way to workaround this by filtering away only the warnings related to HEAD/OPTIONS.

@johanandren johanandren added 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted t:server Issues related to the HTTP server labels Jan 30, 2025
@johanandren
Copy link
Member

Can you share an example server route that reproduces this?

@samerdokas
Copy link
Author

samerdokas commented Jan 30, 2025

That would be the simplest route that does not attempt to read any content, e.g.

val route =
    path("example") {
      options {
        complete(StatusCodes.NoContent)
      }
    }

If Transfer-Encoding: chunked is not used, this route will not produce any warnings.

For completeness, here's a full runnable class:

import akka.actor.ActorSystem
import akka.http.scaladsl.Http
import akka.http.scaladsl.model.StatusCodes
import akka.http.scaladsl.server.Directives._


object Main {
  implicit val system = ActorSystem("early-2xx")

  private val route =
    path("example") {
      options {
        complete(StatusCodes.NoContent)
      }
    }

  def main(args: Array[String]): Unit = {
    Http().newServerAt("127.0.0.1", 8181).bindFlow(route)
  }
}

@johanandren
Copy link
Member

Thanks, surprising indeed that the options directive does not "consume", I'd say that is the issue, was expecting something like a lower level request handler not discarding the request entity stream.

A probable fix that should get rid of the incorrect log is to change the options directive to consume the (empty) content stream.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted t:server Issues related to the HTTP server
Projects
None yet
Development

No branches or pull requests

2 participants