Search in sources :

Example 1 with BadRequestException

use of io.undertow.util.BadRequestException in project undertow by undertow-io.

the class AjpReadListener method createSourceConduit.

private StreamSourceConduit createSourceConduit(StreamSourceConduit underlyingConduit, AjpServerResponseConduit responseConduit, final HttpServerExchange exchange) throws BadRequestException {
    ReadDataStreamSourceConduit conduit = new ReadDataStreamSourceConduit(underlyingConduit, (AbstractServerConnection) exchange.getConnection());
    final HeaderMap requestHeaders = exchange.getRequestHeaders();
    HttpString transferEncoding = Headers.IDENTITY;
    Long length;
    final String teHeader = requestHeaders.getLast(Headers.TRANSFER_ENCODING);
    boolean hasTransferEncoding = teHeader != null;
    if (hasTransferEncoding) {
        transferEncoding = new HttpString(teHeader);
    }
    final String requestContentLength = requestHeaders.getFirst(Headers.CONTENT_LENGTH);
    if (hasTransferEncoding && !transferEncoding.equals(Headers.IDENTITY)) {
        // unknown length
        length = null;
    } else if (requestContentLength != null) {
        try {
            final long contentLength = Long.parseLong(requestContentLength);
            if (contentLength == 0L) {
                UndertowLogger.REQUEST_LOGGER.trace("No content, starting next request");
                // no content - immediately start the next request, returning an empty stream for this one
                Connectors.terminateRequest(httpServerExchange);
                return new EmptyStreamSourceConduit(conduit.getReadThread());
            } else {
                length = contentLength;
            }
        } catch (NumberFormatException e) {
            throw new BadRequestException("Invalid Content-Length header", e);
        }
    } else {
        UndertowLogger.REQUEST_LOGGER.trace("No content length or transfer coding, starting next request");
        // no content - immediately start the next request, returning an empty stream for this one
        Connectors.terminateRequest(exchange);
        return new EmptyStreamSourceConduit(conduit.getReadThread());
    }
    return new AjpServerRequestConduit(conduit, exchange, responseConduit, length, new ConduitListener<AjpServerRequestConduit>() {

        @Override
        public void handleEvent(AjpServerRequestConduit channel) {
            Connectors.terminateRequest(exchange);
        }
    });
}
Also used : EmptyStreamSourceConduit(io.undertow.conduits.EmptyStreamSourceConduit) HeaderMap(io.undertow.util.HeaderMap) ReadDataStreamSourceConduit(io.undertow.conduits.ReadDataStreamSourceConduit) BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString) HttpString(io.undertow.util.HttpString)

Example 2 with BadRequestException

use of io.undertow.util.BadRequestException in project undertow by undertow-io.

the class AjpRequestParser method parseString.

