Search in sources :

Example 46 with Wrapper

use of org.apache.catalina.Wrapper in project tomcat by apache.

the class CoyoteAdapter method postParseRequest.

// ------------------------------------------------------ Protected Methods
/**
     * Perform the necessary processing after the HTTP headers have been parsed
     * to enable the request/response pair to be passed to the start of the
     * container pipeline for processing.
     *
     * @param req      The coyote request object
     * @param request  The catalina request object
     * @param res      The coyote response object
     * @param response The catalina response object
     *
     * @return <code>true</code> if the request should be passed on to the start
     *         of the container pipeline, otherwise <code>false</code>
     *
     * @throws IOException If there is insufficient space in a buffer while
     *                     processing headers
     * @throws ServletException If the supported methods of the target servlet
     *                          cannot be determined
     */
protected boolean postParseRequest(org.apache.coyote.Request req, Request request, org.apache.coyote.Response res, Response response) throws IOException, ServletException {
    // processor hasn't set it, use the settings from the connector
    if (req.scheme().isNull()) {
        // Use connector scheme and secure configuration, (defaults to
        // "http" and false respectively)
        req.scheme().setString(connector.getScheme());
        request.setSecure(connector.getSecure());
    } else {
        // Use processor specified scheme to determine secure state
        request.setSecure(req.scheme().equals("https"));
    }
    // At this point the Host header has been processed.
    // Override if the proxyPort/proxyHost are set
    String proxyName = connector.getProxyName();
    int proxyPort = connector.getProxyPort();
    if (proxyPort != 0) {
        req.setServerPort(proxyPort);
    } else if (req.getServerPort() == -1) {
        // Not explicitly set. Use default ports based on the scheme
        if (req.scheme().equals("https")) {
            req.setServerPort(443);
        } else {
            req.setServerPort(80);
        }
    }
    if (proxyName != null) {
        req.serverName().setString(proxyName);
    }
    MessageBytes undecodedURI = req.requestURI();
    // Check for ping OPTIONS * request
    if (undecodedURI.equals("*")) {
        if (req.method().equalsIgnoreCase("OPTIONS")) {
            StringBuilder allow = new StringBuilder();
            allow.append("GET, HEAD, POST, PUT, DELETE");
            // Trace if allowed
            if (connector.getAllowTrace()) {
                allow.append(", TRACE");
            }
            // Always allow options
            allow.append(", OPTIONS");
            res.setHeader("Allow", allow.toString());
        } else {
            res.setStatus(404);
            res.setMessage("Not found");
        }
        connector.getService().getContainer().logAccess(request, response, 0, true);
        return false;
    }
    MessageBytes decodedURI = req.decodedURI();
    if (undecodedURI.getType() == MessageBytes.T_BYTES) {
        // Copy the raw URI to the decodedURI
        decodedURI.duplicate(undecodedURI);
        // Parse the path parameters. This will:
        //   - strip out the path parameters
        //   - convert the decodedURI to bytes
        parsePathParameters(req, request);
        // %xx decoding of the URL
        try {
            req.getURLDecoder().convert(decodedURI, false);
        } catch (IOException ioe) {
            res.setStatus(400);
            res.setMessage("Invalid URI: " + ioe.getMessage());
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
        // Normalization
        if (!normalize(req.decodedURI())) {
            res.setStatus(400);
            res.setMessage("Invalid URI");
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
        // Character decoding
        convertURI(decodedURI, request);
        // Check that the URI is still normalized
        if (!checkNormalize(req.decodedURI())) {
            res.setStatus(400);
            res.setMessage("Invalid URI character encoding");
            connector.getService().getContainer().logAccess(request, response, 0, true);
            return false;
        }
    } else {
        /* The URI is chars or String, and has been sent using an in-memory
             * protocol handler. The following assumptions are made:
             * - req.requestURI() has been set to the 'original' non-decoded,
             *   non-normalized URI
             * - req.decodedURI() has been set to the decoded, normalized form
             *   of req.requestURI()
             */
        decodedURI.toChars();
        // Remove all path parameters; any needed path parameter should be set
        // using the request object rather than passing it in the URL
        CharChunk uriCC = decodedURI.getCharChunk();
        int semicolon = uriCC.indexOf(';');
        if (semicolon > 0) {
            decodedURI.setChars(uriCC.getBuffer(), uriCC.getStart(), semicolon);
        }
    }
    // Request mapping.
    MessageBytes serverName;
    if (connector.getUseIPVHosts()) {
        serverName = req.localName();
        if (serverName.isNull()) {
            // well, they did ask for it
            res.action(ActionCode.REQ_LOCAL_NAME_ATTRIBUTE, null);
        }
    } else {
        serverName = req.serverName();
    }
    // Version for the second mapping loop and
    // Context that we expect to get for that version
    String version = null;
    Context versionContext = null;
    boolean mapRequired = true;
    while (mapRequired) {
        // This will map the the latest version by default
        connector.getService().getMapper().map(serverName, decodedURI, version, request.getMappingData());
        // has been deployed
        if (request.getContext() == null) {
            res.setStatus(404);
            res.setMessage("Not found");
            // No context, so use host
            Host host = request.getHost();
            // Make sure there is a host (might not be during shutdown)
            if (host != null) {
                host.logAccess(request, response, 0, true);
            }
            return false;
        }
        // Now we have the context, we can parse the session ID from the URL
        // (if any). Need to do this before we redirect in case we need to
        // include the session id in the redirect
        String sessionID;
        if (request.getServletContext().getEffectiveSessionTrackingModes().contains(SessionTrackingMode.URL)) {
            // Get the session ID if there was one
            sessionID = request.getPathParameter(SessionConfig.getSessionUriParamName(request.getContext()));
            if (sessionID != null) {
                request.setRequestedSessionId(sessionID);
                request.setRequestedSessionURL(true);
            }
        }
        // Look for session ID in cookies and SSL session
        parseSessionCookiesId(request);
        parseSessionSslId(request);
        sessionID = request.getRequestedSessionId();
        mapRequired = false;
        if (version != null && request.getContext() == versionContext) {
        // We got the version that we asked for. That is it.
        } else {
            version = null;
            versionContext = null;
            Context[] contexts = request.getMappingData().contexts;
            // No session ID means no possibility of remap
            if (contexts != null && sessionID != null) {
                // Find the context associated with the session
                for (int i = (contexts.length); i > 0; i--) {
                    Context ctxt = contexts[i - 1];
                    if (ctxt.getManager().findSession(sessionID) != null) {
                        // already been mapped?
                        if (!ctxt.equals(request.getMappingData().context)) {
                            // Set version so second time through mapping
                            // the correct context is found
                            version = ctxt.getWebappVersion();
                            versionContext = ctxt;
                            // Reset mapping
                            request.getMappingData().recycle();
                            mapRequired = true;
                            // Recycle cookies and session info in case the
                            // correct context is configured with different
                            // settings
                            request.recycleSessionInfo();
                            request.recycleCookieInfo(true);
                        }
                        break;
                    }
                }
            }
        }
        if (!mapRequired && request.getContext().getPaused()) {
            // point.
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            // Should never happen
            }
            // Reset mapping
            request.getMappingData().recycle();
            mapRequired = true;
        }
    }
    // Possible redirect
    MessageBytes redirectPathMB = request.getMappingData().redirectPath;
    if (!redirectPathMB.isNull()) {
        String redirectPath = URLEncoder.DEFAULT.encode(redirectPathMB.toString(), "UTF-8");
        String query = request.getQueryString();
        if (request.isRequestedSessionIdFromURL()) {
            // This is not optimal, but as this is not very common, it
            // shouldn't matter
            redirectPath = redirectPath + ";" + SessionConfig.getSessionUriParamName(request.getContext()) + "=" + request.getRequestedSessionId();
        }
        if (query != null) {
            // This is not optimal, but as this is not very common, it
            // shouldn't matter
            redirectPath = redirectPath + "?" + query;
        }
        response.sendRedirect(redirectPath);
        request.getContext().logAccess(request, response, 0, true);
        return false;
    }
    // Filter trace method
    if (!connector.getAllowTrace() && req.method().equalsIgnoreCase("TRACE")) {
        Wrapper wrapper = request.getWrapper();
        String header = null;
        if (wrapper != null) {
            String[] methods = wrapper.getServletMethods();
            if (methods != null) {
                for (int i = 0; i < methods.length; i++) {
                    if ("TRACE".equals(methods[i])) {
                        continue;
                    }
                    if (header == null) {
                        header = methods[i];
                    } else {
                        header += ", " + methods[i];
                    }
                }
            }
        }
        res.setStatus(405);
        res.addHeader("Allow", header);
        res.setMessage("TRACE method is not allowed");
        request.getContext().logAccess(request, response, 0, true);
        return false;
    }
    doConnectorAuthenticationAuthorization(req, request);
    return true;
}
Also used : Context(org.apache.catalina.Context) Wrapper(org.apache.catalina.Wrapper) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) Host(org.apache.catalina.Host) IOException(java.io.IOException) CharChunk(org.apache.tomcat.util.buf.CharChunk)

