Skip to content

Commit acc317e

Browse files
authored
merge of the actual 2.x into the 3.0
2 parents 24ef916 + 17f0b35 commit acc317e

File tree

18 files changed

+452
-91
lines changed

18 files changed

+452
-91
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
@@ -18,7 +18,6 @@
1818

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

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

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,7 @@ protected void initChannel(SocketChannel ch) throws Exception {
416416
// headers
417417
if (!jerseyRequest.hasEntity()) {
418418
setHeaders(jerseyRequest, nettyRequest.headers(), false);
419-
420-
// host header - http 1.1
421-
if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
422-
nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
423-
}
419+
setHostHeader(jerseyRequest, nettyRequest);
424420
}
425421

426422
if (jerseyRequest.hasEntity()) {
@@ -468,9 +464,7 @@ public void operationComplete(io.netty.util.concurrent.Future<? super Void> futu
468464
@Override
469465
public OutputStream getOutputStream(int contentLength) throws IOException {
470466
replaceHeaders(jerseyRequest, nettyRequest.headers()); // WriterInterceptor changes
471-
if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
472-
nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
473-
}
467+
setHostHeader(jerseyRequest, nettyRequest);
474468
headersSet.countDown();
475469

476470
return entityWriter.getOutputStream();
@@ -620,4 +614,18 @@ private static HttpHeaders replaceHeaders(ClientRequest jerseyRequest, HttpHeade
620614
private static boolean additionalProxyHeadersToKeep(String key) {
621615
return key.length() > 2 && (key.charAt(0) == 'x' || key.charAt(0) == 'X') && (key.charAt(1) == '-');
622616
}
617+
618+
private static void setHostHeader(ClientRequest jerseyRequest, HttpRequest nettyRequest) {
619+
// host header - http 1.1
620+
if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
621+
int requestPort = jerseyRequest.getUri().getPort();
622+
final String hostHeader;
623+
if (requestPort != 80 && requestPort != 443) {
624+
hostHeader = jerseyRequest.getUri().getHost() + ":" + requestPort;
625+
} else {
626+
hostHeader = jerseyRequest.getUri().getHost();
627+
}
628+
nettyRequest.headers().add(HttpHeaderNames.HOST, hostHeader);
629+
}
630+
}
623631
}

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 jakarta.ws.rs.GET;
27+
import jakarta.ws.rs.POST;
2728
import jakarta.ws.rs.Path;
2829
import jakarta.ws.rs.ProcessingException;
2930
import jakarta.ws.rs.client.Client;
3031
import jakarta.ws.rs.client.ClientBuilder;
32+
import jakarta.ws.rs.client.Entity;
3133
import jakarta.ws.rs.client.WebTarget;
3234
import jakarta.ws.rs.core.Application;
35+
import jakarta.ws.rs.core.MediaType;
3336
import jakarta.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: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
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 jakarta.ws.rs.GET;
27+
import jakarta.ws.rs.POST;
28+
import jakarta.ws.rs.Path;
29+
import jakarta.ws.rs.client.ClientBuilder;
30+
import jakarta.ws.rs.client.Entity;
31+
import jakarta.ws.rs.core.Application;
32+
import jakarta.ws.rs.core.Context;
33+
import jakarta.ws.rs.core.HttpHeaders;
34+
import jakarta.ws.rs.core.MediaType;
35+
import jakarta.ws.rs.core.Response;
36+
37+
public class HostHeaderTest extends JerseyTest {
38+
39+
private static final String HTTP_HEADER_NAME = "HTTP_PORT_INT";
40+
41+
@Path("/")
42+
public static class HostHeaderTestEchoResource {
43+
44+
@POST
45+
public String post(@Context HttpHeaders headers) {
46+
return get(headers);
47+
}
48+
49+
@GET
50+
public String get(@Context HttpHeaders headers) {
51+
String sPort = headers.getHeaderString(HTTP_HEADER_NAME);
52+
String hostPort = headers.getHeaderString(HttpHeaders.HOST);
53+
int indexColon = hostPort.indexOf(':');
54+
if (indexColon != -1) {
55+
hostPort = hostPort.substring(indexColon + 1);
56+
}
57+
if (sPort.equals(hostPort.trim())) {
58+
return GET.class.getName();
59+
} else {
60+
return "Expected port " + sPort + " but found " + hostPort;
61+
}
62+
}
63+
}
64+
65+
@Override
66+
protected Application configure() {
67+
return new ResourceConfig(HostHeaderTestEchoResource.class);
68+
}
69+
70+
@Test
71+
public void testHostHeaderAndPort() {
72+
int port = getPort();
73+
ClientConfig config = new ClientConfig();
74+
config.connectorProvider(new NettyConnectorProvider());
75+
try (Response response = ClientBuilder.newClient(config).target(target().getUri())
76+
.request()
77+
.header(HTTP_HEADER_NAME, port)
78+
.get()) {
79+
MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
80+
MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
81+
}
82+
}
83+
84+
@Test
85+
public void testHostHeaderAndPortAfterRemovedFromFilter() {
86+
int port = getPort();
87+
ClientConfig config = new ClientConfig();
88+
config.connectorProvider(new NettyConnectorProvider());
89+
try (Response response = ClientBuilder.newClient(config)
90+
.target(target().getUri())
91+
.request()
92+
.header(HTTP_HEADER_NAME, port)
93+
.post(Entity.entity("xxx", MediaType.TEXT_PLAIN_TYPE))) {
94+
MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
95+
MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
96+
}
97+
}
98+
99+
}

core-common/pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@
316316
</goals>
317317
</execution>
318318
<execution>
319-
<!-- Compile these files with jdk 8 and put them aside to be included in multirelase jar -->
319+
<!-- Compile these files with jdk 8 and put them aside to be included in multi-release jar -->
320320
<!-- Multi-release jar is built by jdk 11+, but these classes are buildable by jdk 8 only -->
321321
<id>compile-2-java8</id>
322322
<phase>process-resources</phase>
@@ -495,10 +495,10 @@
495495
<goal>copy-resources</goal>
496496
</goals>
497497
<configuration>
498-
<outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/11/org/glassfish/jersey/internal/jsr166</outputDirectory>
498+
<outputDirectory>${project.build.directory}/generated-sources/rsrc-gen/META-INF/versions/11/org/glassfish/jersey</outputDirectory>
499499
<resources>
500500
<resource>
501-
<directory>${java11.sourceDirectory}/org/glassfish/jersey/internal/jsr166</directory>
501+
<directory>${java11.sourceDirectory}/org/glassfish/jersey</directory>
502502
</resource>
503503
</resources>
504504
</configuration>

core-common/src/main/java/org/glassfish/jersey/internal/inject/ParamConverters.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023 Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024 Oracle and/or its affiliates. All rights reserved.
33
* Copyright (c) 2018 Payara Foundation and/or its affiliates.
44
*
55
* This program and the accompanying materials are made available under the
@@ -121,7 +121,7 @@ public String toString(final T value) throws IllegalArgumentException {
121121
@Singleton
122122
public static class StringConstructor extends ParamConverterCompliance implements ParamConverterProvider {
123123

124-
private StringConstructor(boolean canReturnNull) {
124+
protected StringConstructor(boolean canReturnNull) {
125125
super(canReturnNull);
126126
}
127127

@@ -150,7 +150,7 @@ protected T _fromString(final String value) throws Exception {
150150
@Singleton
151151
public static class TypeValueOf extends ParamConverterCompliance implements ParamConverterProvider {
152152

153-
private TypeValueOf(boolean canReturnNull) {
153+
protected TypeValueOf(boolean canReturnNull) {
154154
super(canReturnNull);
155155
}
156156

@@ -178,7 +178,7 @@ public T _fromString(final String value) throws Exception {
178178
@Singleton
179179
public static class TypeFromString extends ParamConverterCompliance implements ParamConverterProvider {
180180

181-
private TypeFromString(boolean canReturnNull) {
181+
protected TypeFromString(boolean canReturnNull) {
182182
super(canReturnNull);
183183
}
184184

@@ -206,7 +206,7 @@ public T _fromString(final String value) throws Exception {
206206
@Singleton
207207
public static class TypeFromStringEnum extends TypeFromString {
208208

209-
private TypeFromStringEnum(boolean canReturnNull) {
209+
protected TypeFromStringEnum(boolean canReturnNull) {
210210
super(canReturnNull);
211211
}
212212

@@ -221,7 +221,7 @@ public <T> ParamConverter<T> getConverter(final Class<T> rawType,
221221
@Singleton
222222
public static class CharacterProvider extends ParamConverterCompliance implements ParamConverterProvider {
223223

224-
private CharacterProvider(boolean canReturnNull) {
224+
protected CharacterProvider(boolean canReturnNull) {
225225
super(canReturnNull);
226226
}
227227

@@ -266,7 +266,7 @@ public String toString(T value) {
266266
@Singleton
267267
public static class DateProvider extends ParamConverterCompliance implements ParamConverterProvider {
268268

269-
private DateProvider(boolean canReturnNull) {
269+
protected DateProvider(boolean canReturnNull) {
270270
super(canReturnNull);
271271
}
272272

@@ -309,7 +309,7 @@ public static class OptionalCustomProvider extends ParamConverterCompliance impl
309309
// Delegates to this provider when the type of Optional is extracted.
310310
private final InjectionManager manager;
311311

312-
public OptionalCustomProvider(InjectionManager manager, boolean canReturnNull) {
312+
protected OptionalCustomProvider(InjectionManager manager, boolean canReturnNull) {
313313
super(canReturnNull);
314314
this.manager = manager;
315315
}
@@ -365,6 +365,8 @@ public String toString(T value) throws IllegalArgumentException {
365365
@Singleton
366366
public static class OptionalProvider implements ParamConverterProvider {
367367

368+
protected OptionalProvider() {}
369+
368370
@Override
369371
public <T> ParamConverter<T> getConverter(Class<T> rawType, Type genericType, Annotation[] annotations) {
370372
final Optionals optionals = Optionals.getOptional(rawType);

0 commit comments

Comments
 (0)