Merge remote-tracking branch 'origin/jetty-11.0.x' into jetty-12.0.x

# Conflicts:
#	jetty-ee9/jetty-ee9-servlets/src/test/java/org/eclipse/jetty/ee9/servlets/CrossOriginFilterTest.java
This commit is contained in:
gregw 2023-05-18 00:18:45 +02:00
commit 3e5d479f39
4 changed files with 200 additions and 168 deletions

View File

@ -31,6 +31,9 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -68,7 +71,7 @@ import org.slf4j.LoggerFactory;
* <p>
* The check whether the timing header is set, will be performed only if
* the user gets general access to the resource using the <b>allowedOrigins</b>.
*
* </dd>
* <dt>allowedMethods</dt>
* <dd>a comma separated list of HTTP methods that
* are allowed to be used when accessing the resources. Default value is
@ -149,17 +152,18 @@ public class CrossOriginFilter implements Filter
private static final List<String> SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
private static final List<String> DEFAULT_ALLOWED_METHODS = Arrays.asList("GET", "POST", "HEAD");
private static final List<String> DEFAULT_ALLOWED_HEADERS = Arrays.asList("X-Requested-With", "Content-Type", "Accept", "Origin");
private static final HttpField VARY_ORIGIN = new PreEncodedHttpField(HttpHeader.VARY, HttpHeader.ORIGIN.asString());
private boolean anyOriginAllowed;
private boolean anyTimingOriginAllowed;
private boolean anyHeadersAllowed;
private Set<String> allowedOrigins = new HashSet<String>();
private List<Pattern> allowedOriginPatterns = new ArrayList<Pattern>();
private Set<String> allowedTimingOrigins = new HashSet<String>();
private List<Pattern> allowedTimingOriginPatterns = new ArrayList<Pattern>();
private List<String> allowedMethods = new ArrayList<String>();
private List<String> allowedHeaders = new ArrayList<String>();
private List<String> exposedHeaders = new ArrayList<String>();
private final Set<String> allowedOrigins = new HashSet<>();
private final List<Pattern> allowedOriginPatterns = new ArrayList<>();
private final Set<String> allowedTimingOrigins = new HashSet<>();
private final List<Pattern> allowedTimingOriginPatterns = new ArrayList<>();
private final List<String> allowedMethods = new ArrayList<>();
private final List<String> allowedHeaders = new ArrayList<>();
private final List<String> exposedHeaders = new ArrayList<>();
private int preflightMaxAge;
private boolean allowCredentials;
private boolean chainPreflight;
@ -269,6 +273,7 @@ public class CrossOriginFilter implements Filter
private void handle(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
{
response.addHeader(VARY_ORIGIN.getName(), VARY_ORIGIN.getValue());
String origin = request.getHeader(ORIGIN_HEADER);
// Is it a cross origin request ?
if (origin != null && isEnabled(request))
@ -319,12 +324,12 @@ public class CrossOriginFilter implements Filter
// protocol that does not accept extra response headers on the upgrade response
for (Enumeration<String> connections = request.getHeaders("Connection"); connections.hasMoreElements(); )
{
String connection = (String)connections.nextElement();
String connection = connections.nextElement();
if ("Upgrade".equalsIgnoreCase(connection))
{
for (Enumeration<String> upgrades = request.getHeaders("Upgrade"); upgrades.hasMoreElements(); )
{
String upgrade = (String)upgrades.nextElement();
String upgrade = upgrades.nextElement();
if ("WebSocket".equalsIgnoreCase(upgrade))
return false;
}
@ -381,16 +386,12 @@ public class CrossOriginFilter implements Filter
String method = request.getMethod();
if (!"OPTIONS".equalsIgnoreCase(method))
return false;
if (request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER) == null)
return false;
return true;
return request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER) != null;
}
private void handleSimpleResponse(HttpServletRequest request, HttpServletResponse response, String origin)
{
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
//W3C CORS spec http://www.w3.org/TR/cors/#resource-implementation
response.addHeader("Vary", ORIGIN_HEADER);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
if (!exposedHeaders.isEmpty())
@ -408,9 +409,6 @@ public class CrossOriginFilter implements Filter
if (!headersAllowed)
return;
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
//W3C CORS spec http://www.w3.org/TR/cors/#resource-implementation
if (!anyOriginAllowed)
response.addHeader("Vary", ORIGIN_HEADER);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
if (preflightMaxAge > 0)
@ -440,7 +438,7 @@ public class CrossOriginFilter implements Filter
if (accessControlRequestHeaders == null)
return Collections.emptyList();
List<String> requestedHeaders = new ArrayList<String>();
List<String> requestedHeaders = new ArrayList<>();
String[] headers = StringUtil.csvSplit(accessControlRequestHeaders);
for (String header : headers)
{

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.ee10.servlets;
import java.io.IOException;
import java.io.Serial;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@ -27,6 +28,7 @@ import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.ee10.servlet.FilterHolder;
import org.eclipse.jetty.ee10.servlet.ServletContextHandler;
import org.eclipse.jetty.ee10.servlet.ServletHolder;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.LocalConnector;
@ -74,16 +76,18 @@ public class CrossOriginFilterTest
final CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.get(HttpHeader.VARY), is(HttpHeader.ORIGIN.asString()));
}
@Test
@ -98,12 +102,13 @@ public class CrossOriginFilterTest
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String otherOrigin = StringUtil.replace(origin, "localhost", "127.0.0.1");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: " + otherOrigin + "\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: %s\r
\r
""".formatted(otherOrigin);
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -322,12 +327,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -351,12 +357,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"PUT / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
PUT / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -380,12 +387,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"OPTIONS / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
OPTIONS / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -456,12 +464,13 @@ public class CrossOriginFilterTest
assertTrue(latch.await(1, TimeUnit.SECONDS));
// Preflight request was ok, now make the actual request
request =
"PUT / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
request = """
PUT / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
rawResponse = connector.getResponse(request);
response = HttpTester.parseResponse(rawResponse);
@ -483,14 +492,17 @@ public class CrossOriginFilterTest
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
// Preflight request
String request =
"OPTIONS / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER + ": DELETE\r\n" +
CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS_HEADER + ": origin,x-custom,x-requested-with\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
OPTIONS / HTTP/1.1\r
Host: localhost\r
Connection: close\r
%s: DELETE\r
%s: origin,x-custom,x-requested-with\r
Origin: http://localhost\r
\r
""".formatted(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER,
CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS_HEADER);
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -505,14 +517,15 @@ public class CrossOriginFilterTest
assertTrue(latch.await(1, TimeUnit.SECONDS));
// Preflight request was ok, now make the actual request
request =
"DELETE / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"X-Custom: value\r\n" +
"X-Requested-With: local\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
request = """
DELETE / HTTP/1.1\r
Host: localhost\r
Connection: close\r
X-Custom: value\r
X-Requested-With: local\r
Origin: http://localhost\r
\r
""";
rawResponse = connector.getResponse(request);
response = HttpTester.parseResponse(rawResponse);
@ -561,13 +574,14 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: WebSocket\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: Upgrade\r
Upgrade: WebSocket\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -588,12 +602,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -633,6 +648,7 @@ public class CrossOriginFilterTest
public static class ResourceServlet extends HttpServlet
{
@Serial
private static final long serialVersionUID = 1L;
private final CountDownLatch latch;

View File

@ -31,6 +31,10 @@ import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.ee9.nested.Response;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PreEncodedHttpField;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -68,7 +72,7 @@ import org.slf4j.LoggerFactory;
* <p>
* The check whether the timing header is set, will be performed only if
* the user gets general access to the resource using the <b>allowedOrigins</b>.
*
* </dd>
* <dt>allowedMethods</dt>
* <dd>a comma separated list of HTTP methods that
* are allowed to be used when accessing the resources. Default value is
@ -149,17 +153,18 @@ public class CrossOriginFilter implements Filter
private static final List<String> SIMPLE_HTTP_METHODS = Arrays.asList("GET", "POST", "HEAD");
private static final List<String> DEFAULT_ALLOWED_METHODS = Arrays.asList("GET", "POST", "HEAD");
private static final List<String> DEFAULT_ALLOWED_HEADERS = Arrays.asList("X-Requested-With", "Content-Type", "Accept", "Origin");
private static final HttpField VARY_ORIGIN = new PreEncodedHttpField(HttpHeader.VARY, HttpHeader.ORIGIN.asString());
private boolean anyOriginAllowed;
private boolean anyTimingOriginAllowed;
private boolean anyHeadersAllowed;
private Set<String> allowedOrigins = new HashSet<String>();
private List<Pattern> allowedOriginPatterns = new ArrayList<Pattern>();
private Set<String> allowedTimingOrigins = new HashSet<String>();
private List<Pattern> allowedTimingOriginPatterns = new ArrayList<Pattern>();
private List<String> allowedMethods = new ArrayList<String>();
private List<String> allowedHeaders = new ArrayList<String>();
private List<String> exposedHeaders = new ArrayList<String>();
private final Set<String> allowedOrigins = new HashSet<>();
private final List<Pattern> allowedOriginPatterns = new ArrayList<>();
private final Set<String> allowedTimingOrigins = new HashSet<>();
private final List<Pattern> allowedTimingOriginPatterns = new ArrayList<>();
private final List<String> allowedMethods = new ArrayList<>();
private final List<String> allowedHeaders = new ArrayList<>();
private final List<String> exposedHeaders = new ArrayList<>();
private int preflightMaxAge;
private boolean allowCredentials;
private boolean chainPreflight;
@ -269,6 +274,10 @@ public class CrossOriginFilter implements Filter
private void handle(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException
{
if (response instanceof Response)
((Response)response).getHttpFields().add(VARY_ORIGIN);
else
response.addHeader(VARY_ORIGIN.getName(), VARY_ORIGIN.getValue());
String origin = request.getHeader(ORIGIN_HEADER);
// Is it a cross origin request ?
if (origin != null && isEnabled(request))
@ -319,12 +328,12 @@ public class CrossOriginFilter implements Filter
// protocol that does not accept extra response headers on the upgrade response
for (Enumeration<String> connections = request.getHeaders("Connection"); connections.hasMoreElements(); )
{
String connection = (String)connections.nextElement();
String connection = connections.nextElement();
if ("Upgrade".equalsIgnoreCase(connection))
{
for (Enumeration<String> upgrades = request.getHeaders("Upgrade"); upgrades.hasMoreElements(); )
{
String upgrade = (String)upgrades.nextElement();
String upgrade = upgrades.nextElement();
if ("WebSocket".equalsIgnoreCase(upgrade))
return false;
}
@ -381,16 +390,12 @@ public class CrossOriginFilter implements Filter
String method = request.getMethod();
if (!"OPTIONS".equalsIgnoreCase(method))
return false;
if (request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER) == null)
return false;
return true;
return request.getHeader(ACCESS_CONTROL_REQUEST_METHOD_HEADER) != null;
}
private void handleSimpleResponse(HttpServletRequest request, HttpServletResponse response, String origin)
{
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
//W3C CORS spec http://www.w3.org/TR/cors/#resource-implementation
response.addHeader("Vary", ORIGIN_HEADER);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
if (!exposedHeaders.isEmpty())
@ -408,9 +413,6 @@ public class CrossOriginFilter implements Filter
if (!headersAllowed)
return;
response.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, origin);
//W3C CORS spec http://www.w3.org/TR/cors/#resource-implementation
if (!anyOriginAllowed)
response.addHeader("Vary", ORIGIN_HEADER);
if (allowCredentials)
response.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER, "true");
if (preflightMaxAge > 0)
@ -440,7 +442,7 @@ public class CrossOriginFilter implements Filter
if (accessControlRequestHeaders == null)
return Collections.emptyList();
List<String> requestedHeaders = new ArrayList<String>();
List<String> requestedHeaders = new ArrayList<>();
String[] headers = StringUtil.csvSplit(accessControlRequestHeaders);
for (String header : headers)
{

View File

@ -14,6 +14,7 @@
package org.eclipse.jetty.ee9.servlets;
import java.io.IOException;
import java.io.Serial;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@ -27,6 +28,7 @@ import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.ee9.servlet.FilterHolder;
import org.eclipse.jetty.ee9.servlet.ServletContextHandler;
import org.eclipse.jetty.ee9.servlet.ServletHolder;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.LocalConnector;
@ -74,16 +76,18 @@ public class CrossOriginFilterTest
final CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertTrue(latch.await(1, TimeUnit.SECONDS));
assertThat(response.toString(), response.getStatus(), is(HttpStatus.OK_200));
assertThat(response.get(HttpHeader.VARY), is(HttpHeader.ORIGIN.asString()));
}
@Test
@ -98,12 +102,13 @@ public class CrossOriginFilterTest
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String otherOrigin = StringUtil.replace(origin, "localhost", "127.0.0.1");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: " + otherOrigin + "\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: %s\r
\r
""".formatted(otherOrigin);
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -322,12 +327,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -351,12 +357,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"PUT / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
PUT / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -380,12 +387,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"OPTIONS / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
OPTIONS / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -456,12 +464,13 @@ public class CrossOriginFilterTest
assertTrue(latch.await(1, TimeUnit.SECONDS));
// Preflight request was ok, now make the actual request
request =
"PUT / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
request = """
PUT / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
rawResponse = connector.getResponse(request);
response = HttpTester.parseResponse(rawResponse);
@ -483,14 +492,17 @@ public class CrossOriginFilterTest
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
// Preflight request
String request =
"OPTIONS / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER + ": DELETE\r\n" +
CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS_HEADER + ": origin,x-custom,x-requested-with\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
OPTIONS / HTTP/1.1\r
Host: localhost\r
Connection: close\r
%s: DELETE\r
%s: origin,x-custom,x-requested-with\r
Origin: http://localhost\r
\r
""".formatted(CrossOriginFilter.ACCESS_CONTROL_REQUEST_METHOD_HEADER,
CrossOriginFilter.ACCESS_CONTROL_REQUEST_HEADERS_HEADER);
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -505,14 +517,15 @@ public class CrossOriginFilterTest
assertTrue(latch.await(1, TimeUnit.SECONDS));
// Preflight request was ok, now make the actual request
request =
"DELETE / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"X-Custom: value\r\n" +
"X-Requested-With: local\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
request = """
DELETE / HTTP/1.1\r
Host: localhost\r
Connection: close\r
X-Custom: value\r
X-Requested-With: local\r
Origin: http://localhost\r
\r
""";
rawResponse = connector.getResponse(request);
response = HttpTester.parseResponse(rawResponse);
@ -561,13 +574,14 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: Upgrade\r\n" +
"Upgrade: WebSocket\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: Upgrade\r
Upgrade: WebSocket\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -588,12 +602,13 @@ public class CrossOriginFilterTest
CountDownLatch latch = new CountDownLatch(1);
context.addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
String request =
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"Connection: close\r\n" +
"Origin: http://localhost\r\n" +
"\r\n";
String request = """
GET / HTTP/1.1\r
Host: localhost\r
Connection: close\r
Origin: http://localhost\r
\r
""";
String rawResponse = connector.getResponse(request);
HttpTester.Response response = HttpTester.parseResponse(rawResponse);
@ -633,6 +648,7 @@ public class CrossOriginFilterTest
public static class ResourceServlet extends HttpServlet
{
@Serial
private static final long serialVersionUID = 1L;
private final CountDownLatch latch;