protected StringHolder parseString(ByteBuffer buf, AjpRequestParseState state, StringType type) throws UnsupportedEncodingException, BadRequestException {
    boolean containsUrlCharacters = state.containsUrlCharacters;
    boolean containsUnencodedUrlCharacters = state.containsUnencodedUrlCharacters;
    if (!buf.hasRemaining()) {
        return new StringHolder(null, false, false, false);
    }
    int stringLength = state.stringLength;
    if (stringLength == -1) {
        int number = buf.get() & 0xFF;
        if (buf.hasRemaining()) {
            final byte b = buf.get();
            stringLength = ((0xFF & number) << 8) + (b & 0xFF);
        } else {
            state.stringLength = number | STRING_LENGTH_MASK;
            return new StringHolder(null, false, false, false);
        }
    } else if ((stringLength & STRING_LENGTH_MASK) != 0) {
        int number = stringLength & ~STRING_LENGTH_MASK;
        stringLength = ((0xFF & number) << 8) + (buf.get() & 0xFF);
    }
    if (type == StringType.HEADER && (stringLength & 0xFF00) != 0) {
        state.stringLength = -1;
        return new StringHolder(headers(stringLength & 0xFF));
    }
    if (stringLength == 0xFFFF) {
        // OxFFFF means null
        state.stringLength = -1;
        return new StringHolder(null, true, false, false);
    }
    int length = state.getCurrentStringLength();
    while (length < stringLength) {
        if (!buf.hasRemaining()) {
            state.stringLength = stringLength;
            state.containsUrlCharacters = containsUrlCharacters;
            state.containsUnencodedUrlCharacters = containsUnencodedUrlCharacters;
            return new StringHolder(null, false, false, false);
        }
        byte c = buf.get();
        if (type == StringType.QUERY_STRING && (c == '+' || c == '%' || c < 0)) {
            if (c < 0) {
                if (!allowUnescapedCharactersInUrl) {
                    throw new BadRequestException();
                } else {
                    containsUnencodedUrlCharacters = true;
                }
            }
            containsUrlCharacters = true;
        } else if (type == StringType.URL && (c == '%' || c < 0)) {
            if (c < 0) {
                if (!allowUnescapedCharactersInUrl) {
                    throw new BadRequestException();
                } else {
                    containsUnencodedUrlCharacters = true;
                }
            }
            containsUrlCharacters = true;
        }
        state.addStringByte(c);
        ++length;
    }
    if (buf.hasRemaining()) {
        // null terminator
        buf.get();
        String value = state.getStringAndClear();
        state.stringLength = -1;
        state.containsUrlCharacters = false;
        state.containsUnencodedUrlCharacters = containsUnencodedUrlCharacters;
        return new StringHolder(value, true, containsUrlCharacters, containsUnencodedUrlCharacters);
    } else {
        state.stringLength = stringLength;
        state.containsUrlCharacters = containsUrlCharacters;
        state.containsUnencodedUrlCharacters = containsUnencodedUrlCharacters;
        return new StringHolder(null, false, false, false);
    }
}
Also used : BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString)

Example 3 with BadRequestException

use of io.undertow.util.BadRequestException in project undertow by undertow-io.

the class AjpRequestParser method parse.

