Search in sources :

Example 6 with BadRequestException

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

the class HttpRequestParser method handlePath.

/**
 * Parses a path value
 *
 * @param buffer   The buffer
 * @param state    The current state
 * @param exchange The exchange builder
 * @return The number of bytes remaining
 */
@SuppressWarnings("unused")
final void handlePath(ByteBuffer buffer, ParseState state, HttpServerExchange exchange) throws BadRequestException {
    StringBuilder stringBuilder = state.stringBuilder;
    int parseState = state.parseState;
    int canonicalPathStart = state.pos;
    boolean urlDecodeRequired = state.urlDecodeRequired;
    while (buffer.hasRemaining()) {
        char next = (char) (buffer.get() & 0xFF);
        if (!allowUnescapedCharactersInUrl && !ALLOWED_TARGET_CHARACTER[next]) {
            throw new BadRequestException(UndertowMessages.MESSAGES.invalidCharacterInRequestTarget(next));
        }
        if (next == ' ' || next == '\t') {
            if (stringBuilder.length() != 0) {
                final String path = stringBuilder.toString();
                parsePathComplete(state, exchange, canonicalPathStart, parseState, urlDecodeRequired, path);
                exchange.setQueryString("");
                state.state = ParseState.VERSION;
                return;
            }
        } else if (next == '\r' || next == '\n') {
            throw UndertowMessages.MESSAGES.failedToParsePath();
        } else if (next == '?' && (parseState == START || parseState == HOST_DONE || parseState == IN_PATH)) {
            beginQueryParameters(buffer, state, exchange, stringBuilder, parseState, canonicalPathStart, urlDecodeRequired);
            return;
        } else if (next == ';') {
            state.parseState = parseState;
            state.urlDecodeRequired = urlDecodeRequired;
            state.pos = canonicalPathStart;
            // store at canonical path the partial path parsed up until here
            state.canonicalPath.append(stringBuilder.substring(canonicalPathStart));
            // handle the path parameters
            handlePathParameters(buffer, state, exchange);
            // and append the '/' read by handlePathParameters
            if (state.state == ParseState.PATH) {
                canonicalPathStart = stringBuilder.length();
                stringBuilder.append('/');
            } else {
                // path has been entirely parsed, just return
                return;
            }
        } else {
            if (decode && (next == '%' || next > 127)) {
                urlDecodeRequired = true;
            } else if (next == ':' && parseState == START) {
                parseState = FIRST_COLON;
            } else if (next == '/' && parseState == FIRST_COLON) {
                parseState = FIRST_SLASH;
            } else if (next == '/' && parseState == FIRST_SLASH) {
                parseState = SECOND_SLASH;
            } else if (next == '/' && parseState == SECOND_SLASH) {
                parseState = HOST_DONE;
                canonicalPathStart = stringBuilder.length();
            } else if (parseState == FIRST_COLON || parseState == FIRST_SLASH) {
                parseState = IN_PATH;
            } else if (next == '/' && parseState != HOST_DONE) {
                parseState = IN_PATH;
            }
            stringBuilder.append(next);
        }
    }
    state.parseState = parseState;
    state.pos = canonicalPathStart;
    state.urlDecodeRequired = urlDecodeRequired;
}
Also used : BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString)

Example 7 with BadRequestException

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

the class HttpRequestParser method handlePathParameters.

/**
 * This method should only ever be called if the path contains am non-decoded semi colon character ';'
 */
