Search in sources :

Example 61 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class TestCookies method test.

private void test(String header, Cookie... expected) {
    MimeHeaders mimeHeaders = new MimeHeaders();
    ServerCookies serverCookies = new ServerCookies(4);
    CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
    MessageBytes cookieHeaderValue = mimeHeaders.addValue("Cookie");
    byte[] bytes = header.getBytes(StandardCharsets.UTF_8);
    cookieHeaderValue.setBytes(bytes, 0, bytes.length);
    cookieProcessor.parseCookieHeader(mimeHeaders, serverCookies);
    Assert.assertEquals(expected.length, serverCookies.getCookieCount());
    for (int i = 0; i < expected.length; i++) {
        Cookie cookie = expected[i];
        ServerCookie actual = serverCookies.getCookie(i);
        Assert.assertEquals(cookie.getName(), actual.getName().toString());
        actual.getValue().getByteChunk().setCharset(StandardCharsets.UTF_8);
        Assert.assertEquals(cookie.getValue(), actual.getValue().toString());
    }
}
Also used : Cookie(jakarta.servlet.http.Cookie) MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 62 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class StandardWrapperValve method invoke.

// --------------------------------------------------------- Public Methods
/**
 * Invoke the servlet we are managing, respecting the rules regarding
 * servlet lifecycle support.
 *
 * @param request Request to be processed
 * @param response Response to be produced
 *
 * @exception IOException if an input/output error occurred
 * @exception ServletException if a servlet error occurred
 */
@Override
public final void invoke(Request request, Response response) throws IOException, ServletException {
    // Initialize local variables we may need
    boolean unavailable = false;
    Throwable throwable = null;
    // This should be a Request attribute...
    long t1 = System.currentTimeMillis();
    requestCount.incrementAndGet();
    StandardWrapper wrapper = (StandardWrapper) getContainer();
    Servlet servlet = null;
    Context context = (Context) wrapper.getParent();
    // Check for the application being marked unavailable
    if (!context.getState().isAvailable()) {
        response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardContext.isUnavailable"));
        unavailable = true;
    }
    // Check for the servlet being marked unavailable
    if (!unavailable && wrapper.isUnavailable()) {
        container.getLogger().info(sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
        unavailable = true;
    }
    // Allocate a servlet instance to process this request
    try {
        if (!unavailable) {
            servlet = wrapper.allocate();
        }
    } catch (UnavailableException e) {
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
    } catch (ServletException e) {
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), StandardWrapper.getRootCause(e));
        throwable = e;
        exception(request, response, e);
    } catch (Throwable e) {
        ExceptionUtils.handleThrowable(e);
        container.getLogger().error(sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
        throwable = e;
        exception(request, response, e);
        servlet = null;
    }
    MessageBytes requestPathMB = request.getRequestPathMB();
    DispatcherType dispatcherType = DispatcherType.REQUEST;
    if (request.getDispatcherType() == DispatcherType.ASYNC) {
        dispatcherType = DispatcherType.ASYNC;
    }
    request.setAttribute(Globals.DISPATCHER_TYPE_ATTR, dispatcherType);
    request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
    // Create the filter chain for this request
    ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
    // Call the filter chain for this request
    // NOTE: This also calls the servlet's service() method
    Container container = this.container;
    try {
        if ((servlet != null) && (filterChain != null)) {
            // Swallow output if needed
            if (context.getSwallowOutput()) {
                try {
                    SystemLogHandler.startCapture();
                    if (request.isAsyncDispatching()) {
                        request.getAsyncContextInternal().doInternalDispatch();
                    } else {
                        filterChain.doFilter(request.getRequest(), response.getResponse());
                    }
                } finally {
                    String log = SystemLogHandler.stopCapture();
                    if (log != null && log.length() > 0) {
                        context.getLogger().info(log);
                    }
                }
            } else {
                if (request.isAsyncDispatching()) {
                    request.getAsyncContextInternal().doInternalDispatch();
                } else {
                    filterChain.doFilter(request.getRequest(), response.getResponse());
                }
            }
        }
    } catch (ClientAbortException | CloseNowException e) {
        if (container.getLogger().isDebugEnabled()) {
            container.getLogger().debug(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        }
        throwable = e;
        exception(request, response, e);
    } catch (IOException e) {
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        throwable = e;
        exception(request, response, e);
    } catch (UnavailableException e) {
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        // throwable = e;
        // exception(request, response, e);
        wrapper.unavailable(e);
        long available = wrapper.getAvailable();
        if ((available > 0L) && (available < Long.MAX_VALUE)) {
            response.setDateHeader("Retry-After", available);
            response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
        } else if (available == Long.MAX_VALUE) {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString("standardWrapper.notFound", wrapper.getName()));
        }
    // Do not save exception in 'throwable', because we
    // do not want to do exception(request, response, e) processing
    } catch (ServletException e) {
        Throwable rootCause = StandardWrapper.getRootCause(e);
        if (!(rootCause instanceof ClientAbortException)) {
            container.getLogger().error(sm.getString("standardWrapper.serviceExceptionRoot", wrapper.getName(), context.getName(), e.getMessage()), rootCause);
        }
        throwable = e;
        exception(request, response, e);
    } catch (Throwable e) {
        ExceptionUtils.handleThrowable(e);
        container.getLogger().error(sm.getString("standardWrapper.serviceException", wrapper.getName(), context.getName()), e);
        throwable = e;
        exception(request, response, e);
    } finally {
        // Release the filter chain (if any) for this request
        if (filterChain != null) {
            filterChain.release();
        }
        // Deallocate the allocated servlet instance
        try {
            if (servlet != null) {
                wrapper.deallocate(servlet);
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
            if (throwable == null) {
                throwable = e;
                exception(request, response, e);
            }
        }
        // unload it and release this instance
        try {
            if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
                wrapper.unload();
            }
        } catch (Throwable e) {
            ExceptionUtils.handleThrowable(e);
            container.getLogger().error(sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
            if (throwable == null) {
                exception(request, response, e);
            }
        }
        long t2 = System.currentTimeMillis();
        long time = t2 - t1;
        processingTime += time;
        if (time > maxTime) {
            maxTime = time;
        }
        if (time < minTime) {
            minTime = time;
        }
    }
}
Also used : Context(org.apache.catalina.Context) UnavailableException(jakarta.servlet.UnavailableException) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) IOException(java.io.IOException) ServletException(jakarta.servlet.ServletException) Container(org.apache.catalina.Container) CloseNowException(org.apache.coyote.CloseNowException) Servlet(jakarta.servlet.Servlet) ClientAbortException(org.apache.catalina.connector.ClientAbortException) DispatcherType(jakarta.servlet.DispatcherType)