public void parse(final ByteBuffer buf, final AjpRequestParseState state, final HttpServerExchange exchange) throws IOException, BadRequestException {
    if (!buf.hasRemaining()) {
        return;
    }
    switch(state.state) {
        case AjpRequestParseState.BEGIN:
            {
                IntegerHolder result = parse16BitInteger(buf, state);
                if (!result.readComplete) {
                    return;
                } else {
                    if (result.value != 0x1234) {
                        throw new BadRequestException(UndertowMessages.MESSAGES.wrongMagicNumber(result.value));
                    }
                }
            }
        case AjpRequestParseState.READING_DATA_SIZE:
            {
                IntegerHolder result = parse16BitInteger(buf, state);
                if (!result.readComplete) {
                    state.state = AjpRequestParseState.READING_DATA_SIZE;
                    return;
                } else {
                    state.dataSize = result.value;
                }
            }
        case AjpRequestParseState.READING_PREFIX_CODE:
            {
                if (!buf.hasRemaining()) {
                    state.state = AjpRequestParseState.READING_PREFIX_CODE;
                    return;
                } else {
                    final byte prefix = buf.get();
                    state.prefix = prefix;
                    if (prefix != 2) {
                        state.state = AjpRequestParseState.DONE;
                        return;
                    }
                }
            }
        case AjpRequestParseState.READING_METHOD:
            {
                if (!buf.hasRemaining()) {
                    state.state = AjpRequestParseState.READING_METHOD;
                    return;
                } else {
                    int method = buf.get();
                    if (method > 0 && method < 28) {
                        exchange.setRequestMethod(HTTP_METHODS[method]);
                    } else if ((method & 0xFF) != 0xFF) {
                        throw new BadRequestException("Unknown method type " + method);
                    }
                }
            }
        case AjpRequestParseState.READING_PROTOCOL:
            {
                StringHolder result = parseString(buf, state, StringType.OTHER);
                if (result.readComplete) {
                    // TODO: more efficient way of doing this
                    exchange.setProtocol(HttpString.tryFromString(result.value));
                } else {
                    state.state = AjpRequestParseState.READING_PROTOCOL;
                    return;
                }
            }
        case AjpRequestParseState.READING_REQUEST_URI:
            {
                StringHolder result = parseString(buf, state, StringType.URL);
                if (result.readComplete) {
                    int colon = result.value.indexOf(';');
                    if (colon == -1) {
                        String res = decode(result.value, result.containsUrlCharacters);
                        if (result.containsUnencodedCharacters) {
                            // we decode if the URL was non-compliant, and contained incorrectly encoded characters
                            // there is not really a 'correct' thing to do in this situation, but this seems the least incorrect
                            exchange.setRequestURI(res);
                        } else {
                            exchange.setRequestURI(result.value);
                        }
                        exchange.setRequestPath(res);
                        exchange.setRelativePath(res);
                    } else {
                        final StringBuffer resBuffer = new StringBuffer();
                        int pathParamParsingIndex = 0;
                        try {
                            do {
                                final String url = result.value.substring(pathParamParsingIndex, colon);
                                resBuffer.append(decode(url, result.containsUrlCharacters));
                                pathParamParsingIndex = colon + 1 + URLUtils.parsePathParams(result.value.substring(colon + 1), exchange, encoding, doDecode && result.containsUrlCharacters, maxParameters);
                                colon = result.value.indexOf(';', pathParamParsingIndex + 1);
                            } while (pathParamParsingIndex < result.value.length() && colon != -1);
                        } catch (ParameterLimitException e) {
                            UndertowLogger.REQUEST_IO_LOGGER.failedToParseRequest(e);
                            state.badRequest = true;
                        }
                        if (pathParamParsingIndex < result.value.length()) {
                            final String url = result.value.substring(pathParamParsingIndex);
                            resBuffer.append(decode(url, result.containsUrlCharacters));
                        }
                        final String res = resBuffer.toString();
                        if (result.containsUnencodedCharacters) {
                            exchange.setRequestURI(res);
                        } else {
                            exchange.setRequestURI(result.value);
                        }
                        exchange.setRequestPath(res);
                        exchange.setRelativePath(res);
                    }
                } else {
                    state.state = AjpRequestParseState.READING_REQUEST_URI;
                    return;
                }
            }
        case AjpRequestParseState.READING_REMOTE_ADDR:
            {
                StringHolder result = parseString(buf, state, StringType.OTHER);
                if (result.readComplete) {
                    state.remoteAddress = result.value;
                } else {
                    state.state = AjpRequestParseState.READING_REMOTE_ADDR;
                    return;
                }
            }
        case AjpRequestParseState.READING_REMOTE_HOST:
            {
                StringHolder result = parseString(buf, state, StringType.OTHER);
                if (!result.readComplete) {
                    state.state = AjpRequestParseState.READING_REMOTE_HOST;
                    return;
                }
            }
        case AjpRequestParseState.READING_SERVER_NAME:
            {
                StringHolder result = parseString(buf, state, StringType.OTHER);
                if (result.readComplete) {
                    state.serverAddress = result.value;
                } else {
                    state.state = AjpRequestParseState.READING_SERVER_NAME;
                    return;
                }
            }
        case AjpRequestParseState.READING_SERVER_PORT:
            {
                IntegerHolder result = parse16BitInteger(buf, state);
                if (result.readComplete) {
                    state.serverPort = result.value;
                } else {
                    state.state = AjpRequestParseState.READING_SERVER_PORT;
                    return;
                }
            }
        case AjpRequestParseState.READING_IS_SSL:
            {
                if (!buf.hasRemaining()) {
                    state.state = AjpRequestParseState.READING_IS_SSL;
                    return;
                } else {
                    final byte isSsl = buf.get();
                    if (isSsl != 0) {
                        exchange.setRequestScheme("https");
                    } else {
                        exchange.setRequestScheme("http");
                    }
                }
            }
        case AjpRequestParseState.READING_NUM_HEADERS:
            {
                IntegerHolder result = parse16BitInteger(buf, state);
                if (!result.readComplete) {
                    state.state = AjpRequestParseState.READING_NUM_HEADERS;
                    return;
                } else {
                    state.numHeaders = result.value;
                    if (state.numHeaders > maxHeaders) {
                        UndertowLogger.REQUEST_IO_LOGGER.failedToParseRequest(new BadRequestException(UndertowMessages.MESSAGES.tooManyHeaders(maxHeaders)));
                        state.badRequest = true;
                    }
                }
            }
        case AjpRequestParseState.READING_HEADERS:
            {
                int readHeaders = state.readHeaders;
                while (readHeaders < state.numHeaders) {
                    if (state.currentHeader == null) {
                        StringHolder result = parseString(buf, state, StringType.HEADER);
                        if (!result.readComplete) {
                            state.state = AjpRequestParseState.READING_HEADERS;
                            state.readHeaders = readHeaders;
                            return;
                        }
                        if (result.header != null) {
                            state.currentHeader = result.header;
                        } else {
                            state.currentHeader = HttpString.tryFromString(result.value);
                            Connectors.verifyToken(state.currentHeader);
                        }
                    }
                    StringHolder result = parseString(buf, state, StringType.OTHER);
                    if (!result.readComplete) {
                        state.state = AjpRequestParseState.READING_HEADERS;
                        state.readHeaders = readHeaders;
                        return;
                    }
                    if (!state.badRequest) {
                        exchange.getRequestHeaders().add(state.currentHeader, result.value);
                    }
                    state.currentHeader = null;
                    ++readHeaders;
                }
            }
        case AjpRequestParseState.READING_ATTRIBUTES:
            {
                for (; ; ) {
                    if (state.currentAttribute == null && state.currentIntegerPart == -1) {
                        if (!buf.hasRemaining()) {
                            state.state = AjpRequestParseState.READING_ATTRIBUTES;
                            return;
                        }
                        int val = (0xFF & buf.get());
                        if (val == 0xFF) {
                            state.state = AjpRequestParseState.DONE;
                            return;
                        } else if (val == 0x0A) {
                            // we need to read the name. We overload currentIntegerPart to avoid adding another state field
                            state.currentIntegerPart = 1;
                        } else {
                            if (val == 0 || val >= ATTRIBUTES.length) {
                                // ignore unknown codes for compatibility
                                continue;
                            }
                            state.currentAttribute = ATTRIBUTES[val];
                        }
                    }
                    if (state.currentIntegerPart == 1) {
                        StringHolder result = parseString(buf, state, StringType.OTHER);
                        if (!result.readComplete) {
                            state.state = AjpRequestParseState.READING_ATTRIBUTES;
                            return;
                        }
                        state.currentAttribute = result.value;
                        state.currentIntegerPart = -1;
                    }
                    String result;
                    boolean decodingAlreadyDone = false;
                    if (state.currentAttribute.equals(SSL_KEY_SIZE)) {
                        IntegerHolder resultHolder = parse16BitInteger(buf, state);
                        if (!resultHolder.readComplete) {
                            state.state = AjpRequestParseState.READING_ATTRIBUTES;
                            return;
                        }
                        result = Integer.toString(resultHolder.value);
                    } else {
                        StringHolder resultHolder = parseString(buf, state, state.currentAttribute.equals(QUERY_STRING) ? StringType.QUERY_STRING : StringType.OTHER);
                        if (!resultHolder.readComplete) {
                            state.state = AjpRequestParseState.READING_ATTRIBUTES;
                            return;
                        }
                        if (resultHolder.containsUnencodedCharacters) {
                            result = decode(resultHolder.value, true);
                            decodingAlreadyDone = true;
                        } else {
                            result = resultHolder.value;
                        }
                    }
                    // query string.
                    if (state.currentAttribute.equals(QUERY_STRING)) {
                        String resultAsQueryString = result == null ? "" : result;
                        exchange.setQueryString(resultAsQueryString);
                        try {
                            URLUtils.parseQueryString(resultAsQueryString, exchange, encoding, doDecode && !decodingAlreadyDone, maxParameters);
                        } catch (ParameterLimitException | IllegalArgumentException e) {
                            UndertowLogger.REQUEST_IO_LOGGER.failedToParseRequest(e);
                            state.badRequest = true;
                        }
                    } else if (state.currentAttribute.equals(REMOTE_USER)) {
                        exchange.putAttachment(ExternalAuthenticationMechanism.EXTERNAL_PRINCIPAL, result);
                        exchange.putAttachment(HttpServerExchange.REMOTE_USER, result);
                    } else if (state.currentAttribute.equals(AUTH_TYPE)) {
                        exchange.putAttachment(ExternalAuthenticationMechanism.EXTERNAL_AUTHENTICATION_TYPE, result);
                    } else if (state.currentAttribute.equals(STORED_METHOD)) {
                        HttpString requestMethod = new HttpString(result);
                        Connectors.verifyToken(requestMethod);
                        exchange.setRequestMethod(requestMethod);
                    } else if (state.currentAttribute.equals(AJP_REMOTE_PORT)) {
                        state.remotePort = Integer.parseInt(result);
                    } else if (state.currentAttribute.equals(SSL_SESSION)) {
                        state.sslSessionId = result;
                    } else if (state.currentAttribute.equals(SSL_CIPHER)) {
                        state.sslCipher = result;
                    } else if (state.currentAttribute.equals(SSL_CERT)) {
                        state.sslCert = result;
                    } else if (state.currentAttribute.equals(SSL_KEY_SIZE)) {
                        state.sslKeySize = result;
                    } else {
                        // other attributes
                        if (state.attributes == null) {
                            state.attributes = new TreeMap<>();
                        }
                        if (ATTR_SET.contains(state.currentAttribute)) {
                            // known attirubtes
                            state.attributes.put(state.currentAttribute, result);
                        } else if (allowedRequestAttributesPattern != null) {
                            // custom allowed attributes
                            Matcher m = allowedRequestAttributesPattern.matcher(state.currentAttribute);
                            if (m.matches()) {
                                state.attributes.put(state.currentAttribute, result);
                            }
                        }
                    }
                    state.currentAttribute = null;
                }
            }
    }
    state.state = AjpRequestParseState.DONE;
}
Also used : ParameterLimitException(io.undertow.util.ParameterLimitException) Matcher(java.util.regex.Matcher) BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString) TreeMap(java.util.TreeMap) HttpString(io.undertow.util.HttpString)

