ServletHttpHandlerAdapter supports Serlvet path mapping
Issue: SPR-16155
This commit is contained in:
@@ -17,11 +17,13 @@
|
||||
package org.springframework.http.server.reactive;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.AsyncEvent;
|
||||
import javax.servlet.AsyncListener;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletRegistration;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
@@ -62,9 +64,9 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
|
||||
private int bufferSize = DEFAULT_BUFFER_SIZE;
|
||||
|
||||
@Nullable
|
||||
private String servletPath;
|
||||
|
||||
// Servlet is based on blocking I/O, hence the usage of non-direct, heap-based buffers
|
||||
// (i.e. 'false' as constructor argument)
|
||||
private DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(false);
|
||||
|
||||
|
||||
@@ -90,6 +92,18 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
return this.bufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Servlet path under which the Servlet is deployed by checking
|
||||
* the Servlet registration from {@link #init(ServletConfig)}.
|
||||
* @return the path, or an empty string if the Servlet is deployed without
|
||||
* a prefix (i.e. "/" or "/*"), or {@code null} if this method is invoked
|
||||
* before the {@link #init(ServletConfig)} Servlet container callback.
|
||||
*/
|
||||
@Nullable
|
||||
public String getServletPath() {
|
||||
return this.servletPath;
|
||||
}
|
||||
|
||||
public void setDataBufferFactory(DataBufferFactory dataBufferFactory) {
|
||||
Assert.notNull(dataBufferFactory, "DataBufferFactory must not be null");
|
||||
this.dataBufferFactory = dataBufferFactory;
|
||||
@@ -100,7 +114,40 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
}
|
||||
|
||||
|
||||
// The Servlet.service method
|
||||
// Servlet methods...
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) {
|
||||
this.servletPath = getServletPath(config);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getServletPath(ServletConfig config) {
|
||||
String name = config.getServletName();
|
||||
ServletRegistration registration = config.getServletContext().getServletRegistration(name);
|
||||
Assert.notNull(registration, "ServletRegistration not found for Servlet '" + name + "'.");
|
||||
|
||||
Collection<String> mappings = registration.getMappings();
|
||||
if (mappings.size() == 1) {
|
||||
String mapping = mappings.iterator().next();
|
||||
if (mapping.equals("/")) {
|
||||
return "";
|
||||
}
|
||||
if (mapping.endsWith("/*")) {
|
||||
String path = mapping.substring(0, mapping.length() - 2);
|
||||
if (!path.isEmpty()) {
|
||||
logger.info("Found Servlet mapping '" + path + "' for Servlet '" + name + "'.");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Expected a single Servlet mapping -- " +
|
||||
"either the default Servlet mapping (i.e. '/'), " +
|
||||
"or a path based mapping (e.g. '/*', '/foo/*'). " +
|
||||
"Actual mappings: " + mappings + " for Servlet '" + name + "'.");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void service(ServletRequest request, ServletResponse response) throws IOException {
|
||||
@@ -121,21 +168,24 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
this.httpHandler.handle(httpRequest, httpResponse).subscribe(subscriber);
|
||||
}
|
||||
|
||||
protected ServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context) throws IOException {
|
||||
protected ServerHttpRequest createRequest(HttpServletRequest request, AsyncContext context)
|
||||
throws IOException {
|
||||
|
||||
Assert.notNull(this.servletPath, "servletPath is not initialized.");
|
||||
|
||||
return new ServletServerHttpRequest(
|
||||
request, context, getDataBufferFactory(), getBufferSize());
|
||||
request, context, this.servletPath, getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
|
||||
protected ServerHttpResponse createResponse(HttpServletResponse response, AsyncContext context) throws IOException {
|
||||
return new ServletServerHttpResponse(
|
||||
response, context, getDataBufferFactory(), getBufferSize());
|
||||
protected ServerHttpResponse createResponse(HttpServletResponse response, AsyncContext context)
|
||||
throws IOException {
|
||||
|
||||
return new ServletServerHttpResponse(response, context, getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
|
||||
|
||||
// Other Servlet methods...
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig config) {
|
||||
public String getServletInfo() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,11 +194,6 @@ public class ServletHttpHandlerAdapter implements Servlet {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServletInfo() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ class ServletServerHttpRequest extends AbstractServerHttpRequest {
|
||||
|
||||
|
||||
public ServletServerHttpRequest(HttpServletRequest request, AsyncContext asyncContext,
|
||||
DataBufferFactory bufferFactory, int bufferSize) throws IOException {
|
||||
String servletPath, DataBufferFactory bufferFactory, int bufferSize) throws IOException {
|
||||
|
||||
super(initUri(request), request.getContextPath(), initHeaders(request));
|
||||
super(initUri(request), request.getContextPath() + servletPath, initHeaders(request));
|
||||
|
||||
Assert.notNull(bufferFactory, "'bufferFactory' must not be null");
|
||||
Assert.isTrue(bufferSize > 0, "'bufferSize' must be higher than 0");
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.apache.catalina.connector.CoyoteOutputStream;
|
||||
import org.springframework.core.io.buffer.DataBuffer;
|
||||
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||
import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link ServletHttpHandlerAdapter} extension that uses Tomcat APIs for reading
|
||||
@@ -42,18 +43,25 @@ import org.springframework.core.io.buffer.DataBufferUtils;
|
||||
@WebServlet(asyncSupported = true)
|
||||
public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
|
||||
|
||||
public TomcatHttpHandlerAdapter(HttpHandler httpHandler) {
|
||||
super(httpHandler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected ServerHttpRequest createRequest(HttpServletRequest request, AsyncContext cxt) throws IOException {
|
||||
return new TomcatServerHttpRequest(request, cxt, getDataBufferFactory(), getBufferSize());
|
||||
protected ServerHttpRequest createRequest(HttpServletRequest request, AsyncContext asyncContext)
|
||||
throws IOException {
|
||||
|
||||
Assert.notNull(getServletPath(), "servletPath is not initialized.");
|
||||
return new TomcatServerHttpRequest(request, asyncContext, getServletPath(),
|
||||
getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ServerHttpResponse createResponse(HttpServletResponse response, AsyncContext cxt) throws IOException {
|
||||
protected ServerHttpResponse createResponse(HttpServletResponse response, AsyncContext cxt)
|
||||
throws IOException {
|
||||
|
||||
return new TomcatServerHttpResponse(response, cxt, getDataBufferFactory(), getBufferSize());
|
||||
}
|
||||
|
||||
@@ -61,9 +69,9 @@ public class TomcatHttpHandlerAdapter extends ServletHttpHandlerAdapter {
|
||||
private final class TomcatServerHttpRequest extends ServletServerHttpRequest {
|
||||
|
||||
public TomcatServerHttpRequest(HttpServletRequest request, AsyncContext context,
|
||||
DataBufferFactory factory, int bufferSize) throws IOException {
|
||||
String servletPath, DataBufferFactory factory, int bufferSize) throws IOException {
|
||||
|
||||
super(request, context, factory, bufferSize);
|
||||
super(request, context, servletPath, factory, bufferSize);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user