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;
}
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;
}
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);
}
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;
}
Aggregations