Skip to content

Commit

Permalink
NettyConnector - HOST header contains port & 307 works with buffered …
Browse files Browse the repository at this point in the history
…post

Signed-off-by: jansupol <[email protected]>
  • Loading branch information
jansupol committed Nov 13, 2024
1 parent bd6edcd commit b88e8e9
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
package org.glassfish.jersey.netty.connector;

import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -47,7 +46,6 @@
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.HttpObject;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpUtil;
import io.netty.handler.codec.http.LastHttpContent;
import io.netty.handler.timeout.IdleStateEvent;
import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
Expand Down Expand Up @@ -145,7 +143,21 @@ protected void notifyResponse() {
ClientRequest newReq = new ClientRequest(jerseyRequest);
newReq.setUri(newUri);
restrictRedirectRequest(newReq, cr);
connector.execute(newReq, redirectUriHistory, responseAvailable);

final NettyConnector newConnector = new NettyConnector(newReq.getClient());
newConnector.execute(newReq, redirectUriHistory, new CompletableFuture<ClientResponse>() {
@Override
public boolean complete(ClientResponse value) {
newConnector.close();
return responseAvailable.complete(value);
}

@Override
public boolean completeExceptionally(Throwable ex) {
newConnector.close();
return responseAvailable.completeExceptionally(ex);
}
});
}
} catch (IllegalArgumentException e) {
responseAvailable.completeExceptionally(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,14 @@ protected void initChannel(SocketChannel ch) throws Exception {

// host header - http 1.1
if (!nettyRequest.headers().contains(HttpHeaderNames.HOST)) {
nettyRequest.headers().add(HttpHeaderNames.HOST, jerseyRequest.getUri().getHost());
int requestPort = jerseyRequest.getUri().getPort();
final String hostHeader;
if (requestPort != 80 && requestPort != 443) {
hostHeader = jerseyRequest.getUri().getHost() + ":" + requestPort;
} else {
hostHeader = jerseyRequest.getUri().getHost();
}
nettyRequest.headers().add(HttpHeaderNames.HOST, hostHeader);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
Expand All @@ -24,16 +24,20 @@
import java.util.logging.Logger;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.client.ClientProperties;
import org.glassfish.jersey.client.RequestEntityProcessing;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.netty.connector.internal.RedirectException;
import org.glassfish.jersey.server.ResourceConfig;
Expand All @@ -60,6 +64,11 @@ public String get() {
return "GET";
}

@POST
public String post() {
return "POST";
}

@GET
@Path("redirect")
public Response redirect() {
Expand All @@ -77,6 +86,12 @@ public Response loop() {
public Response redirect2() {
return Response.seeOther(URI.create(TEST_URL_REF.get() + "/redirect")).build();
}

@POST
@Path("status307")
public Response status307() {
return Response.temporaryRedirect(URI.create(TEST_URL_REF.get())).build();
}
}

@Override
Expand Down Expand Up @@ -169,4 +184,15 @@ public void testRedirectNoLimitReached() {
assertEquals(200, r.getStatus());
assertEquals("GET", r.readEntity(String.class));
}

@Test
public void testRedirect307PostBuffered() {
try (Response response = target("test/status307")
.property(ClientProperties.FOLLOW_REDIRECTS, true)
.property(ClientProperties.REQUEST_ENTITY_PROCESSING, RequestEntityProcessing.BUFFERED)
.request().post(Entity.entity("Something", MediaType.TEXT_PLAIN_TYPE))) {
assertEquals(200, response.getStatus());
assertEquals("POST", response.readEntity(String.class));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
* Copyright (c) 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/

package org.glassfish.jersey.netty.connector;

import org.glassfish.jersey.client.ClientConfig;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;

public class HostHeaderTest extends JerseyTest {

private static final String HTTP_HEADER_NAME = "HTTP_PORT_INT";

@Path("/")
public static class HostHeaderTestEchoResource {
@GET
public String get(@Context HttpHeaders headers) {
String sPort = headers.getHeaderString(HTTP_HEADER_NAME);
String hostPort = headers.getHeaderString(HttpHeaders.HOST);
int indexColon = hostPort.indexOf(':');
if (indexColon != -1) {
hostPort = hostPort.substring(indexColon + 1);
}
if (sPort.equals(hostPort.trim())) {
return GET.class.getName();
} else {
return "Expected port " + sPort + " but found " + hostPort;
}
}
}

@Override
protected Application configure() {
return new ResourceConfig(HostHeaderTestEchoResource.class);
}

@Test
public void testHostHeaderAndPort() {
int port = getPort();
ClientConfig config = new ClientConfig();
config.connectorProvider(new NettyConnectorProvider());
try (Response response = ClientBuilder.newClient(config).target(target().getUri())
.request()
.header(HTTP_HEADER_NAME, port)
.get()) {
MatcherAssert.assertThat(response.getStatus(), Matchers.is(200));
MatcherAssert.assertThat(response.readEntity(String.class), Matchers.is(GET.class.getName()));
}
}

}

0 comments on commit b88e8e9

Please sign in to comment.