Merge branch 'jetty-9.4.x' into jetty-10.0.x
This commit is contained in:
commit
972cd95ec0
|
@ -3,51 +3,47 @@
|
|||
pipeline {
|
||||
agent any
|
||||
// save some io during the build
|
||||
options { durabilityHint('PERFORMANCE_OPTIMIZED') }
|
||||
options { durabilityHint( 'PERFORMANCE_OPTIMIZED' ) }
|
||||
stages {
|
||||
stage("Parallel Stage") {
|
||||
stage( "Parallel Stage" ) {
|
||||
parallel {
|
||||
stage("Build / Test - JDK11") {
|
||||
stage( "Build / Test - JDK11" ) {
|
||||
agent {
|
||||
node { label 'linux' }
|
||||
}
|
||||
options { timeout(time: 120, unit: 'MINUTES') }
|
||||
options { timeout( time: 120, unit: 'MINUTES' ) }
|
||||
steps {
|
||||
container('jetty-build') {
|
||||
mavenBuild("jdk11", "-T3 -Pmongodb clean install", "maven3", true) // -Pautobahn
|
||||
// Collect up the jacoco execution results (only on main build)
|
||||
jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class',
|
||||
exclusionPattern: '' +
|
||||
// build tools
|
||||
'**/org/eclipse/jetty/ant/**' +
|
||||
',**/org/eclipse/jetty/maven/**' +
|
||||
',**/org/eclipse/jetty/jspc/**' +
|
||||
// example code / documentation
|
||||
',**/org/eclipse/jetty/embedded/**' +
|
||||
',**/org/eclipse/jetty/asyncrest/**' +
|
||||
',**/org/eclipse/jetty/demo/**' +
|
||||
// special environments / late integrations
|
||||
',**/org/eclipse/jetty/gcloud/**' +
|
||||
',**/org/eclipse/jetty/infinispan/**' +
|
||||
',**/org/eclipse/jetty/osgi/**' +
|
||||
',**/org/eclipse/jetty/spring/**' +
|
||||
',**/org/eclipse/jetty/http/spi/**' +
|
||||
// test classes
|
||||
',**/org/eclipse/jetty/tests/**' +
|
||||
',**/org/eclipse/jetty/test/**',
|
||||
execPattern: '**/target/jacoco.exec',
|
||||
classPattern: '**/target/classes',
|
||||
sourcePattern: '**/src/main/java'
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml,**/target/autobahntestsuite-reports/*.xml'
|
||||
timeout( time: 120, unit: 'MINUTES' ) {
|
||||
mavenBuild( "jdk11", "-T3 -Pmongodb clean install", "maven3", true ) // -Pautobahn
|
||||
// Collect up the jacoco execution results (only on main build)
|
||||
jacoco inclusionPattern: '**/org/eclipse/jetty/**/*.class',
|
||||
exclusionPattern: '' +
|
||||
// build tools
|
||||
'**/org/eclipse/jetty/ant/**' + ',**/org/eclipse/jetty/maven/**' +
|
||||
',**/org/eclipse/jetty/jspc/**' +
|
||||
// example code / documentation
|
||||
',**/org/eclipse/jetty/embedded/**' + ',**/org/eclipse/jetty/asyncrest/**' +
|
||||
',**/org/eclipse/jetty/demo/**' +
|
||||
// special environments / late integrations
|
||||
',**/org/eclipse/jetty/gcloud/**' + ',**/org/eclipse/jetty/infinispan/**' +
|
||||
',**/org/eclipse/jetty/osgi/**' + ',**/org/eclipse/jetty/spring/**' +
|
||||
',**/org/eclipse/jetty/http/spi/**' +
|
||||
// test classes
|
||||
',**/org/eclipse/jetty/tests/**' + ',**/org/eclipse/jetty/test/**',
|
||||
execPattern: '**/target/jacoco.exec',
|
||||
classPattern: '**/target/classes',
|
||||
sourcePattern: '**/src/main/java'
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
junit testResults: '**/target/surefire-reports/*.xml,**/target/invoker-reports/TEST*.xml,**/target/autobahntestsuite-reports/*.xml'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage("Build / Test - JDK14") {
|
||||
stage( "Build / Test - JDK14" ) {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
container('jetty-build') {
|
||||
container( 'jetty-build' ) {
|
||||
timeout( time: 120, unit: 'MINUTES' ) {
|
||||
mavenBuild( "jdk14", "-T3 -Pmongodb clean install", "maven3", true )
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
|
@ -57,7 +53,7 @@ pipeline {
|
|||
}
|
||||
}
|
||||
|
||||
stage("Build Javadoc") {
|
||||
stage( "Build Javadoc" ) {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
container('jetty-build') {
|
||||
|
@ -69,23 +65,34 @@ pipeline {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage( "Build Compact3" ) {
|
||||
agent { node { label 'linux' } }
|
||||
steps {
|
||||
container('jetty-build') {
|
||||
timeout( time: 30, unit: 'MINUTES' ) {
|
||||
mavenBuild( "jdk8", "-T3 -Pcompact3 clean install -DskipTests", "maven3", true )
|
||||
warnings consoleParsers: [[parserName: 'Maven'], [parserName: 'Java']]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
post {
|
||||
failure {
|
||||
slackNotif()
|
||||
}
|
||||
unstable {
|
||||
slackNotif()
|
||||
}
|
||||
fixed {
|
||||
slackNotif()
|
||||
post {
|
||||
failure {
|
||||
slackNotif()
|
||||
}
|
||||
unstable {
|
||||
slackNotif()
|
||||
}
|
||||
fixed {
|
||||
slackNotif()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def slackNotif() {
|
||||
script {
|
||||
try {
|
||||
|
@ -116,7 +123,7 @@ def slackNotif() {
|
|||
*/
|
||||
def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) {
|
||||
def localRepo = ".repository"
|
||||
def mavenOpts = '-Xms1g -Xmx4g -Djava.awt.headless=true'
|
||||
def mavenOpts = '-Xms1g -Xmx6g -Djava.awt.headless=true'
|
||||
|
||||
withMaven(
|
||||
maven: mvnName,
|
||||
|
@ -126,7 +133,7 @@ def mavenBuild(jdk, cmdline, mvnName, junitPublishDisabled) {
|
|||
mavenOpts: mavenOpts,
|
||||
mavenLocalRepo: localRepo) {
|
||||
// Some common Maven command line + provided command line
|
||||
sh "mvn -Pci -V -B -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME
|
||||
sh "mvn -Premote-session-tests -Pci -V -B -e -fae -Dmaven.test.failure.ignore=true -Djetty.testtracker.log=true $cmdline -Dunix.socket.tmp=" + env.JENKINS_HOME
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -641,6 +641,10 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
|
|||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Proxy v2 {} {}", getEndPoint(), proxyEndPoint.toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
_buffer.position(_buffer.position() + _length);
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("Proxy v2 parsing dynamic packet part is now done, upgrading to {}", _nextProtocol);
|
||||
|
@ -777,7 +781,7 @@ public class ProxyConnectionFactory extends DetectorConnectionFactory
|
|||
{
|
||||
return _tlvs != null ? _tlvs.get(type) : null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void close(Throwable cause)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://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:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
|
||||
/**
|
||||
* <p>Customizer that extracts the real local and remote address:port pairs from a {@link ProxyConnectionFactory}
|
||||
* and sets them on the request with {@link ServletRequest#setAttribute(String, Object)}.
|
||||
*/
|
||||
public class ProxyCustomizer implements HttpConfiguration.Customizer
|
||||
{
|
||||
/**
|
||||
* The remote address attribute name.
|
||||
*/
|
||||
public static final String REMOTE_ADDRESS_ATTRIBUTE_NAME = "org.eclipse.jetty.proxy.remote.address";
|
||||
|
||||
/**
|
||||
* The remote port attribute name.
|
||||
*/
|
||||
public static final String REMOTE_PORT_ATTRIBUTE_NAME = "org.eclipse.jetty.proxy.remote.port";
|
||||
|
||||
/**
|
||||
* The local address attribute name.
|
||||
*/
|
||||
public static final String LOCAL_ADDRESS_ATTRIBUTE_NAME = "org.eclipse.jetty.proxy.local.address";
|
||||
|
||||
/**
|
||||
* The local port attribute name.
|
||||
*/
|
||||
public static final String LOCAL_PORT_ATTRIBUTE_NAME = "org.eclipse.jetty.proxy.local.port";
|
||||
|
||||
@Override
|
||||
public void customize(Connector connector, HttpConfiguration channelConfig, Request request)
|
||||
{
|
||||
EndPoint endPoint = request.getHttpChannel().getEndPoint();
|
||||
if (endPoint instanceof ProxyConnectionFactory.ProxyEndPoint)
|
||||
{
|
||||
EndPoint underlyingEndpoint = ((ProxyConnectionFactory.ProxyEndPoint)endPoint).unwrap();
|
||||
request.setAttributes(new ProxyAttributes(underlyingEndpoint.getRemoteAddress(), underlyingEndpoint.getLocalAddress(), request.getAttributes()));
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProxyAttributes extends Attributes.Wrapper
|
||||
{
|
||||
private final InetSocketAddress remoteAddress;
|
||||
private final InetSocketAddress localAddress;
|
||||
|
||||
private ProxyAttributes(InetSocketAddress remoteAddress, InetSocketAddress localAddress, Attributes attributes)
|
||||
{
|
||||
super(attributes);
|
||||
this.remoteAddress = remoteAddress;
|
||||
this.localAddress = localAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(String name)
|
||||
{
|
||||
switch (name)
|
||||
{
|
||||
case REMOTE_ADDRESS_ATTRIBUTE_NAME:
|
||||
return remoteAddress.getAddress().getHostAddress();
|
||||
case REMOTE_PORT_ATTRIBUTE_NAME:
|
||||
return remoteAddress.getPort();
|
||||
case LOCAL_ADDRESS_ATTRIBUTE_NAME:
|
||||
return localAddress.getAddress().getHostAddress();
|
||||
case LOCAL_PORT_ATTRIBUTE_NAME:
|
||||
return localAddress.getPort();
|
||||
default:
|
||||
return super.getAttribute(name);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getAttributeNameSet()
|
||||
{
|
||||
Set<String> names = new HashSet<>(_attributes.getAttributeNameSet());
|
||||
names.add(REMOTE_ADDRESS_ATTRIBUTE_NAME);
|
||||
names.add(REMOTE_PORT_ATTRIBUTE_NAME);
|
||||
names.add(LOCAL_ADDRESS_ATTRIBUTE_NAME);
|
||||
names.add(LOCAL_PORT_ATTRIBUTE_NAME);
|
||||
return names;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -151,6 +151,39 @@ public class ProxyConnectionTest
|
|||
assertThat(response, Matchers.containsString("remote=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff:12345"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestProcessors")
|
||||
public void testLocalV2(RequestProcessor p) throws Exception
|
||||
{
|
||||
String proxy =
|
||||
// Preamble
|
||||
"0D0A0D0A000D0A515549540A" +
|
||||
|
||||
// V2, LOCAL
|
||||
"20" +
|
||||
|
||||
// 0x1 : AF_INET 0x1 : STREAM.
|
||||
"11" +
|
||||
|
||||
// Address length is 16.
|
||||
"0010" +
|
||||
|
||||
// gibberish
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
||||
;
|
||||
String http = "GET /path HTTP/1.1\n" +
|
||||
"Host: server:80\n" +
|
||||
"Connection: close\n" +
|
||||
"\n";
|
||||
|
||||
String response = p.sendRequestWaitingForResponse(TypeUtil.fromHexString(proxy), http.getBytes(StandardCharsets.US_ASCII));
|
||||
|
||||
assertThat(response, Matchers.containsString("HTTP/1.1 200"));
|
||||
assertThat(response, Matchers.containsString("pathInfo=/path"));
|
||||
assertThat(response, Matchers.containsString("local=0.0.0.0:0"));
|
||||
assertThat(response, Matchers.containsString("remote=0.0.0.0:0"));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("requestProcessors")
|
||||
public void testMissingField(RequestProcessor p) throws Exception
|
||||
|
|
|
@ -0,0 +1,178 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2020 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under
|
||||
// the terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://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:
|
||||
// the Apache License v2.0 which is available at
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
public class ProxyCustomizerTest
|
||||
{
|
||||
private Server server;
|
||||
|
||||
private ProxyResponse sendProxyRequest(String proxyAsHexString, String rawHttp) throws IOException
|
||||
{
|
||||
try (Socket socket = new Socket(server.getURI().getHost(), server.getURI().getPort()))
|
||||
{
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(TypeUtil.fromHexString(proxyAsHexString));
|
||||
output.write(rawHttp.getBytes(StandardCharsets.UTF_8));
|
||||
output.flush();
|
||||
socket.shutdownOutput();
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
while (true)
|
||||
{
|
||||
String line = reader.readLine();
|
||||
if (line == null)
|
||||
break;
|
||||
sb.append(line).append("\r\n");
|
||||
}
|
||||
|
||||
return new ProxyResponse((InetSocketAddress)socket.getLocalSocketAddress(), (InetSocketAddress)socket.getRemoteSocketAddress(), sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static class ProxyResponse
|
||||
{
|
||||
private final InetSocketAddress localSocketAddress;
|
||||
private final InetSocketAddress remoteSocketAddress;
|
||||
private final String httpResponse;
|
||||
|
||||
public ProxyResponse(InetSocketAddress localSocketAddress, InetSocketAddress remoteSocketAddress, String httpResponse)
|
||||
{
|
||||
this.localSocketAddress = localSocketAddress;
|
||||
this.remoteSocketAddress = remoteSocketAddress;
|
||||
this.httpResponse = httpResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception
|
||||
{
|
||||
Handler handler = new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
response.addHeader("preexisting.attribute", request.getAttribute("some.attribute").toString());
|
||||
ArrayList<String> attributeNames = Collections.list(request.getAttributeNames());
|
||||
Collections.sort(attributeNames);
|
||||
response.addHeader("attributeNames", String.join(",", attributeNames));
|
||||
|
||||
response.addHeader("localAddress", request.getLocalAddr() + ":" + request.getLocalPort());
|
||||
response.addHeader("remoteAddress", request.getRemoteAddr() + ":" + request.getRemotePort());
|
||||
Object localAddress = request.getAttribute(ProxyCustomizer.LOCAL_ADDRESS_ATTRIBUTE_NAME);
|
||||
if (localAddress != null)
|
||||
response.addHeader("proxyLocalAddress", localAddress.toString() + ":" + request.getAttribute(ProxyCustomizer.LOCAL_PORT_ATTRIBUTE_NAME));
|
||||
Object remoteAddress = request.getAttribute(ProxyCustomizer.REMOTE_ADDRESS_ATTRIBUTE_NAME);
|
||||
if (remoteAddress != null)
|
||||
response.addHeader("proxyRemoteAddress", remoteAddress.toString() + ":" + request.getAttribute(ProxyCustomizer.REMOTE_PORT_ATTRIBUTE_NAME));
|
||||
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
};
|
||||
|
||||
server = new Server();
|
||||
HttpConfiguration httpConfiguration = new HttpConfiguration();
|
||||
httpConfiguration.addCustomizer((connector, channelConfig, request) -> request.setAttribute("some.attribute", "some value"));
|
||||
httpConfiguration.addCustomizer(new ProxyCustomizer());
|
||||
ServerConnector connector = new ServerConnector(server, new ProxyConnectionFactory(), new HttpConnectionFactory(httpConfiguration));
|
||||
server.addConnector(connector);
|
||||
server.setHandler(handler);
|
||||
server.start();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() throws Exception
|
||||
{
|
||||
server.stop();
|
||||
server = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProxyCustomizerWithProxyData() throws Exception
|
||||
{
|
||||
String proxy =
|
||||
// Preamble
|
||||
"0D0A0D0A000D0A515549540A" +
|
||||
// V2, PROXY
|
||||
"21" +
|
||||
// 0x1 : AF_INET 0x1 : STREAM. Address length is 2*4 + 2*2 = 12 bytes.
|
||||
"11" +
|
||||
// length of remaining header (4+4+2+2 = 12)
|
||||
"000C" +
|
||||
// uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port;
|
||||
"01010001" +
|
||||
"010100FE" +
|
||||
"3039" +
|
||||
"1F90";
|
||||
String http = "GET /1 HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n";
|
||||
|
||||
ProxyResponse response = sendProxyRequest(proxy, http);
|
||||
|
||||
assertThat(response.httpResponse, Matchers.containsString("localAddress: 1.1.0.254:8080"));
|
||||
assertThat(response.httpResponse, Matchers.containsString("remoteAddress: 1.1.0.1:12345"));
|
||||
assertThat(response.httpResponse, Matchers.containsString("proxyLocalAddress: " + response.remoteSocketAddress.getAddress().getHostAddress() + ":" + response.remoteSocketAddress.getPort()));
|
||||
assertThat(response.httpResponse, Matchers.containsString("proxyRemoteAddress: " + response.localSocketAddress.getAddress().getHostAddress() + ":" + response.localSocketAddress.getPort()));
|
||||
assertThat(response.httpResponse, Matchers.containsString("preexisting.attribute: some value"));
|
||||
assertThat(response.httpResponse, Matchers.containsString("attributeNames: org.eclipse.jetty.proxy.local.address,org.eclipse.jetty.proxy.local.port,org.eclipse.jetty.proxy.remote.address,org.eclipse.jetty.proxy.remote.port,some.attribute"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testProxyCustomizerWithoutProxyData() throws Exception
|
||||
{
|
||||
String proxy = "";
|
||||
String http = "GET /1 HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n";
|
||||
|
||||
ProxyResponse response = sendProxyRequest(proxy, http);
|
||||
|
||||
assertThat(response.httpResponse, Matchers.containsString("localAddress: " + response.remoteSocketAddress.getAddress().getHostAddress() + ":" + response.remoteSocketAddress.getPort()));
|
||||
assertThat(response.httpResponse, Matchers.containsString("remoteAddress: " + response.localSocketAddress.getAddress().getHostAddress() + ":" + response.localSocketAddress.getPort()));
|
||||
assertThat(response.httpResponse, Matchers.not(Matchers.containsString("proxyLocalAddress: ")));
|
||||
assertThat(response.httpResponse, Matchers.not(Matchers.containsString("proxyRemoteAddress: ")));
|
||||
assertThat(response.httpResponse, Matchers.containsString("preexisting.attribute: some value"));
|
||||
assertThat(response.httpResponse, Matchers.containsString("attributeNames: some.attribute"));
|
||||
}
|
||||
}
|
|
@ -216,5 +216,81 @@ public class ProxyProtocolTest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testProxyProtocolV2Local() throws Exception
|
||||
{
|
||||
start(new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
});
|
||||
|
||||
try (Socket socket = new Socket("localhost", connector.getLocalPort()))
|
||||
{
|
||||
String proxy =
|
||||
// Preamble
|
||||
"0D0A0D0A000D0A515549540A" +
|
||||
|
||||
// V2, LOCAL
|
||||
"20" +
|
||||
|
||||
// 0x1 : AF_INET 0x1 : STREAM. Address length is 2*4 + 2*2 = 12 bytes.
|
||||
"11" +
|
||||
|
||||
// length of remaining header (4+4+2+2+6+3 = 21)
|
||||
"0015" +
|
||||
|
||||
// uint32_t src_addr; uint32_t dst_addr; uint16_t src_port; uint16_t dst_port;
|
||||
"C0A80001" +
|
||||
"7f000001" +
|
||||
"3039" +
|
||||
"1F90" +
|
||||
|
||||
// NOOP value 0
|
||||
"040000" +
|
||||
|
||||
// NOOP value ABCDEF
|
||||
"040003ABCDEF";
|
||||
|
||||
String request1 =
|
||||
"GET /1 HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n";
|
||||
OutputStream output = socket.getOutputStream();
|
||||
output.write(TypeUtil.fromHexString(proxy));
|
||||
output.write(request1.getBytes(StandardCharsets.UTF_8));
|
||||
output.flush();
|
||||
|
||||
InputStream input = socket.getInputStream();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(input, StandardCharsets.UTF_8));
|
||||
String response1 = reader.readLine();
|
||||
assertTrue(response1.startsWith("HTTP/1.1 200 "));
|
||||
while (true)
|
||||
{
|
||||
if (reader.readLine().isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
// Send a second request to verify that the proxied IP is retained.
|
||||
String request2 =
|
||||
"GET /2 HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Connection: close\r\n" +
|
||||
"\r\n";
|
||||
output.write(request2.getBytes(StandardCharsets.UTF_8));
|
||||
output.flush();
|
||||
|
||||
String response2 = reader.readLine();
|
||||
assertTrue(response2.startsWith("HTTP/1.1 200 "));
|
||||
while (true)
|
||||
{
|
||||
if (reader.readLine() == null)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
12
pom.xml
12
pom.xml
|
@ -33,7 +33,7 @@
|
|||
<jmh.version>1.21</jmh.version>
|
||||
<jmhjar.name>benchmarks</jmhjar.name>
|
||||
<tycho-version>1.4.0</tycho-version>
|
||||
<junit.version>5.5.1</junit.version>
|
||||
<junit.version>5.6.2</junit.version>
|
||||
<maven.version>3.6.0</maven.version>
|
||||
<maven.resolver.version>1.3.1</maven.resolver.version>
|
||||
<weld.version>3.1.2.Final</weld.version>
|
||||
|
@ -1063,6 +1063,16 @@
|
|||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<version>1.14.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>1.14.1</version>
|
||||
</dependency>
|
||||
<!-- Old Deps -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.sessions.mongo</bundle-symbolic-name>
|
||||
<embedmongo.host>localhost</embedmongo.host>
|
||||
<!-- if changing this version please update default in MongoTestHelper you will get thanks from Eclipse IDE users -->
|
||||
<mongo.docker.version>2.2.7</mongo.docker.version>
|
||||
</properties>
|
||||
<build>
|
||||
<plugins>
|
||||
|
@ -111,13 +113,28 @@
|
|||
<artifactId>jetty-test-helper</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>testcontainers</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>mongodb</id>
|
||||
<id>remote-session-tests</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>mongodb.enabled</name>
|
||||
<name>mongo.enabled</name>
|
||||
<value>true</value>
|
||||
</property>
|
||||
</activation>
|
||||
|
@ -128,51 +145,11 @@
|
|||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<embedmongoPort>${embedmongo.port}</embedmongoPort>
|
||||
<embedmongoHost>${embedmongo.host}</embedmongoHost>
|
||||
<mongo.docker.version>${mongo.docker.version}</mongo.docker.version>
|
||||
</systemPropertyVariables>
|
||||
<skipTests>false</skipTests>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.joelittlejohn.embedmongo</groupId>
|
||||
<artifactId>embedmongo-maven-plugin</artifactId>
|
||||
<version>0.4.1</version>
|
||||
<configuration>
|
||||
<!--port>37017</port-->
|
||||
<!-- allocates a random port and overrides embedmongo.port -->
|
||||
<randomPort>true</randomPort>
|
||||
|
||||
<databaseDirectory>${project.build.directory}/mongotest</databaseDirectory>
|
||||
|
||||
<!-- optional (file|console|none), default console -->
|
||||
<logging>file</logging>
|
||||
<!-- optional, can be used when logging=file, default is ./embedmongo.log -->
|
||||
<logFile>${project.build.directory}/embedmongo.log</logFile>
|
||||
<!--optional, one of wiredTiger or mmapv1 (default is mmapv1) -->
|
||||
<!--storageEngine>wiredTiger</storageEngine-->
|
||||
<!-- optional, skips this plugin entirely, use on the command line like -Dembedmongo.skip -->
|
||||
<skip>false</skip>
|
||||
<downloadPath>https://jenkins.webtide.net/userContent/</downloadPath>
|
||||
<version>2.2.1</version>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>start</id>
|
||||
<phase>process-test-classes</phase>
|
||||
<goals>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop</id>
|
||||
<phase>test</phase>
|
||||
<goals>
|
||||
<goal>stop</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
|
|
@ -42,15 +42,16 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
*/
|
||||
public class MongoSessionDataStoreTest extends AbstractSessionDataStoreTest
|
||||
{
|
||||
|
||||
@BeforeEach
|
||||
public void beforeClass() throws Exception
|
||||
public void beforeEach() throws Exception
|
||||
{
|
||||
MongoTestHelper.dropCollection();
|
||||
MongoTestHelper.createCollection();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void afterClass() throws Exception
|
||||
public void afterEach() throws Exception
|
||||
{
|
||||
MongoTestHelper.dropCollection();
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.testcontainers.containers.GenericContainer;
|
||||
import org.testcontainers.containers.output.Slf4jLogConsumer;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
@ -45,37 +48,71 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
public class MongoTestHelper
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(MongoTestHelper.class);
|
||||
private static final Logger MONGO_LOG = LoggerFactory.getLogger("org.eclipse.jetty.nosql.mongodb.MongoLogs");
|
||||
|
||||
public static final String DB_NAME = "HttpSessions";
|
||||
public static final String COLLECTION_NAME = "testsessions";
|
||||
|
||||
static MongoClient _mongoClient;
|
||||
static GenericContainer mongo =
|
||||
new GenericContainer("mongo:" + System.getProperty("mongo.docker.version", "2.2.7"))
|
||||
.withLogConsumer(new Slf4jLogConsumer(MONGO_LOG));
|
||||
|
||||
static
|
||||
static MongoClient mongoClient;
|
||||
|
||||
public static void startMongo()
|
||||
{
|
||||
try
|
||||
{
|
||||
_mongoClient =
|
||||
new MongoClient(System.getProperty("embedmongo.host"), Integer.getInteger("embedmongoPort"));
|
||||
long start = System.currentTimeMillis();
|
||||
mongo.start();
|
||||
String containerIpAddress = mongo.getContainerIpAddress();
|
||||
int mongoPort = mongo.getMappedPort(27017);
|
||||
LOG.info("Mongo container started for {}:{} - {}ms", containerIpAddress, mongoPort,
|
||||
System.currentTimeMillis() - start);
|
||||
System.setProperty("embedmongoHost", containerIpAddress);
|
||||
System.setProperty("embedmongoPort", Integer.toString(mongoPort));
|
||||
}
|
||||
catch (UnknownHostException e)
|
||||
catch (Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
LOG.error(e.getMessage(), e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void dropCollection() throws MongoException, UnknownHostException
|
||||
public static void stopMongo()
|
||||
{
|
||||
_mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME).drop();
|
||||
mongo.stop();
|
||||
mongoClient = null;
|
||||
}
|
||||
|
||||
public static MongoClient getMongoClient() throws UnknownHostException
|
||||
{
|
||||
boolean restart = false;
|
||||
if (mongo == null || !mongo.isRunning())
|
||||
{
|
||||
startMongo();
|
||||
restart = true;
|
||||
}
|
||||
if (mongoClient == null || restart)
|
||||
{
|
||||
mongoClient = new MongoClient(System.getProperty("embedmongoHost"), Integer.getInteger("embedmongoPort"));
|
||||
}
|
||||
return mongoClient;
|
||||
}
|
||||
|
||||
public static void dropCollection() throws Exception
|
||||
{
|
||||
getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME).drop();
|
||||
}
|
||||
|
||||
public static void createCollection() throws UnknownHostException, MongoException
|
||||
{
|
||||
_mongoClient.getDB(DB_NAME).createCollection(COLLECTION_NAME, null);
|
||||
getMongoClient().getDB(DB_NAME).createCollection(COLLECTION_NAME, null);
|
||||
}
|
||||
|
||||
public static DBCollection getCollection() throws UnknownHostException, MongoException
|
||||
{
|
||||
return _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
return getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
}
|
||||
|
||||
public static MongoSessionDataStoreFactory newSessionDataStoreFactory()
|
||||
|
@ -91,7 +128,7 @@ public class MongoTestHelper
|
|||
public static boolean checkSessionExists(String id)
|
||||
throws Exception
|
||||
{
|
||||
DBCollection collection = _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
DBCollection collection = getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
|
||||
DBObject fields = new BasicDBObject();
|
||||
fields.put(MongoSessionDataStore.__EXPIRY, 1);
|
||||
|
@ -108,7 +145,7 @@ public class MongoTestHelper
|
|||
public static boolean checkSessionPersisted(SessionData data)
|
||||
throws Exception
|
||||
{
|
||||
DBCollection collection = _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
DBCollection collection = getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
|
||||
DBObject fields = new BasicDBObject();
|
||||
|
||||
|
@ -116,7 +153,7 @@ public class MongoTestHelper
|
|||
if (sessionDocument == null)
|
||||
return false; //doesn't exist
|
||||
|
||||
LOG.info("{}", sessionDocument);
|
||||
LOG.debug("{}", sessionDocument);
|
||||
|
||||
Boolean valid = (Boolean)sessionDocument.get(MongoSessionDataStore.__VALID);
|
||||
|
||||
|
@ -182,7 +219,7 @@ public class MongoTestHelper
|
|||
Map<String, Object> attributes)
|
||||
throws Exception
|
||||
{
|
||||
DBCollection collection = _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
DBCollection collection = getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
|
||||
// Form query for upsert
|
||||
BasicDBObject key = new BasicDBObject(MongoSessionDataStore.__ID, id);
|
||||
|
@ -231,7 +268,7 @@ public class MongoTestHelper
|
|||
throws Exception
|
||||
{
|
||||
|
||||
DBCollection collection = _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
DBCollection collection = getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
|
||||
// Form query for upsert
|
||||
BasicDBObject key = new BasicDBObject(MongoSessionDataStore.__ID, id);
|
||||
|
@ -277,7 +314,7 @@ public class MongoTestHelper
|
|||
throws Exception
|
||||
{
|
||||
//make old-style session to test if we can retrieve it
|
||||
DBCollection collection = _mongoClient.getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
DBCollection collection = getMongoClient().getDB(DB_NAME).getCollection(COLLECTION_NAME);
|
||||
|
||||
// Form query for upsert
|
||||
BasicDBObject key = new BasicDBObject(MongoSessionDataStore.__ID, id);
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
org.slf4j.simpleLogger.defaultLogLevel=info
|
||||
org.slf4j.simpleLogger.log.org.eclipse.jetty.nosql.mongodb.MongoLogs=error
|
||||
org.slf4j.simpleLogger.log.org.eclipse.jetty.nosql.mongodb.MongoTestHelper=info
|
Loading…
Reference in New Issue