Example 4 with BadRequestException

use of io.undertow.util.BadRequestException in project undertow by undertow-io.

the class HttpRequestParser method handleHeaderValueCacheMiss.

private void handleHeaderValueCacheMiss(ByteBuffer buffer, ParseState state, HttpServerExchange builder, HttpString headerName, CacheMap<HttpString, String> headerValuesCache, StringBuilder stringBuilder) throws BadRequestException {
    int parseState = state.parseState;
    while (buffer.hasRemaining() && parseState == NORMAL) {
        final byte next = buffer.get();
        if (next == '\r') {
            parseState = BEGIN_LINE_END;
        } else if (next == '\n') {
            parseState = LINE_END;
        } else if (next == ' ' || next == '\t') {
            parseState = WHITESPACE;
        } else {
            stringBuilder.append((char) (next & 0xFF));
        }
    }
    while (buffer.hasRemaining()) {
        final byte next = buffer.get();
        switch(parseState) {
            case NORMAL:
                {
                    if (next == '\r') {
                        parseState = BEGIN_LINE_END;
                    } else if (next == '\n') {
                        parseState = LINE_END;
                    } else if (next == ' ' || next == '\t') {
                        parseState = WHITESPACE;
                    } else {
                        stringBuilder.append((char) (next & 0xFF));
                    }
                    break;
                }
            case WHITESPACE:
                {
                    if (next == '\r') {
                        parseState = BEGIN_LINE_END;
                    } else if (next == '\n') {
                        parseState = LINE_END;
                    } else if (next == ' ' || next == '\t') {
                    } else {
                        if (stringBuilder.length() > 0) {
                            stringBuilder.append(' ');
                        }
                        stringBuilder.append((char) (next & 0xFF));
                        parseState = NORMAL;
                    }
                    break;
                }
            case LINE_END:
            case BEGIN_LINE_END:
                {
                    if (next == '\n' && parseState == BEGIN_LINE_END) {
                        parseState = LINE_END;
                    } else if (next == '\t' || next == ' ') {
                        // this is a continuation
                        parseState = WHITESPACE;
                    } else {
                        // we have a header
                        String headerValue = stringBuilder.toString();
                        if (++state.mapCount > maxHeaders) {
                            throw new BadRequestException(UndertowMessages.MESSAGES.tooManyHeaders(maxHeaders));
                        }
                        // TODO: we need to decode this according to RFC-2047 if we have seen a =? symbol
                        builder.getRequestHeaders().add(headerName, headerValue);
                        if (headerValuesCache != null && headerName.length() + headerValue.length() < maxCachedHeaderSize) {
                            headerValuesCache.put(headerName, headerValue);
                        }
                        state.nextHeader = null;
                        state.leftOver = next;
                        state.stringBuilder.setLength(0);
                        if (next == '\r') {
                            parseState = AWAIT_DATA_END;
                        } else if (next == '\n') {
                            state.state = ParseState.PARSE_COMPLETE;
                            return;
                        } else {
                            state.state = ParseState.HEADER;
                            state.parseState = 0;
                            return;
                        }
                    }
                    break;
                }
            case AWAIT_DATA_END:
                {
                    state.state = ParseState.PARSE_COMPLETE;
                    return;
                }
        }
    }
    // we only write to the state if we did not finish parsing
    state.parseState = parseState;
}
Also used : BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString)

Example 5 with BadRequestException

use of io.undertow.util.BadRequestException in project undertow by undertow-io.

the class AjpReadListener method handleEvent.

public void handleEvent(final StreamSourceChannel channel) {
    if (connection.getOriginalSinkConduit().isWriteShutdown() || connection.getOriginalSourceConduit().isReadShutdown()) {
        safeClose(connection);
        channel.suspendReads();
        return;
    }
    PooledByteBuffer existing = connection.getExtraBytes();
    final PooledByteBuffer pooled = existing == null ? connection.getByteBufferPool().allocate() : existing;
    final ByteBuffer buffer = pooled.getBuffer();
    boolean free = true;
    boolean bytesRead = false;
    try {
        int res;
        do {
            if (existing == null) {
                buffer.clear();
                res = channel.read(buffer);
            } else {
                res = buffer.remaining();
            }
            if (res == 0) {
                if (bytesRead && parseTimeoutUpdater != null) {
                    parseTimeoutUpdater.failedParse();
                }
                if (!channel.isReadResumed()) {
                    channel.getReadSetter().set(this);
                    channel.resumeReads();
                }
                return;
            }
            if (res == -1) {
                channel.shutdownReads();
                final StreamSinkChannel responseChannel = connection.getChannel().getSinkChannel();
                responseChannel.shutdownWrites();
                safeClose(connection);
                return;
            }
            bytesRead = true;
            // TODO: we need to handle parse errors
            if (existing != null) {
                existing = null;
                connection.setExtraBytes(null);
            } else {
                buffer.flip();
            }
            int begin = buffer.remaining();
            if (httpServerExchange == null) {
                httpServerExchange = new HttpServerExchange(connection, maxEntitySize);
            }
            parser.parse(buffer, state, httpServerExchange);
            read += begin - buffer.remaining();
            if (buffer.hasRemaining()) {
                free = false;
                connection.setExtraBytes(pooled);
            }
            if (read > maxRequestSize) {
                UndertowLogger.REQUEST_LOGGER.requestHeaderWasTooLarge(connection.getPeerAddress(), maxRequestSize);
                safeClose(connection);
                return;
            }
        } while (!state.isComplete());
        if (parseTimeoutUpdater != null) {
            parseTimeoutUpdater.requestStarted();
        }
        if (state.prefix != AjpRequestParser.FORWARD_REQUEST) {
            if (state.prefix == AjpRequestParser.CPING) {
                UndertowLogger.REQUEST_LOGGER.debug("Received CPING, sending CPONG");
                handleCPing();
            } else if (state.prefix == AjpRequestParser.CPONG) {
                UndertowLogger.REQUEST_LOGGER.debug("Received CPONG, starting next request");
                state = new AjpRequestParseState();
                channel.getReadSetter().set(this);
                channel.resumeReads();
            } else {
                UndertowLogger.REQUEST_LOGGER.ignoringAjpRequestWithPrefixCode(state.prefix);
                safeClose(connection);
            }
            return;
        }
        // we remove ourselves as the read listener from the channel;
        // if the http handler doesn't set any then reads will suspend, which is the right thing to do
        channel.getReadSetter().set(null);
        channel.suspendReads();
        final HttpServerExchange httpServerExchange = this.httpServerExchange;
        final AjpServerResponseConduit responseConduit = new AjpServerResponseConduit(connection.getChannel().getSinkChannel().getConduit(), connection.getByteBufferPool(), httpServerExchange, new ConduitListener<AjpServerResponseConduit>() {

            @Override
            public void handleEvent(AjpServerResponseConduit channel) {
                Connectors.terminateResponse(httpServerExchange);
            }
        }, httpServerExchange.getRequestMethod().equals(Methods.HEAD));
        connection.getChannel().getSinkChannel().setConduit(responseConduit);
        connection.getChannel().getSourceChannel().setConduit(createSourceConduit(connection.getChannel().getSourceChannel().getConduit(), responseConduit, httpServerExchange));
        // we need to set the write ready handler. This allows the response conduit to wrap it
        responseConduit.setWriteReadyHandler(writeReadyHandler);
        connection.setSSLSessionInfo(state.createSslSessionInfo());
        httpServerExchange.setSourceAddress(state.createPeerAddress());
        httpServerExchange.setDestinationAddress(state.createDestinationAddress());
        if (scheme != null) {
            httpServerExchange.setRequestScheme(scheme);
        }
        if (state.attributes != null) {
            httpServerExchange.putAttachment(HttpServerExchange.REQUEST_ATTRIBUTES, state.attributes);
        }
        AjpRequestParseState oldState = state;
        state = null;
        this.httpServerExchange = null;
        httpServerExchange.setPersistent(true);
        if (recordRequestStartTime) {
            Connectors.setRequestStartTime(httpServerExchange);
        }
        connection.setCurrentExchange(httpServerExchange);
        if (connectorStatistics != null) {
            connectorStatistics.setup(httpServerExchange);
        }
        if (!Connectors.areRequestHeadersValid(httpServerExchange.getRequestHeaders())) {
            oldState.badRequest = true;
            UndertowLogger.REQUEST_IO_LOGGER.debugf("Invalid AJP request from %s, request contained invalid headers", connection.getPeerAddress());
        }
        if (oldState.badRequest) {
            httpServerExchange.setStatusCode(StatusCodes.BAD_REQUEST);
            httpServerExchange.endExchange();
            handleBadRequest();
            safeClose(connection);
        } else {
            Connectors.executeRootHandler(connection.getRootHandler(), httpServerExchange);
        }
    } catch (BadRequestException e) {
        UndertowLogger.REQUEST_IO_LOGGER.failedToParseRequest(e);
        handleBadRequest();
        safeClose(connection);
    } catch (IOException e) {
        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
        handleInternalServerError();
        safeClose(connection);
    } catch (Throwable t) {
        UndertowLogger.REQUEST_LOGGER.exceptionProcessingRequest(t);
        handleInternalServerError();
        safeClose(connection);
    } finally {
        if (free)
            pooled.close();
    }
}
Also used : StreamSinkChannel(org.xnio.channels.StreamSinkChannel) ConduitStreamSinkChannel(org.xnio.conduits.ConduitStreamSinkChannel) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) HttpServerExchange(io.undertow.server.HttpServerExchange) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) BadRequestException(io.undertow.util.BadRequestException)

Aggregations

BadRequestException (io.undertow.util.BadRequestException)9 HttpString (io.undertow.util.HttpString)7 EmptyStreamSourceConduit (io.undertow.conduits.EmptyStreamSourceConduit)1 ReadDataStreamSourceConduit (io.undertow.conduits.ReadDataStreamSourceConduit)1 PooledByteBuffer (io.undertow.connector.PooledByteBuffer)1 HttpServerExchange (io.undertow.server.HttpServerExchange)1 HeaderMap (io.undertow.util.HeaderMap)1 ParameterLimitException (io.undertow.util.ParameterLimitException)1 IOException (java.io.IOException)1 ByteBuffer (java.nio.ByteBuffer)1 TreeMap (java.util.TreeMap)1 Matcher (java.util.regex.Matcher)1 StreamSinkChannel (org.xnio.channels.StreamSinkChannel)1 ConduitStreamSinkChannel (org.xnio.conduits.ConduitStreamSinkChannel)1