Example 47 with Wrapper

use of org.apache.catalina.Wrapper in project tomcat by apache.

the class ApplicationContext method getServletRegistrations.

@Override
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
    Map<String, ApplicationServletRegistration> result = new HashMap<>();
    Container[] wrappers = context.findChildren();
    for (Container wrapper : wrappers) {
        result.put(((Wrapper) wrapper).getName(), new ApplicationServletRegistration((Wrapper) wrapper, context));
    }
    return result;
}
Also used : Wrapper(org.apache.catalina.Wrapper) Container(org.apache.catalina.Container) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 48 with Wrapper

use of org.apache.catalina.Wrapper in project tomcat by apache.

the class ApplicationContext method addServlet.

private ServletRegistration.Dynamic addServlet(String servletName, String servletClass, Servlet servlet, Map<String, String> initParams) throws IllegalStateException {
    if (servletName == null || servletName.equals("")) {
        throw new IllegalArgumentException(sm.getString("applicationContext.invalidServletName", servletName));
    }
    if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
        //TODO Spec breaking enhancement to ignore this restriction
        throw new IllegalStateException(sm.getString("applicationContext.addServlet.ise", getContextPath()));
    }
    Wrapper wrapper = (Wrapper) context.findChild(servletName);
    // a name
    if (wrapper == null) {
        wrapper = context.createWrapper();
        wrapper.setName(servletName);
        context.addChild(wrapper);
    } else {
        if (wrapper.getName() != null && wrapper.getServletClass() != null) {
            if (wrapper.isOverridable()) {
                wrapper.setOverridable(false);
            } else {
                return null;
            }
        }
    }
    if (servlet == null) {
        wrapper.setServletClass(servletClass);
    } else {
        wrapper.setServletClass(servlet.getClass().getName());
        wrapper.setServlet(servlet);
    }
    if (initParams != null) {
        for (Map.Entry<String, String> initParam : initParams.entrySet()) {
            wrapper.addInitParameter(initParam.getKey(), initParam.getValue());
        }
    }
    return context.dynamicServletAdded(wrapper);
}
Also used : Wrapper(org.apache.catalina.Wrapper) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 49 with Wrapper

