Open fgaule opened 7 years ago
You can set a custom server:
EmbeddedServers.add(EmbeddedServers.Identifiers.JETTY, new EmbeddedJettyFactory((i, j, k) -> {
Server server = new Server();
return server;
}));
Please reopen if context-path doesn't work with this appraoch.
Hi @tipsy When you try to configure a handler for jetty containing a context path, it doesn't work. To configure a contextPath you need to add a handler to jetty: http://www.eclipse.org/jetty/documentation/9.3.x/embedding-jetty.html
public class OneServletContext
{
public static void main( String[] args ) throws Exception
{
Server server = new Server(8080);
ServletContextHandler context = new ServletContextHandler(
ServletContextHandler.SESSIONS);
context.setContextPath("/this-is-my-path");
server.setHandler(context);
server.start();
server.join();
}
}
It seems that Spark creates other handler (spark.embeddedserver.jetty.JettyHandler) overriding the one i have created with its contextPath.
Does this make sense?
Yeah, I checked the code, you're right.
In case it's useful to someone else here's a more complete example of configuring a custom context path. I don't know if this is the best way to do it but it seems to work. My use case for this is running a Spark application behind nginx so that it shares a hostname with other content/applications.
In addition to wrapping Spark's handler in a ServletContextHandler we also need to strip the context path prefix off the path used for routing. As a convenience for anyone connecting to the backend application directly (for development, debugging etc) I also like to add a redirect from / to the context-path.
static void contextPath(String path) {
if (path == null || path.isEmpty() || path.equals("/")) {
return;
}
EmbeddedServers.add(EmbeddedServers.Identifiers.JETTY, new EmbeddedJettyFactory() {
@Override
public EmbeddedServer create(Routes routeMatcher, StaticFilesConfiguration staticFilesConfiguration, boolean hasMultipleHandler) {
// Spark uses the full ServletRequest.getRequestURI() rather than a context relative path like
// getPathInfo as the path for routing so we must wrap the request and strip the context path
// off the front of it.
MatcherFilter matcherFilter = new MatcherFilter(routeMatcher, staticFilesConfiguration, false, hasMultipleHandler);
matcherFilter.init(null);
JettyHandler handler = new JettyHandler(matcherFilter) {
@Override
public void doHandle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
request = new HttpServletRequestWrapper(request) {
@Override
public String getRequestURI() {
return super.getRequestURI().substring(path.length());
}
};
super.doHandle(target, baseRequest, request, response);
}
};
ServletContextHandler servletContextHandler = new ServletContextHandler();
servletContextHandler.setContextPath(path);
servletContextHandler.setHandler(handler);
// For convenience also install a redirect from / to the context path
HandlerWrapper wrapper = new HandlerWrapper() {
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (target.equals("/")) {
response.sendRedirect(path);
} else {
super.handle(target, baseRequest, request, response);
}
}
};
wrapper.setHandler(servletContextHandler);
// unfortunately JettyServer is package-private so we have to duplicate it
return new EmbeddedJettyServer(new JettyServerFactory() {
@Override
public Server create(int i, int j, int k) {
// XXX: we're ignoring the the thread limits
return new Server();
}
@Override
public Server create(ThreadPool threadPool) {
return new Server(threadPool);
}
}, wrapper);
}
});
}
Using jetty, you can set a global context path for your application by calling:
How can this be done with the embedded jetty provided by Spark?