-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Review HttpClient Request header APIs #4808
Comments
See also #577. |
Introduced: * Request Request.headers(Consumer<HttpFields.Mutable>). This allows applications to modify the headers, and chain calls. It also delegates the precise semantic of put/add/remove/clear to HttpFields, so there is no API duplication. * HttpRequest.header(HttpField) to efficiently add fields while normalizing the request (only used in implementation). * HttpResponse.header(HttpField) to efficiently add fields while parsing the response (only used in implementation). This pairs with HttpResponse.trailer(HttpField). * HttpResponse.headers(Consumer<HttpFields.Mutable>) to modify the fields after they have been populated (only used in tests). Removed: * Request.[set,add,put,remove], replaced by headers(Consumer<HttpFields.Mutable>). Deprecated: * Request.header(String, String) * Request.header(HttpHeader, String) Both replaced by headers(Consumer<HttpFields.Mutable>) with clearer semantic for add/put/remove. All the rest is code cleanup to remove the usage of the deprecated header() methods. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
Fixed test failures. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
I was initially a bit nervous at the removal of some APIs, like But the replacement just feels and looks better. Old example Request request = client.newRequest(uri)
.path("/")
.method(method);
if (clientClose)
request.header(HttpHeader.CONNECTION, "close");
else if (serverClose)
request.header("X-Close", "true"); New way Request request = client.newRequest(uri)
.path("/")
.method(method)
.headers((fields) -> {
if (clientClose)
fields.put(HttpHeader.CONNECTION, "close");
else if (serverClose)
fields.put("X-Close", "true");
}); |
Updates after review. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
…ient_header_api Fixes #4808 - Review HttpClient Request header APIs.
For some reason, Request.getHeaders() returned HttpFields, but HttpRequest.getHeaders() returned HttpFields.Mutable, and it was obviously wrong. Fixed WebSocket code that was relying on this API error. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
New API is counterintuitive and doesn't fit overall style. Then why query parameters still |
Why it is counterintuitive? It gives you full access to the
Because the values require special encoding that 99.9% of the developers forget, so Jetty does it for them. |
It is counterintuitive because:
I'm would like has simple client.newRequest("http://localhost:8080")
.method("GET")
.param("search", textSearch)
.header("X-app-log-metrics", "true")
.header("X-app-client-id", clientId)
.send() vs client.newRequest("http://localhost:8080")
.method("GET")
.param("search", textSearch)
.headers( (headers) -> {
headers.put("X-app-log-metrics", "true")
headers.put("X-app-client-id", clientId)
})
.send() I think it is longer and more text to read. It "breaks" chain of common methods. Don't get me wrong - I just would like an old way to be here too.
client.newRequest("http://localhost:8080")
.method("GET")
.param("search", textSearch)
.headers(CommonHeaders::add)
.params(context::qparams)
.send() |
Read the first comment. We cannot support only super-simple examples, we have to support all use cases. I don't understand your last example -- things seems more complicated and less clear just to be "chain like". The goal is to provide clear and precise functionalities for all use cases, with little code duplication. In your last example, it is not clear what happens to You may have a point about |
Jetty version
10.0.x
Description
In light of #4773 and #4777, the client
Request.header()
API should be reviewed.Currently, there is only one API:
header(String, String)
.This has the problem that there is no semantic for add/put (i.e. add the header, or replace the header), there is no semantic for remove (you have to pass a
null
value), and it's not optimal if you already have the pre-computedHttpField
.So perhaps the API should just expose a
HttpFields.Mutable
to let application have all the needed semantic (without repeating them inRequest
) - however this has the problem that it will break the API fluency (since a Request.headers() method would returnHttpFields.Mutable
, notRequest
so fluent chaining won't be possible).@gregw thoughts?
The text was updated successfully, but these errors were encountered: