private ServletChain createHandler( final DeploymentInfo deploymentInfo, final ServletHandler targetServlet, final Map<DispatcherType, List<ManagedFilter>> noExtension, final String servletPath, final boolean defaultServlet) { final ServletChain initialHandler; if (noExtension.isEmpty()) { initialHandler = servletChain( targetServlet, targetServlet.getManagedServlet(), servletPath, deploymentInfo, defaultServlet); } else { FilterHandler handler = new FilterHandler( noExtension, deploymentInfo.isAllowNonStandardWrappers(), targetServlet); initialHandler = servletChain( handler, targetServlet.getManagedServlet(), servletPath, deploymentInfo, defaultServlet); } return initialHandler; }
@Test public void testReplaceServletHandlerWithServlet() throws Exception { ServletContextHandler context = new ServletContextHandler(); context.addServlet(TestServlet.class, "/test"); context.setContextPath("/"); _server.setHandler(context); _server.start(); StringBuffer request = new StringBuffer(); request.append("GET /test HTTP/1.0\n"); request.append("Host: localhost\n"); request.append("\n"); String response = _connector.getResponses(request.toString()); assertResponseContains("Test", response); context.stop(); ServletHandler srvHnd = new ServletHandler(); srvHnd.addServletWithMapping(HelloServlet.class, "/hello"); context.setServletHandler(srvHnd); context.start(); request = new StringBuffer(); request.append("GET /hello HTTP/1.0\n"); request.append("Host: localhost\n"); request.append("\n"); response = _connector.getResponses(request.toString()); assertResponseContains("Hello World", response); }
@Test public void testFallThrough() throws Exception { HandlerList list = new HandlerList(); _server.setHandler(list); ServletContextHandler root = new ServletContextHandler(list, "/", ServletContextHandler.SESSIONS); ServletHandler servlet = root.getServletHandler(); servlet.setEnsureDefaultServlet(false); servlet.addServletWithMapping(HelloServlet.class, "/hello/*"); list.addHandler( new AbstractHandler() { @Override public void handle( String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.sendError(404, "Fell Through"); } }); _server.start(); String response = _connector.getResponses("GET /hello HTTP/1.0\r\n\r\n"); Assert.assertThat(response, Matchers.containsString("200 OK")); response = _connector.getResponses("GET /other HTTP/1.0\r\n\r\n"); Assert.assertThat(response, Matchers.containsString("404 Fell Through")); }
/** @since servlet-api-3.0 */ @Override public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) { if (isStarted()) throw new IllegalStateException(); if (filterName == null || "".equals(filterName.trim())) throw new IllegalStateException("Missing filter name"); if (!_enabled) throw new UnsupportedOperationException(); final ServletHandler handler = ServletContextHandler.this.getServletHandler(); FilterHolder holder = handler.getFilter(filterName); if (holder == null) { // new filter holder = handler.newFilterHolder(Source.JAVAX_API); holder.setName(filterName); holder.setFilter(filter); handler.addFilter(holder); return holder.getRegistration(); } if (holder.getClassName() == null && holder.getHeldClass() == null) { // preliminary filter registration completion holder.setFilter(filter); return holder.getRegistration(); } else return null; // existing filter }
/** @since servlet-api-3.0 */ @Override public ServletRegistration.Dynamic addServlet( String servletName, Class<? extends Servlet> servletClass) { if (!isStarting()) throw new IllegalStateException(); if (servletName == null || "".equals(servletName.trim())) throw new IllegalStateException("Missing servlet name"); if (!_enabled) throw new UnsupportedOperationException(); final ServletHandler handler = ServletContextHandler.this.getServletHandler(); ServletHolder holder = handler.getServlet(servletName); if (holder == null) { // new servlet holder = handler.newServletHolder(Source.JAVAX_API); holder.setName(servletName); holder.setHeldClass(servletClass); handler.addServlet(holder); return dynamicHolderAdded(holder); } // complete a partial registration if (holder.getClassName() == null && holder.getHeldClass() == null) { holder.setHeldClass(servletClass); return holder.getRegistration(); } else return null; // existing completed registration for servlet name }
@Before public void setUp() throws Exception { HttpConfiguration http_config = new HttpConfiguration(); http_config.setOutputBufferSize(4096); _connector = new ServerConnector(_server, new HttpConnectionFactory(http_config)); _server.setConnectors(new Connector[] {_connector}); ServletContextHandler context = new ServletContextHandler(); context.setContextPath("/ctx"); _server.setHandler(context); _servletHandler = context.getServletHandler(); ServletHolder holder = new ServletHolder(_servlet0); holder.setAsyncSupported(true); _servletHandler.addServletWithMapping(holder, "/path/*"); ServletHolder holder2 = new ServletHolder(_servlet2); holder.setAsyncSupported(true); _servletHandler.addServletWithMapping(holder2, "/path2/*"); _server.start(); _port = _connector.getLocalPort(); _owp.set(0); _oda.set(0); _read.set(0); }
/** @param servletHandler The servletHandler to set. */ public void setServletHandler(ServletHandler servletHandler) { if (isStarted()) throw new IllegalStateException("STARTED"); Handler next = null; if (_servletHandler != null) { next = _servletHandler.getHandler(); _servletHandler.setHandler(null); replaceHandler(_servletHandler, servletHandler); } _servletHandler = servletHandler; if (next != null && _servletHandler.getHandler() == null) _servletHandler.setHandler(next); relinkHandlers(); }
@Override public Map<String, ? extends FilterRegistration> getFilterRegistrations() { if (!_enabled) throw new UnsupportedOperationException(); HashMap<String, FilterRegistration> registrations = new HashMap<String, FilterRegistration>(); ServletHandler handler = ServletContextHandler.this.getServletHandler(); FilterHolder[] holders = handler.getFilters(); if (holders != null) { for (FilterHolder holder : holders) registrations.put(holder.getName(), holder.getRegistration()); } return registrations; }
/* ------------------------------------------------------------ */ protected void illegalStateIfContextStarted() { if (_servletHandler != null) { ServletContext context = _servletHandler.getServletContext(); if ((context instanceof ContextHandler.Context) && ((ContextHandler.Context) context).getContextHandler().isStarted()) throw new IllegalStateException("Started"); } }
/** * Finish constructing handlers and link them together. * * @see org.eclipse.jetty.server.handler.ContextHandler#startContext() */ @Override protected void startContext() throws Exception { ServletContainerInitializerCaller sciBean = getBean(ServletContainerInitializerCaller.class); if (sciBean != null) sciBean.start(); if (_servletHandler != null) { // Call decorators on all holders, and also on any EventListeners before // decorators are called on any other classes (like servlets and filters) if (_servletHandler.getListeners() != null) { for (ListenerHolder holder : _servletHandler.getListeners()) { _objFactory.decorate(holder.getListener()); } } } super.startContext(); // OK to Initialize servlet handler now that all relevant object trees have been started if (_servletHandler != null) _servletHandler.initialize(); }
/** * Sets up the handlers in the servlet chain. We setup a chain for every path + extension match * possibility. (i.e. if there a m path mappings and n extension mappings we have n*m chains). * * <p>If a chain consists of only the default servlet then we add it as an async handler, so that * resources can be served up directly without using blocking operations. * * <p>TODO: this logic is a bit convoluted at the moment, we should look at simplifying it */ private ServletPathMatchesData setupServletChains() { // create the default servlet ServletHandler defaultServlet = null; final ManagedServlets servlets = deployment.getServlets(); final ManagedFilters filters = deployment.getFilters(); final Map<String, ServletHandler> extensionServlets = new HashMap<>(); final Map<String, ServletHandler> pathServlets = new HashMap<>(); final Set<String> pathMatches = new HashSet<>(); final Set<String> extensionMatches = new HashSet<>(); DeploymentInfo deploymentInfo = deployment.getDeploymentInfo(); // loop through all filter mappings, and add them to the set of known paths for (FilterMappingInfo mapping : deploymentInfo.getFilterMappings()) { if (mapping.getMappingType() == FilterMappingInfo.MappingType.URL) { String path = mapping.getMapping(); if (path.equals("*")) { // UNDERTOW-95, support this non-standard filter mapping path = "/*"; } if (!path.startsWith("*.")) { pathMatches.add(path); } else { extensionMatches.add(path.substring(2)); } } } // now loop through all servlets. for (Map.Entry<String, ServletHandler> entry : servlets.getServletHandlers().entrySet()) { final ServletHandler handler = entry.getValue(); // add the servlet to the approprite path maps for (String path : handler.getManagedServlet().getServletInfo().getMappings()) { if (path.equals("/")) { // the default servlet pathMatches.add("/*"); if (defaultServlet != null) { throw UndertowServletMessages.MESSAGES.twoServletsWithSameMapping(path); } defaultServlet = handler; } else if (!path.startsWith("*.")) { // either an exact or a /* based path match if (path.isEmpty()) { path = "/"; } pathMatches.add(path); if (pathServlets.containsKey(path)) { throw UndertowServletMessages.MESSAGES.twoServletsWithSameMapping(path); } pathServlets.put(path, handler); } else { // an extension match based servlet String ext = path.substring(2); extensionMatches.add(ext); extensionServlets.put(ext, handler); } } } ServletHandler managedDefaultServlet = servlets.getServletHandler(DEFAULT_SERVLET_NAME); if (managedDefaultServlet == null) { // we always create a default servlet, even if it is not going to have any path mappings // registered managedDefaultServlet = servlets.addServlet(new ServletInfo(DEFAULT_SERVLET_NAME, DefaultServlet.class)); } if (defaultServlet == null) { // no explicit default servlet was specified, so we register our mapping pathMatches.add("/*"); defaultServlet = managedDefaultServlet; } final ServletPathMatchesData.Builder builder = ServletPathMatchesData.builder(); // we now loop over every path in the application, and build up the patches based on this path // these paths contain both /* and exact matches. for (final String path : pathMatches) { // resolve the target servlet, will return null if this is the default servlet MatchData targetServletMatch = resolveServletForPath(path, pathServlets, extensionServlets, defaultServlet); final Map<DispatcherType, List<ManagedFilter>> noExtension = new EnumMap<>(DispatcherType.class); final Map<String, Map<DispatcherType, List<ManagedFilter>>> extension = new HashMap<>(); // initalize the extension map. This contains all the filers in the noExtension map, plus // any filters that match the extension key for (String ext : extensionMatches) { extension.put(ext, new EnumMap<DispatcherType, List<ManagedFilter>>(DispatcherType.class)); } // loop over all the filters, and add them to the appropriate map in the correct order for (final FilterMappingInfo filterMapping : deploymentInfo.getFilterMappings()) { ManagedFilter filter = filters.getManagedFilter(filterMapping.getFilterName()); if (filterMapping.getMappingType() == FilterMappingInfo.MappingType.SERVLET) { if (targetServletMatch.handler != null) { if (filterMapping .getMapping() .equals( targetServletMatch.handler.getManagedServlet().getServletInfo().getName())) { addToListMap(noExtension, filterMapping.getDispatcher(), filter); } } for (Map.Entry<String, Map<DispatcherType, List<ManagedFilter>>> entry : extension.entrySet()) { ServletHandler pathServlet = targetServletMatch.handler; boolean defaultServletMatch = targetServletMatch.defaultServlet; if (defaultServletMatch && extensionServlets.containsKey(entry.getKey())) { pathServlet = extensionServlets.get(entry.getKey()); } if (filterMapping .getMapping() .equals(pathServlet.getManagedServlet().getServletInfo().getName())) { addToListMap(extension.get(entry.getKey()), filterMapping.getDispatcher(), filter); } } } else { if (filterMapping.getMapping().isEmpty() || !filterMapping.getMapping().startsWith("*.")) { if (isFilterApplicable(path, filterMapping.getMapping())) { addToListMap(noExtension, filterMapping.getDispatcher(), filter); for (Map<DispatcherType, List<ManagedFilter>> l : extension.values()) { addToListMap(l, filterMapping.getDispatcher(), filter); } } } else { addToListMap( extension.get(filterMapping.getMapping().substring(2)), filterMapping.getDispatcher(), filter); } } } // resolve any matches and add them to the builder if (path.endsWith("/*")) { String prefix = path.substring(0, path.length() - 2); // add the default non-extension match builder.addPrefixMatch( prefix, createHandler( deploymentInfo, targetServletMatch.handler, noExtension, targetServletMatch.matchedPath, targetServletMatch.defaultServlet), targetServletMatch.defaultServlet || targetServletMatch .handler .getManagedServlet() .getServletInfo() .isRequireWelcomeFileMapping()); // build up the chain for each non-extension match for (Map.Entry<String, Map<DispatcherType, List<ManagedFilter>>> entry : extension.entrySet()) { ServletHandler pathServlet = targetServletMatch.handler; String pathMatch = targetServletMatch.matchedPath; boolean defaultServletMatch = targetServletMatch.defaultServlet; if (defaultServletMatch && extensionServlets.containsKey(entry.getKey())) { defaultServletMatch = false; pathServlet = extensionServlets.get(entry.getKey()); } HttpHandler handler = pathServlet; if (!entry.getValue().isEmpty()) { handler = new FilterHandler( entry.getValue(), deploymentInfo.isAllowNonStandardWrappers(), handler); } builder.addExtensionMatch( prefix, entry.getKey(), servletChain( handler, pathServlet.getManagedServlet(), pathMatch, deploymentInfo, defaultServletMatch)); } } else if (path.isEmpty()) { // the context root match builder.addExactMatch( "/", createHandler( deploymentInfo, targetServletMatch.handler, noExtension, targetServletMatch.matchedPath, targetServletMatch.defaultServlet)); } else { // we need to check for an extension match, so paths like /exact.txt will have the correct // filter applied String lastSegment = path.substring(path.lastIndexOf('/')); if (lastSegment.contains(".")) { String ext = lastSegment.substring(lastSegment.lastIndexOf('.') + 1); if (extension.containsKey(ext)) { Map<DispatcherType, List<ManagedFilter>> extMap = extension.get(ext); builder.addExactMatch( path, createHandler( deploymentInfo, targetServletMatch.handler, extMap, targetServletMatch.matchedPath, targetServletMatch.defaultServlet)); } else { builder.addExactMatch( path, createHandler( deploymentInfo, targetServletMatch.handler, noExtension, targetServletMatch.matchedPath, targetServletMatch.defaultServlet)); } } else { builder.addExactMatch( path, createHandler( deploymentInfo, targetServletMatch.handler, noExtension, targetServletMatch.matchedPath, targetServletMatch.defaultServlet)); } } } // now setup name based mappings // these are used for name based dispatch for (Map.Entry<String, ServletHandler> entry : servlets.getServletHandlers().entrySet()) { final Map<DispatcherType, List<ManagedFilter>> filtersByDispatcher = new EnumMap<>(DispatcherType.class); for (final FilterMappingInfo filterMapping : deploymentInfo.getFilterMappings()) { ManagedFilter filter = filters.getManagedFilter(filterMapping.getFilterName()); if (filterMapping.getMappingType() == FilterMappingInfo.MappingType.SERVLET) { if (filterMapping.getMapping().equals(entry.getKey())) { addToListMap(filtersByDispatcher, filterMapping.getDispatcher(), filter); } } } if (filtersByDispatcher.isEmpty()) { builder.addNameMatch( entry.getKey(), servletChain( entry.getValue(), entry.getValue().getManagedServlet(), null, deploymentInfo, false)); } else { builder.addNameMatch( entry.getKey(), servletChain( new FilterHandler( filtersByDispatcher, deploymentInfo.isAllowNonStandardWrappers(), entry.getValue()), entry.getValue().getManagedServlet(), null, deploymentInfo, false)); } } return builder.build(); }
protected void configureHttpServer(HttpServer server) { // Favicon hack HttpContext faviconContext = new HttpContext(); faviconContext.setContextPath("/favicon.ico"); server.addContext(faviconContext); ResourceHandler faviconHandler = new ResourceHandler(); faviconContext.setResourceBase(SysConfig.getStaticDir().getRootPath()); faviconContext.addHandler(faviconHandler); faviconContext.addHandler(new NotFoundHandler()); // robots.txt hack HttpContext robotsContext = new HttpContext(); robotsContext.setContextPath("/robots.txt"); server.addContext(robotsContext); ResourceHandler robotsHandler = new ResourceHandler(); robotsContext.setResourceBase(SysConfig.getStaticDir().getRootPath()); robotsContext.addHandler(robotsHandler); robotsContext.addHandler(new NotFoundHandler()); // Dynamic content HttpContext servletContext = new HttpContext(); servletContext.setContextPath("/"); server.addContext(servletContext); ServletHandler servlets = new ServletHandler(); servletContext.addHandler(servlets); servlets.addServlet("/*", "org.wahlzeit.main.MainServlet"); servletContext.addHandler(new NotFoundHandler()); // Photos content HttpContext photosContext = new HttpContext(); photosContext.setContextPath(SysConfig.getPhotosDirAsString()); server.addContext(photosContext); ResourceHandler photosHandler = new ResourceHandler(); photosContext.setResourceBase(SysConfig.getPhotosDirAsString()); photosContext.addHandler(photosHandler); photosContext.addHandler(new NotFoundHandler()); // Static content HttpContext staticContext = new HttpContext(); staticContext.setContextPath(SysConfig.getStaticDir().getRootPath()); server.addContext(staticContext); ResourceHandler staticHandler = new ResourceHandler(); staticContext.setResourceBase(SysConfig.getStaticDir().getRootPath()); staticContext.addHandler(staticHandler); staticContext.addHandler(new NotFoundHandler()); }