Skip to content

Commit

Permalink
Fix HttpServletRequest.getRemoteAddr for the HttpConnector mode
Browse files Browse the repository at this point in the history
Signed-off-by: Lachlan Roberts <[email protected]>
  • Loading branch information
lachlan-roberts committed Nov 18, 2024
1 parent b4c953a commit a54e790
Show file tree
Hide file tree
Showing 14 changed files with 409 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,18 @@
import com.google.apphosting.runtime.jetty.AppInfoFactory;
import com.google.common.base.Strings;
import com.google.common.flogger.GoogleLogger;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.time.Duration;
import java.util.Objects;
import java.util.stream.Stream;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.ConnectionMetaData;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.HostPort;

/**
* Implementation for the {@link RequestAPIData} to allow for the Jetty {@link Request} to be used
Expand Down Expand Up @@ -274,6 +278,7 @@ public JettyRequestAPIData(
traceContext =
com.google.apphosting.base.protos.TracePb.TraceContextProto.getDefaultInstance();

String finalUserIp = userIp;
this.originalRequest = request;
this.request =
new Request.Wrapper(request) {
Expand All @@ -291,6 +296,26 @@ public boolean isSecure() {
public HttpFields getHeaders() {
return fields;
}

@Override
public ConnectionMetaData getConnectionMetaData() {
return new ConnectionMetaData.Wrapper(super.getConnectionMetaData()) {
@Override
public SocketAddress getRemoteSocketAddress() {
return InetSocketAddress.createUnresolved(finalUserIp, 0);
}

@Override
public HostPort getServerAuthority() {
return new HostPort("0.0.0.0", 0);
}

@Override
public SocketAddress getLocalSocketAddress() {
return InetSocketAddress.createUnresolved("0.0.0.0", 0);
}
};
}
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,12 @@
import com.google.common.base.Strings;
import com.google.common.flogger.GoogleLogger;
import java.time.Duration;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Stream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpScheme;
Expand Down Expand Up @@ -287,6 +284,7 @@ public JettyRequestAPIData(
traceContext = TraceContextProto.getDefaultInstance();
}

String finalUserIp = userIp;
this.httpServletRequest =
new HttpServletRequestWrapper(httpServletRequest) {

Expand Down Expand Up @@ -329,6 +327,41 @@ public String getScheme() {
public boolean isSecure() {
return isSecure;
}

@Override
public String getRemoteAddr() {
return finalUserIp;
}

@Override
public String getServerName() {
return "0.0.0.0";
}

@Override
public String getRemoteHost() {
return finalUserIp;
}

@Override
public int getRemotePort() {
return 0;
}

@Override
public String getLocalName() {
return "0.0.0.0";
}

@Override
public String getLocalAddr() {
return "0.0.0.0";
}

@Override
public int getLocalPort() {
return 0;
}
};

this.baseRequest = request;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.apphosting.runtime.jetty9;

import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;

import java.util.Arrays;
import java.util.Collection;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class RemoteAddressTest extends JavaRuntimeViaHttpBase {

@Parameterized.Parameters
public static Collection<Object[]> data() {
return Arrays.asList(
new Object[][] {
{"jetty94", false},
{"jetty94", true},
{"ee8", false},
{"ee8", true},
{"ee10", false},
{"ee10", true},
});
}

@Rule public TemporaryFolder temp = new TemporaryFolder();
private final HttpClient httpClient = new HttpClient();
private final boolean httpMode;
private final String environment;
private RuntimeContext<?> runtime;

public RemoteAddressTest(String environment, boolean httpMode) {
this.environment = environment;
this.httpMode = httpMode;
System.setProperty("appengine.use.HttpConnector", Boolean.toString(httpMode));
}

@Before
public void before() throws Exception {
String app = "com/google/apphosting/runtime/jetty9/remoteaddrapp/" + environment;
copyAppToDir(app, temp.getRoot().toPath());
httpClient.start();
runtime = runtimeContext();
System.err.println("==== Using Environment: " + environment + " " + httpMode + " ====");
}

@After
public void after() throws Exception {
httpClient.stop();
runtime.close();
}

@Test
public void test() throws Exception {
String url = runtime.jettyUrl("/");
ContentResponse response = httpClient.newRequest(url)
.header("X-AppEngine-User-IP", "203.0.113.1")
.send();

assertThat(response.getStatus(), equalTo(HttpStatus.OK_200));
String contentReceived = response.getContentAsString();
assertThat(contentReceived, containsString("getRemoteAddr: 203.0.113.1"));
assertThat(contentReceived, containsString("getLocalAddr: 0.0.0.0"));
assertThat(contentReceived, containsString("getServerPort: " + runtime.getPort()));
assertThat(contentReceived, containsString("getRemotePort: 0"));
assertThat(contentReceived, containsString("getLocalPort: 0"));
assertThat(contentReceived, containsString("getServerName: 0.0.0.0"));
}

private RuntimeContext<?> runtimeContext() throws Exception {
RuntimeContext.Config<?> config =
RuntimeContext.Config.builder().setApplicationPath(temp.getRoot().toString()).build();
return RuntimeContext.create(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import java.util.Enumeration;
import org.eclipse.jetty.util.IO;

/** Servlet that prints all the system properties. */
public class EE10EchoServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.IO;

/** Servlet that prints all the system properties. */
public class EE8EchoServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.apphosting.runtime.jetty9.remoteaddrapp;

import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class EE10RemoteAddrServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
writer.println("getRemoteAddr: " + req.getRemoteAddr());
writer.println("getLocalAddr: " + req.getLocalAddr());
writer.println("getServerPort: " + req.getServerPort());
writer.println("getRemotePort: " + req.getRemotePort());
writer.println("getLocalPort: " + req.getLocalPort());
writer.println("getServerName: " + req.getServerName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright 2021 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.google.apphosting.runtime.jetty9.remoteaddrapp;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EE8RemoteAddrServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
PrintWriter writer = resp.getWriter();
writer.println("getRemoteAddr: " + req.getRemoteAddr());
writer.println("getLocalAddr: " + req.getLocalAddr());
writer.println("getServerPort: " + req.getServerPort());
writer.println("getRemotePort: " + req.getRemotePort());
writer.println("getLocalPort: " + req.getLocalPort());
writer.println("getServerName: " + req.getServerName());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@
<application>gzip</application>
<threadsafe>true</threadsafe>
<system-properties>
<property name="appengine.use.EE8" value="true"/>
<property name="appengine.use.EE8" value="false"/>
</system-properties>
</appengine-web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
<runtime>java21</runtime>
<application>remoteaddr</application>
<system-properties>
<property name="appengine.use.EE10" value="false"/>
<property name="appengine.use.EE10" value="true"/>
</system-properties>
</appengine-web-app>
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2021 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<web-app
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
metadata-complete="false"
version="3.1">
<servlet>
<servlet-name>Main</servlet-name>
<servlet-class>com.google.apphosting.runtime.jetty9.remoteaddrapp.EE10RemoteAddrServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>
Loading

0 comments on commit a54e790

Please sign in to comment.