Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-19 Thread Daniel Fuchs
On Fri, 8 Apr 2022 10:19:08 GMT, Jaikiran Pai  wrote:

>> Hello Conor,
>> 
>> I had a look at this latest update to the `Http1Request`.  The github diff 
>> isn't easy to understand/explain in this case, so I'll paste here the latest 
>> code contained in this PR, from that method. It looks like:
>> 
>> 
>> if (requestPublisher == null) {
>> // Not a user request, or maybe a method, e.g. GET, with no body.
>> contentLength = 0;
>> } else {
>> contentLength = requestPublisher.contentLength();
>> }
>> 
>> // GET, HEAD and DELETE with no request body should not set the 
>> Content-Length header
>> if (requestPublisher != null) {
>> if (contentLength == 0) {
>> systemHeadersBuilder.setHeader("Content-Length", "0");
>> } else if (contentLength > 0) {
>> systemHeadersBuilder.setHeader("Content-Length", 
>> Long.toString(contentLength));
>> streaming = false;
>> } else {
>> streaming = true;
>> systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
>> }
>> }
>> 
>> I think we don't need the additional/new ` if (requestPublisher != null)` 
>> block and can instead move the contents of this `if` block into the 
>> immediately preceding `else` block. Thinking a bit more, I think this entire 
>> above code can be reduced to just:
>> 
>> 
>> // absence of a requestPublisher indicates a request with no body, in which 
>> // case we don't explicitly set any Content-Length header
>> if (requestPublisher != null) {
>> var contentLength = requestPublisher.contentLength();
>> if (contentLength == 0) {
>> systemHeadersBuilder.setHeader("Content-Length", "0");
>> } else if (contentLength > 0) {
>> systemHeadersBuilder.setHeader("Content-Length", 
>> Long.toString(contentLength));
>> streaming = false;
>> } else {
>> streaming = true;
>> systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
>> }
>> }
>> 
>> and the previous if/else block completely deleted. The absence of a 
>> `requestPublisher` would mean a request with no body. 
>> 
>> Additionally, I noticed that the `HttpRequest.Builder` does this for `HEAD` 
>> method:
>> 
>> 
>> /**
>>  * Sets the request method of this builder to HEAD.
>>  *
>>  * @implSpec The default implementation is expected to have the same 
>> behaviour as:
>>  * {@code return method("HEAD", BodyPublishers.noBody());}
>>  *
>>  * @return this builder
>>  * @since 18
>>  */
>> default Builder HEAD() {
>> return method("HEAD", BodyPublishers.noBody());
>> }
>> 
>> This is unlike other methods, for example `DELETE()` where the body 
>> publisher itself is `null`. In the case of `HEAD` the body publisher is 
>> present but it still represents that there's no body to that request. Should 
>> we perhaps detect even this specific case (i.e. `instanceof 
>> RequestPublishers.EmptyPublisher`) and skip setting the `Content-Length` 
>> header. If we don't add this additional check, from what I see with this 
>> updated code now, we will still end up explicitly setting `Content-Length` 
>> to `0` when a `HEAD` request is generated using the 
>> `HttpRequest.Builder.HEAD()` API, since the `EmptyPublisher` will return `0` 
>> from its `contentLength()` implementation.
>
>> This is unlike other methods, for example DELETE() where the body publisher 
>> itself is null. In the case of HEAD the body publisher is present but it 
>> still represents that there's no body to that request.
> 
> Please disregard this part of the comment. As you and Daniel rightly noted in 
> a private conversation, the `HttpRequestBuilderImpl` overrides the `HEAD()` 
> method to set `null` to the body publisher.

@jaikiran @c-cleary 


// absence of a requestPublisher indicates a request with no body, in which 
// case we don't explicitly set any Content-Length header
if (requestPublisher != null) {
var contentLength = requestPublisher.contentLength();
if (contentLength == 0) {
systemHeadersBuilder.setHeader("Content-Length", "0");
} else if (contentLength > 0) {
systemHeadersBuilder.setHeader("Content-Length", 
Long.toString(contentLength));
streaming = false;
} else {
streaming = true;
systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
}
}


Sounds good to me.

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-19 Thread Daniel Fuchs
On Tue, 19 Apr 2022 16:44:35 GMT, Daniel Fuchs  wrote:

>> test/jdk/java/net/httpclient/ContentLengthHeaderTest.java line 202:
>> 
>>> 200: } else {
>>> 201: String responseBody = exchange.getRequestMethod() + " 
>>> request contained an unexpected " +
>>> 202: "Content-length header.";
>> 
>> Maybe the message could include the value of `Content-Length` that was 
>> received.
>
> Also it's always better to drain the request input stream even if there is no 
> bytes.

You could possibly do that in `handleResponse()`

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-19 Thread Daniel Fuchs
On Thu, 7 Apr 2022 13:53:35 GMT, Conor Cleary  wrote:

>> **Issue**
>> When using the `HttpClient.send()` to send a GET request created using the 
>> `HttpRequest.newBuilder()`, a `Content-length: 0` header is set. This 
>> behaviour causes issues with many services as a body related header is 
>> usually not expected to be included with a GET request. 
>> 
>> **Solution**
>> `Http1Request.java` was modified so that when the request method is a GET, a 
>> `Content-length` header is not added to the request. However, if a developer 
>> chooses to include a body in a GET request (though it is generally 
>> considered bad practice), a `Content-length` header with the appropriate 
>> value will be added.
>
> Conor Cleary has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8283544: Updated URI creation

test/jdk/java/net/httpclient/ContentLengthHeaderTest.java line 202:

> 200: } else {
> 201: String responseBody = exchange.getRequestMethod() + " 
> request contained an unexpected " +
> 202: "Content-length header.";

Maybe the message could include the value of `Content-Length` that was received.

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-19 Thread Daniel Fuchs
On Tue, 19 Apr 2022 16:43:12 GMT, Daniel Fuchs  wrote:

>> Conor Cleary has updated the pull request incrementally with one additional 
>> commit since the last revision:
>> 
>>   8283544: Updated URI creation
>
> test/jdk/java/net/httpclient/ContentLengthHeaderTest.java line 202:
> 
>> 200: } else {
>> 201: String responseBody = exchange.getRequestMethod() + " 
>> request contained an unexpected " +
>> 202: "Content-length header.";
> 
> Maybe the message could include the value of `Content-Length` that was 
> received.

Also it's always better to drain the request input stream even if there is no 
bytes.

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-08 Thread Jaikiran Pai
On Fri, 8 Apr 2022 09:35:31 GMT, Jaikiran Pai  wrote:

> This is unlike other methods, for example DELETE() where the body publisher 
> itself is null. In the case of HEAD the body publisher is present but it 
> still represents that there's no body to that request.

Please disregard this part of the comment. As you and Daniel rightly noted in a 
private conversation, the `HttpRequestBuilderImpl` overrides the `HEAD()` 
method to set `null` to the body publisher.

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-08 Thread Jaikiran Pai
On Thu, 7 Apr 2022 13:53:35 GMT, Conor Cleary  wrote:

>> **Issue**
>> When using the `HttpClient.send()` to send a GET request created using the 
>> `HttpRequest.newBuilder()`, a `Content-length: 0` header is set. This 
>> behaviour causes issues with many services as a body related header is 
>> usually not expected to be included with a GET request. 
>> 
>> **Solution**
>> `Http1Request.java` was modified so that when the request method is a GET, a 
>> `Content-length` header is not added to the request. However, if a developer 
>> chooses to include a body in a GET request (though it is generally 
>> considered bad practice), a `Content-length` header with the appropriate 
>> value will be added.
>
> Conor Cleary has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8283544: Updated URI creation

Hello Conor,

I had a look at this latest update to the `Http1Request`.  The github diff 
isn't easy to understand/explain in this case, so I'll paste here the latest 
code contained in this PR, from that method. It looks like:


if (requestPublisher == null) {
// Not a user request, or maybe a method, e.g. GET, with no body.
contentLength = 0;
} else {
contentLength = requestPublisher.contentLength();
}

// GET, HEAD and DELETE with no request body should not set the Content-Length 
header
if (requestPublisher != null) {
if (contentLength == 0) {
systemHeadersBuilder.setHeader("Content-Length", "0");
} else if (contentLength > 0) {
systemHeadersBuilder.setHeader("Content-Length", 
Long.toString(contentLength));
streaming = false;
} else {
streaming = true;
systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
}
}

I think we don't need the additional/new ` if (requestPublisher != null)` block 
and can instead move the contents of this `if` block into the immediately 
preceding `else` block. Thinking a bit more, I think this entire above code can 
be reduced to just:


// absence of a requestPublisher indicates a request with no body, in which 
// case we don't explicitly set any Content-Length header
if (requestPublisher != null) {
var contentLength = requestPublisher.contentLength();
if (contentLength == 0) {
systemHeadersBuilder.setHeader("Content-Length", "0");
} else if (contentLength > 0) {
systemHeadersBuilder.setHeader("Content-Length", 
Long.toString(contentLength));
streaming = false;
} else {
streaming = true;
systemHeadersBuilder.setHeader("Transfer-encoding", "chunked");
}
}

and the previous if/else block completely deleted. The absence of a 
`requestPublisher` would mean a request with no body. 

Additionally, I noticed that the `HttpRequest.Builder` does this for `HEAD` 
method:


/**
 * Sets the request method of this builder to HEAD.
 *
 * @implSpec The default implementation is expected to have the same behaviour 
as:
 * {@code return method("HEAD", BodyPublishers.noBody());}
 *
 * @return this builder
 * @since 18
 */
default Builder HEAD() {
return method("HEAD", BodyPublishers.noBody());
}

This is unlike other methods, for example `DELETE()` where the body publisher 
itself is `null`. In the case of `HEAD` the body publisher is present but it 
still represents that there's no body to that request. Should we perhaps detect 
even this specific case (i.e. `instanceof RequestPublishers.EmptyPublisher`) 
and skip setting the `Content-Length` header. If we don't add this additional 
check, from what I see with this updated code now, we will still end up 
explicitly setting `Content-Length` to `0` when a `HEAD` request is generated 
using the `HttpRequest.Builder.HEAD()` API, since the `EmptyPublisher` will 
return `0` from its `contentLength()` implementation.

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-08 Thread Conor Cleary
On Thu, 7 Apr 2022 13:53:35 GMT, Conor Cleary  wrote:

>> **Issue**
>> When using the `HttpClient.send()` to send a GET request created using the 
>> `HttpRequest.newBuilder()`, a `Content-length: 0` header is set. This 
>> behaviour causes issues with many services as a body related header is 
>> usually not expected to be included with a GET request. 
>> 
>> **Solution**
>> `Http1Request.java` was modified so that when the request method is a GET, a 
>> `Content-length` header is not added to the request. However, if a developer 
>> chooses to include a body in a GET request (though it is generally 
>> considered bad practice), a `Content-length` header with the appropriate 
>> value will be added.
>
> Conor Cleary has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   8283544: Updated URI creation

@Michael-Mc-Mahon @djelinski @jaikiran the src/ and test/ changes have been 
updated with reference to your comments. Seeking additional feedback if there 
is any? 

Also thanks for the previous reviews, all been very helpful!

-

PR: https://git.openjdk.java.net/jdk/pull/8017


Re: RFR: 8283544: HttpClient GET method adds Content-Length: 0 header [v5]

2022-04-07 Thread Conor Cleary
> **Issue**
> When using the `HttpClient.send()` to send a GET request created using the 
> `HttpRequest.newBuilder()`, a `Content-length: 0` header is set. This 
> behaviour causes issues with many services as a body related header is 
> usually not expected to be included with a GET request. 
> 
> **Solution**
> `Http1Request.java` was modified so that when the request method is a GET, a 
> `Content-length` header is not added to the request. However, if a developer 
> chooses to include a body in a GET request (though it is generally considered 
> bad practice), a `Content-length` header with the appropriate value will be 
> added.

Conor Cleary has updated the pull request incrementally with one additional 
commit since the last revision:

  8283544: Updated URI creation

-

Changes:
  - all: https://git.openjdk.java.net/jdk/pull/8017/files
  - new: https://git.openjdk.java.net/jdk/pull/8017/files/92d5309a..c1ef7d29

Webrevs:
 - full: https://webrevs.openjdk.java.net/?repo=jdk=8017=04
 - incr: https://webrevs.openjdk.java.net/?repo=jdk=8017=03-04

  Stats: 18 lines in 1 file changed: 7 ins; 0 del; 11 mod
  Patch: https://git.openjdk.java.net/jdk/pull/8017.diff
  Fetch: git fetch https://git.openjdk.java.net/jdk pull/8017/head:pull/8017

PR: https://git.openjdk.java.net/jdk/pull/8017