Skip to content

Commit b231664

Browse files
jansupolsenivam
authored andcommitted
NettyConnector - HOST header contains port & 307 works with buffered post
Signed-off-by: jansupol <[email protected]>
1 parent bd6edcd commit b231664

File tree

4 files changed

+125
-5
lines changed

4 files changed

+125
-5
lines changed

connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/JerseyClientHandler.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.glassfish.jersey.netty.connector;
1818

1919
import java.io.IOException;
20-
import java.io.InputStream;
2120
import java.net.URI;
2221
import java.util.Iterator;
2322
import java.util.List;
@@ -47,7 +46,6 @@
4746
import io.netty.handler.codec.http.HttpContent;
4847
import io.netty.handler.codec.http.HttpObject;
4948
import io.netty.handler.codec.http.HttpResponse;
50-
import io.netty.handler.codec.http.HttpUtil;
5149
import io.netty.handler.codec.http.LastHttpContent;
5250
import io.netty.handler.timeout.IdleStateEvent;
5351
import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
@@ -145,7 +143,21 @@ protected void notifyResponse() {
145143
ClientRequest newReq = new ClientRequest(jerseyRequest);
146144
newReq.setUri(newUri);
147145
restrictRedirectRequest(newReq, cr);
148-
connector.execute(newReq, redirectUriHistory, responseAvailable);
146+
147+
final NettyConnector newConnector = new NettyConnector(newReq.getClient());
148+
newConnector.execute(newReq, redirectUriHistory, new CompletableFuture<ClientResponse>() {
149+
@Override
150+
public boolean complete(ClientResponse value) {
151+
newConnector.close();
152+
return responseAvailable.complete(value);
153+
}
154+
155+
@Override
156+
public boolean completeExceptionally(Throwable ex) {
157+
newConnector.close();
158+
return responseAvailable.completeExceptionally(ex);
159+
}
160+
});
149161
}
150162
} catch (IllegalArgumentException e) {
151163
responseAvailable.completeExceptionally(

connectors/netty-connector/src/main/java/org/glassfish/jersey/netty/connector/NettyConnector.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,14 @@ protected void initChannel(SocketChannel ch) throws Exception {
418418

419419
// host header - http 1.1
420420
if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
421-
nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
421+
int requestPort = jerseyRequest.getUri().getPort();
422+
final String hostHeader;
423+
if (requestPort != 80 && requestPort != 443) {
424+
hostHeader = jerseyRequest.getUri().getHost() + ":" + requestPort;
425+
} else {
426+
hostHeader = jerseyRequest.getUri().getHost();
427+
}
428+
nettyRequest.headers().add(HttpHeaderNames.HOST, hostHeader);
422429
}
423430
}
424431

connectors/netty-connector/src/test/java/org/glassfish/jersey/netty/connector/FollowRedirectsTest.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -24,16 +24,20 @@
2424
import java.util.logging.Logger;
2525

2626
import javax.ws.rs.GET;
27+
import javax.ws.rs.POST;
2728
import javax.ws.rs.Path;
2829
import javax.ws.rs.ProcessingException;
2930
import javax.ws.rs.client.Client;
3031
import javax.ws.rs.client.ClientBuilder;
32+
import javax.ws.rs.client.Entity;
3133
import javax.ws.rs.client.WebTarget;
3234
import javax.ws.rs.core.Application;
35+
import javax.ws.rs.core.MediaType;
3336
import javax.ws.rs.core.Response;
3437

3538
import org.glassfish.jersey.client.ClientConfig;
3639
import org.glassfish.jersey.client.ClientProperties;
40+
import org.glassfish.jersey.client.RequestEntityProcessing;
3741
import org.glassfish.jersey.logging.LoggingFeature;
3842
import org.glassfish.jersey.netty.connector.internal.RedirectException;
3943
import org.glassfish.jersey.server.ResourceConfig;
@@ -60,6 +64,11 @@ public String get() {
6064
return "GET";
6165
}
6266

67+
@POST
68+
public String post() {
69+
return "POST";
70+
}
71+
6372
@GET
6473
@Path("redirect")
6574
public Response redirect() {
@@ -77,6 +86,12 @@ public Response loop() {
7786
public Response redirect2() {
7887
return Response.seeOther(URI.create(TEST_URL_REF.get() + "/redirect")).build();
7988
}
89+
90+
@POST
91+
@Path("status307")
92+
public Response status307() {
93+
return Response.temporaryRedirect(URI.create(TEST_URL_REF.get())).build();
94+
}
8095
}
8196

8297
@Override
@@ -169,4 +184,15 @@ public void testRedirectNoLimitReached() {
169184
assertEquals(200, r.getStatus());
170185
assertEquals("GET", r.readEntity(String.class));
171186
}
187+
188+
@Test
189+
public void testRedirect307PostBuffered() {
190+
try (Response response = target("test/status307")
191+
.property(ClientProperties.FOLLOW_REDIRECTS, true)
192+
.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
193+
.request().post(Entity.entity("Something", MediaType.TEXT_PLAIN_TYPE))) {
194+
assertEquals(200, response.getStatus());
195+
assertEquals("POST", response.readEntity(String.class));
196+
}
197+
}
172198
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.jersey.netty.connector;
18+
19+
import org.glassfish.jersey.client.ClientConfig;
20+
import org.glassfish.jersey.server.ResourceConfig;
21+
import org.glassfish.jersey.test.JerseyTest;
22+
import org.hamcrest.MatcherAssert;
23+
import org.hamcrest.Matchers;
24+
import org.junit.jupiter.api.Test;
25+
26+
import javax.ws.rs.GET;
27+
import javax.ws.rs.Path;
28+
import javax.ws.rs.client.ClientBuilder;
29+
import javax.ws.rs.core.Application;
30+
import javax.ws.rs.core.Context;
31+
import javax.ws.rs.core.HttpHeaders;
32+
import javax.ws.rs.core.Response;
33+
34+
public class HostHeaderTest extends JerseyTest {
35+
36+
private static final String HTTP_HEADER_NAME = "HTTP_PORT_INT";
37+
38+
@Path("/")
39+
public static class HostHeaderTestEchoResource {
40+
@GET
41+
public String get(@Context HttpHeaders headers) {
42+
String sPort = headers.getHeaderString(HTTP_HEADER_NAME);
43+
String hostPort = headers.getHeaderString(HttpHeaders.HOST);
44+
int indexColon = hostPort.indexOf(':');
45+
if (indexColon != -1) {
46+
hostPort = hostPort.substring(indexColon + 1);
47+
}
48+
if (sPort.equals(hostPort.trim())) {
49+
return GET.class.getName();
50+
} else {
51+
return "Expected port " + sPort + " but found " + hostPort;
52+
}
53+
}
54+
}
55+
56+
@Override
57+
protected Application configure() {
58+
return new ResourceConfig(HostHeaderTestEchoResource.class);
59+
}
60+
61+
@Test
62+
public void testHostHeaderAndPort() {
63+
int port = getPort();
64+
ClientConfig config = new ClientConfig();
65+
config.connectorProvider(new NettyConnectorProvider());
66+
try (Response response = ClientBuilder.newClient(config).target(target().getUri())
67+
.request()
68+
.header(HTTP_HEADER_NAME, port)
69+
.get()) {
70+
MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
71+
MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
72+
}
73+
}
74+
75+
}

0 commit comments

Comments
 (0)