final void handlePathParameters(ByteBuffer buffer, ParseState state, HttpServerExchange exchange) throws BadRequestException {
    state.state = ParseState.PATH_PARAMETERS;
    boolean urlDecodeRequired = state.urlDecodeRequired;
    String param = state.nextQueryParam;
    final StringBuilder stringBuilder = state.stringBuilder;
    stringBuilder.append(";");
    int pos = stringBuilder.length();
    while (buffer.hasRemaining()) {
        char next = (char) (buffer.get() & 0xFF);
        if (!allowUnescapedCharactersInUrl && !ALLOWED_TARGET_CHARACTER[next]) {
            throw new BadRequestException(UndertowMessages.MESSAGES.invalidCharacterInRequestTarget(next));
        }
        // end of HTTP URI
        if (next == ' ' || next == '\t' || next == '?') {
            handleParsedParam(param, stringBuilder.substring(pos), exchange, urlDecodeRequired, state);
            final String path = stringBuilder.toString();
            // the canonicalPathStart should be the current length to not add anything to it
            parsePathComplete(state, exchange, path.length(), state.parseState, urlDecodeRequired, path);
            state.state = ParseState.VERSION;
            state.nextQueryParam = null;
            if (next == '?') {
                state.state = ParseState.QUERY_PARAMETERS;
                handleQueryParameters(buffer, state, exchange);
            } else
                exchange.setQueryString("");
            return;
        } else if (next == '\r' || next == '\n') {
            throw UndertowMessages.MESSAGES.failedToParsePath();
        } else if (next == '/') {
            handleParsedParam(param, stringBuilder.substring(pos), exchange, urlDecodeRequired, state);
            state.pos = stringBuilder.length();
            state.state = ParseState.PATH;
            state.nextQueryParam = null;
            return;
        } else {
            if (decode && (next == '+' || next == '%' || next > 127)) {
                urlDecodeRequired = true;
            }
            if (next == '=' && param == null) {
                param = decode(stringBuilder.substring(pos), urlDecodeRequired, state, true, true);
                urlDecodeRequired = false;
                pos = stringBuilder.length() + 1;
            } else if (next == ';') {
                handleParsedParam(param, stringBuilder.substring(pos), exchange, urlDecodeRequired, state);
                param = null;
                pos = stringBuilder.length() + 1;
            } else if (next == ',') {
                if (param == null) {
                    throw UndertowMessages.MESSAGES.failedToParsePath();
                } else {
                    handleParsedParam(param, stringBuilder.substring(pos), exchange, urlDecodeRequired, state);
                    pos = stringBuilder.length() + 1;
                }
            }
            stringBuilder.append(next);
        }
    }
    state.urlDecodeRequired = urlDecodeRequired;
    state.pos = pos;
    state.urlDecodeRequired = urlDecodeRequired;
    state.nextQueryParam = param;
}
Also used : BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString)

Example 8 with BadRequestException

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

the class HttpRequestParser method handle.

public void handle(ByteBuffer buffer, final ParseState currentState, final HttpServerExchange builder) throws BadRequestException {
    if (currentState.state == ParseState.VERB) {
        // fast path, we assume that it will parse fully so we avoid all the if statements
        // fast path HTTP GET requests, basically just assume all requests are get
        // and fall out to the state machine if it is not
        final int position = buffer.position();
        if (buffer.remaining() > 3 && buffer.get(position) == 'G' && buffer.get(position + 1) == 'E' && buffer.get(position + 2) == 'T' && buffer.get(position + 3) == ' ') {
            buffer.position(position + 4);
            builder.setRequestMethod(Methods.GET);
            currentState.state = ParseState.PATH;
        } else {
            try {
                handleHttpVerb(buffer, currentState, builder);
            } catch (IllegalArgumentException e) {
                throw new BadRequestException(e);
            }
        }
        handlePath(buffer, currentState, builder);
        boolean failed = false;
        if (buffer.remaining() > HTTP_LENGTH + 3) {
            int pos = buffer.position();
            for (int i = 0; i < HTTP_LENGTH; ++i) {
                if (HTTP[i] != buffer.get(pos + i)) {
                    failed = true;
                    break;
                }
            }
            if (!failed) {
                final byte b = buffer.get(pos + HTTP_LENGTH);
                final byte b2 = buffer.get(pos + HTTP_LENGTH + 1);
                final byte b3 = buffer.get(pos + HTTP_LENGTH + 2);
                if (b2 == '\r' && b3 == '\n') {
                    if (b == '1') {
                        builder.setProtocol(Protocols.HTTP_1_1);
                        buffer.position(pos + HTTP_LENGTH + 3);
                        currentState.state = ParseState.HEADER;
                    } else if (b == '0') {
                        builder.setProtocol(Protocols.HTTP_1_0);
                        buffer.position(pos + HTTP_LENGTH + 3);
                        currentState.state = ParseState.HEADER;
                    } else {
                        failed = true;
                    }
                } else {
                    failed = true;
                }
            }
        } else {
            failed = true;
        }
        if (failed) {
            handleHttpVersion(buffer, currentState, builder);
            handleAfterVersion(buffer, currentState);
        }
        while (currentState.state != ParseState.PARSE_COMPLETE && buffer.hasRemaining()) {
            handleHeader(buffer, currentState, builder);
            if (currentState.state == ParseState.HEADER_VALUE) {
                handleHeaderValue(buffer, currentState, builder);
            }
        }
        return;
    }
    handleStateful(buffer, currentState, builder);
}
Also used : BadRequestException(io.undertow.util.BadRequestException)