Example 63 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method prepareRequest.

/**
 * After reading the request headers, we have to setup the request filters.
 */
private void prepareRequest() throws IOException {
    if (protocol.isSSLEnabled()) {
        request.scheme().setString("https");
    }
    MimeHeaders headers = request.getMimeHeaders();
    // Check connection header
    MessageBytes connectionValueMB = headers.getValue(Constants.CONNECTION);
    if (connectionValueMB != null && !connectionValueMB.isNull()) {
        Set<String> tokens = new HashSet<>();
        TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
        if (tokens.contains(Constants.CLOSE)) {
            keepAlive = false;
        } else if (tokens.contains(Constants.KEEP_ALIVE_HEADER_VALUE_TOKEN)) {
            keepAlive = true;
        }
    }
    if (http11) {
        prepareExpectation(headers);
    }
    // Check user-agent header
    Pattern restrictedUserAgents = protocol.getRestrictedUserAgentsPattern();
    if (restrictedUserAgents != null && (http11 || keepAlive)) {
        MessageBytes userAgentValueMB = headers.getValue("user-agent");
        // and keepAlive flags accordingly
        if (userAgentValueMB != null && !userAgentValueMB.isNull()) {
            String userAgentValue = userAgentValueMB.toString();
            if (restrictedUserAgents.matcher(userAgentValue).matches()) {
                http11 = false;
                keepAlive = false;
            }
        }
    }
    // Check host header
    MessageBytes hostValueMB = null;
    try {
        hostValueMB = headers.getUniqueValue("host");
    } catch (IllegalArgumentException iae) {
        // Multiple Host headers are not permitted
        badRequest("http11processor.request.multipleHosts");
    }
    if (http11 && hostValueMB == null) {
        badRequest("http11processor.request.noHostHeader");
    }
    // Check for an absolute-URI less the query string which has already
    // been removed during the parsing of the request line
    ByteChunk uriBC = request.requestURI().getByteChunk();
    byte[] uriB = uriBC.getBytes();
    if (uriBC.startsWithIgnoreCase("http", 0)) {
        int pos = 4;
        // Check for https
        if (uriBC.startsWithIgnoreCase("s", pos)) {
            pos++;
        }
        // Next 3 characters must be "://"
        if (uriBC.startsWith("://", pos)) {
            pos += 3;
            int uriBCStart = uriBC.getStart();
            // '/' does not appear in the authority so use the first
            // instance to split the authority and the path segments
            int slashPos = uriBC.indexOf('/', pos);
            // '@' in the authority delimits the userinfo
            int atPos = uriBC.indexOf('@', pos);
            if (slashPos > -1 && atPos > slashPos) {
                // First '@' is in the path segments so no userinfo
                atPos = -1;
            }
            if (slashPos == -1) {
                slashPos = uriBC.getLength();
                // Set URI as "/". Use 6 as it will always be a '/'.
                // 01234567
                // http://
                // https://
                request.requestURI().setBytes(uriB, uriBCStart + 6, 1);
            } else {
                request.requestURI().setBytes(uriB, uriBCStart + slashPos, uriBC.getLength() - slashPos);
            }
            // Skip any user info
            if (atPos != -1) {
                // Validate the userinfo
                for (; pos < atPos; pos++) {
                    byte c = uriB[uriBCStart + pos];
                    if (!HttpParser.isUserInfo(c)) {
                        // Strictly there needs to be a check for valid %nn
                        // encoding here but skip it since it will never be
                        // decoded because the userinfo is ignored
                        badRequest("http11processor.request.invalidUserInfo");
                        break;
                    }
                }
                // Skip the '@'
                pos = atPos + 1;
            }
            if (http11) {
                // Missing host header is illegal but handled above
                if (hostValueMB != null) {
                    // the Host header
                    if (!hostValueMB.getByteChunk().equals(uriB, uriBCStart + pos, slashPos - pos)) {
                        if (protocol.getAllowHostHeaderMismatch()) {
                            // The requirements of RFC 2616 are being
                            // applied. If the host header and the request
                            // line do not agree, the request line takes
                            // precedence
                            hostValueMB = headers.setValue("host");
                            hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
                        } else {
                            // The requirements of RFC 7230 are being
                            // applied. If the host header and the request
                            // line do not agree, trigger a 400 response.
                            badRequest("http11processor.request.inconsistentHosts");
                        }
                    }
                }
            } else {
                // Tomcat internals assume it is set
                try {
                    hostValueMB = headers.setValue("host");
                    hostValueMB.setBytes(uriB, uriBCStart + pos, slashPos - pos);
                } catch (IllegalStateException e) {
                // Edge case
                // If the request has too many headers it won't be
                // possible to create the host header. Ignore this as
                // processing won't reach the point where the Tomcat
                // internals expect there to be a host header.
                }
            }
        } else {
            badRequest("http11processor.request.invalidScheme");
        }
    }
    // the point of decoding.
    for (int i = uriBC.getStart(); i < uriBC.getEnd(); i++) {
        if (!httpParser.isAbsolutePathRelaxed(uriB[i])) {
            badRequest("http11processor.request.invalidUri");
            break;
        }
    }
    // Input filter setup
    prepareInputFilters(headers);
    // Validate host name and extract port if present
    parseHost(hostValueMB);
    if (!getErrorState().isIoAllowed()) {
        getAdapter().log(request, response, 0);
    }
}
Also used : MimeHeaders(org.apache.tomcat.util.http.MimeHeaders) Pattern(java.util.regex.Pattern) ByteChunk(org.apache.tomcat.util.buf.ByteChunk) MessageBytes(org.apache.tomcat.util.buf.MessageBytes) HashSet(java.util.HashSet)