use of org.apache.catalina.Wrapper in project tomcat by apache.

the class TestStuckThreadDetectionValve method testDetection.

@Test
public void testDetection() throws Exception {
    // second, we test the actual effect of the flag on the startup
    StuckingServlet stuckingServlet = new StuckingServlet(8000L);
    Wrapper servlet = Tomcat.addServlet(context, "myservlet", stuckingServlet);
    servlet.addMapping("/myservlet");
    StuckThreadDetectionValve valve = new StuckThreadDetectionValve();
    valve.setThreshold(2);
    context.addValve(valve);
    context.setBackgroundProcessorDelay(1);
    tomcat.start();
    Assert.assertEquals(0, valve.getStuckThreadIds().length);
    final ByteChunk result = new ByteChunk();
    Thread asyncThread = new Thread() {

        @Override
        public void run() {
            try {
                getUrl("http://localhost:" + getPort() + "/myservlet", result, null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    asyncThread.start();
    try {
        Thread.sleep(500L);
        Assert.assertEquals(0, valve.getStuckThreadIds().length);
        Thread.sleep(5000L);
        Assert.assertEquals(1, valve.getStuckThreadIds().length);
    } finally {
        asyncThread.join(20000);
        // check that we did not reach the join timeout
        Assert.assertFalse(asyncThread.isAlive());
    }
    Assert.assertFalse(stuckingServlet.wasInterrupted);
    Assert.assertTrue(result.toString().startsWith("OK"));
}
Also used : Wrapper(org.apache.catalina.Wrapper) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) IOException(java.io.IOException) TomcatBaseTest(org.apache.catalina.startup.TomcatBaseTest) Test(org.junit.Test)

Example 50 with Wrapper

use of org.apache.catalina.Wrapper in project tomcat by apache.

the class TestStuckThreadDetectionValve method testInterruption.

@Test
public void testInterruption() throws Exception {
    // second, we test the actual effect of the flag on the startup
    StuckingServlet stuckingServlet = new StuckingServlet(TimeUnit.SECONDS.toMillis(20L));
    Wrapper servlet = Tomcat.addServlet(context, "myservlet", stuckingServlet);
    servlet.addMapping("/myservlet");
    StuckThreadDetectionValve valve = new StuckThreadDetectionValve();
    valve.setThreshold(2);
    valve.setInterruptThreadThreshold(5);
    context.addValve(valve);
    context.setBackgroundProcessorDelay(1);
    tomcat.start();
    Assert.assertEquals(0, valve.getStuckThreadIds().length);
    final ByteChunk result = new ByteChunk();
    Thread asyncThread = new Thread() {

        @Override
        public void run() {
            try {
                getUrl("http://localhost:" + getPort() + "/myservlet", result, null);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    };
    asyncThread.start();
    try {
        Thread.sleep(4000L);
        Assert.assertEquals(1, valve.getStuckThreadIds().length);
    } finally {
        asyncThread.join(20000);
        // check that we did not reach the join timeout
        Assert.assertFalse(asyncThread.isAlive());
    }
    Assert.assertTrue(stuckingServlet.wasInterrupted);
    Assert.assertEquals(0, valve.getStuckThreadIds().length);
    Assert.assertTrue(result.toString().startsWith("OK"));
}
Also used : Wrapper(org.apache.catalina.Wrapper) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) IOException(java.io.IOException) TomcatBaseTest(org.apache.catalina.startup.TomcatBaseTest) Test(org.junit.Test)

Aggregations

Wrapper (org.apache.catalina.Wrapper)87 Context (org.apache.catalina.Context)53 Tomcat (org.apache.catalina.startup.Tomcat)46 AsyncContext (javax.servlet.AsyncContext)33 Test (org.junit.Test)31 TomcatBaseTest (org.apache.catalina.startup.TomcatBaseTest)28 ServletRequestWrapper (javax.servlet.ServletRequestWrapper)24 ServletResponseWrapper (javax.servlet.ServletResponseWrapper)24 TesterContext (org.apache.tomcat.unittest.TesterContext)24 ByteChunk (org.apache.tomcat.util.buf.ByteChunk)22 IOException (java.io.IOException)14 TesterAccessLogValve (org.apache.catalina.valves.TesterAccessLogValve)14 File (java.io.File)11 Container (org.apache.catalina.Container)11 StandardWrapper (org.apache.catalina.core.StandardWrapper)10 StandardContext (org.apache.catalina.core.StandardContext)6 SecurityConstraint (org.apache.tomcat.util.descriptor.web.SecurityConstraint)6 ServletException (javax.servlet.ServletException)5 ArrayList (java.util.ArrayList)4 ServletContext (javax.servlet.ServletContext)4