Example 9 with BadRequestException

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

the class HttpRequestParser method handleQueryParameters.

/**
 * Parses query string parameters
 *
 * @param buffer   The buffer
 * @param state    The current state
 * @param exchange The exchange builder
 * @return The number of bytes remaining
 */
@SuppressWarnings("unused")
final void handleQueryParameters(ByteBuffer buffer, ParseState state, HttpServerExchange exchange) throws BadRequestException {
    StringBuilder stringBuilder = state.stringBuilder;
    int queryParamPos = state.pos;
    int mapCount = state.mapCount;
    boolean urlDecodeRequired = state.urlDecodeRequired;
    String nextQueryParam = state.nextQueryParam;
    while (buffer.hasRemaining()) {
        char next = (char) (buffer.get() & 0xFF);
        if (!allowUnescapedCharactersInUrl && !ALLOWED_TARGET_CHARACTER[next]) {
            throw new BadRequestException(UndertowMessages.MESSAGES.invalidCharacterInRequestTarget(next));
        }
        if (next == ' ' || next == '\t') {
            final String queryString = stringBuilder.toString();
            exchange.setQueryString(queryString);
            if (nextQueryParam == null) {
                if (queryParamPos != stringBuilder.length()) {
                    exchange.addQueryParam(decode(stringBuilder.substring(queryParamPos), urlDecodeRequired, state, true, true), "");
                }
            } else {
                exchange.addQueryParam(nextQueryParam, decode(stringBuilder.substring(queryParamPos), urlDecodeRequired, state, true, true));
            }
            state.state = ParseState.VERSION;
            state.stringBuilder.setLength(0);
            state.pos = 0;
            state.nextQueryParam = null;
            state.urlDecodeRequired = false;
            state.mapCount = 0;
            return;
        } else if (next == '\r' || next == '\n') {
            throw UndertowMessages.MESSAGES.failedToParsePath();
        } else {
            if (decode && (next == '+' || next == '%' || next > 127)) {
                // + is only a whitespace substitute in the query part of the URL
                urlDecodeRequired = true;
            } else if (next == '=' && nextQueryParam == null) {
                nextQueryParam = decode(stringBuilder.substring(queryParamPos), urlDecodeRequired, state, true, true);
                urlDecodeRequired = false;
                queryParamPos = stringBuilder.length() + 1;
            } else if (next == '&' && nextQueryParam == null) {
                if (++mapCount >= maxParameters) {
                    throw UndertowMessages.MESSAGES.tooManyQueryParameters(maxParameters);
                }
                if (queryParamPos != stringBuilder.length()) {
                    exchange.addQueryParam(decode(stringBuilder.substring(queryParamPos), urlDecodeRequired, state, true, true), "");
                }
                urlDecodeRequired = false;
                queryParamPos = stringBuilder.length() + 1;
            } else if (next == '&') {
                if (++mapCount >= maxParameters) {
                    throw UndertowMessages.MESSAGES.tooManyQueryParameters(maxParameters);
                }
                exchange.addQueryParam(nextQueryParam, decode(stringBuilder.substring(queryParamPos), urlDecodeRequired, state, true, true));
                urlDecodeRequired = false;
                queryParamPos = stringBuilder.length() + 1;
                nextQueryParam = null;
            }
            stringBuilder.append(next);
        }
    }
    state.pos = queryParamPos;
    state.nextQueryParam = nextQueryParam;
    state.urlDecodeRequired = urlDecodeRequired;
    state.mapCount = mapCount;
}
Also used : BadRequestException(io.undertow.util.BadRequestException) HttpString(io.undertow.util.HttpString)

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