Example 64 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method prepareExpectation.

private void prepareExpectation(MimeHeaders headers) {
    MessageBytes expectMB = headers.getValue("expect");
    if (expectMB != null && !expectMB.isNull()) {
        if (expectMB.toString().trim().equalsIgnoreCase("100-continue")) {
            inputBuffer.setSwallowInput(false);
            request.setExpectation(true);
        } else {
            response.setStatus(HttpServletResponse.SC_EXPECTATION_FAILED);
            setErrorState(ErrorState.CLOSE_CLEAN, null);
        }
    }
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes)

Example 65 with MessageBytes

use of org.apache.tomcat.util.buf.MessageBytes in project tomcat by apache.

the class Http11Processor method isConnectionToken.

private static boolean isConnectionToken(MimeHeaders headers, String token) throws IOException {
    MessageBytes connection = headers.getValue(Constants.CONNECTION);
    if (connection == null) {
        return false;
    }
    Set<String> tokens = new HashSet<>();
    TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
    return tokens.contains(token);
}
Also used : MessageBytes(org.apache.tomcat.util.buf.MessageBytes) HashSet(java.util.HashSet)

Aggregations

MessageBytes (org.apache.tomcat.util.buf.MessageBytes)73 MimeHeaders (org.apache.tomcat.util.http.MimeHeaders)15 ByteChunk (org.apache.tomcat.util.buf.ByteChunk)14 IOException (java.io.IOException)11 Test (org.junit.Test)11 Context (org.apache.catalina.Context)10 LoggingBaseTest (org.apache.catalina.startup.LoggingBaseTest)8 Pattern (java.util.regex.Pattern)6 AbstractEndpoint (org.apache.tomcat.util.net.AbstractEndpoint)6 Principal (java.security.Principal)5 Wrapper (org.apache.catalina.Wrapper)5 CharChunk (org.apache.tomcat.util.buf.CharChunk)5 Host (org.apache.catalina.Host)4 ServletException (jakarta.servlet.ServletException)3 Cookie (jakarta.servlet.http.Cookie)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)3 HashSet (java.util.HashSet)3 ServletException (javax.servlet.ServletException)3 Cookie (javax.servlet.http.Cookie)3 Container (org.apache.catalina.Container)3