use of io.undertow.util.HttpString in project undertow by undertow-io.
the class HttpRequestParser method handleHeaderValueCacheMiss.
private void handleHeaderValueCacheMiss(ByteBuffer buffer, ParseState state, HttpServerExchange builder, HttpString headerName, HashMap<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.size() < maxHeaders) {
//we have a limit on how many we can cache
//to prevent memory filling and hash collision attacks
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;
}
use of io.undertow.util.HttpString in project camel by apache.
the class UndertowConsumer method handleRequest.
@Override
public void handleRequest(HttpServerExchange httpExchange) throws Exception {
HttpString requestMethod = httpExchange.getRequestMethod();
if (Methods.OPTIONS.equals(requestMethod) && !getEndpoint().isOptionsEnabled()) {
String allowedMethods;
if (getEndpoint().getHttpMethodRestrict() != null) {
allowedMethods = "OPTIONS," + getEndpoint().getHttpMethodRestrict();
} else {
allowedMethods = "GET,HEAD,POST,PUT,DELETE,TRACE,OPTIONS,CONNECT,PATCH";
}
//return list of allowed methods in response headers
httpExchange.setStatusCode(StatusCodes.OK);
httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_LENGTH, 0);
httpExchange.getResponseHeaders().put(Headers.ALLOW, allowedMethods);
httpExchange.getResponseSender().close();
return;
}
//perform blocking operation on exchange
if (httpExchange.isInIoThread()) {
httpExchange.dispatch(this);
return;
}
//create new Exchange
//binding is used to extract header and payload(if available)
Exchange camelExchange = getEndpoint().createExchange(httpExchange);
//Unit of Work to process the Exchange
createUoW(camelExchange);
try {
getProcessor().process(camelExchange);
} catch (Exception e) {
getExceptionHandler().handleException(e);
} finally {
doneUoW(camelExchange);
}
Object body = getResponseBody(httpExchange, camelExchange);
TypeConverter tc = getEndpoint().getCamelContext().getTypeConverter();
if (body == null) {
LOG.trace("No payload to send as reply for exchange: " + camelExchange);
httpExchange.getResponseHeaders().put(ExchangeHeaders.CONTENT_TYPE, MimeMappings.DEFAULT_MIME_MAPPINGS.get("txt"));
httpExchange.getResponseSender().send("No response available");
} else {
ByteBuffer bodyAsByteBuffer = tc.convertTo(ByteBuffer.class, body);
httpExchange.getResponseSender().send(bodyAsByteBuffer);
}
httpExchange.getResponseSender().close();
}
use of io.undertow.util.HttpString in project camel by apache.
the class UndertowHelper method createMethod.
/**
* Creates the HttpMethod to use to call the remote server, often either its GET or POST.
*/
public static HttpString createMethod(Exchange exchange, UndertowEndpoint endpoint, boolean hasPayload) throws URISyntaxException {
// is a query string provided in the endpoint URI or in a header (header
// overrules endpoint)
String queryString = exchange.getIn().getHeader(Exchange.HTTP_QUERY, String.class);
// We need also check the HTTP_URI header query part
String uriString = exchange.getIn().getHeader(Exchange.HTTP_URI, String.class);
// resolve placeholders in uriString
try {
uriString = exchange.getContext().resolvePropertyPlaceholders(uriString);
} catch (Exception e) {
throw new RuntimeExchangeException("Cannot resolve property placeholders with uri: " + uriString, exchange, e);
}
if (uriString != null) {
URI uri = new URI(uriString);
queryString = uri.getQuery();
}
if (queryString == null) {
queryString = endpoint.getHttpURI().getRawQuery();
}
// compute what method to use either GET or POST
HttpString answer;
String m = exchange.getIn().getHeader(Exchange.HTTP_METHOD, String.class);
if (m != null) {
// always use what end-user provides in a header
answer = new HttpString(m);
} else if (queryString != null) {
// if a query string is provided then use GET
answer = Methods.GET;
} else {
// fallback to POST if we have payload, otherwise GET
answer = hasPayload ? Methods.POST : Methods.GET;
}
return answer;
}
use of io.undertow.util.HttpString in project camel by apache.
the class UndertowProducer method process.
@Override
public boolean process(Exchange exchange, AsyncCallback callback) {
ClientConnection connection = null;
try {
final UndertowClient client = UndertowClient.getInstance();
IoFuture<ClientConnection> connect = client.connect(endpoint.getHttpURI(), worker, pool, options);
// creating the url to use takes 2-steps
final String exchangeUri = UndertowHelper.createURL(exchange, getEndpoint());
final URI uri = UndertowHelper.createURI(exchange, exchangeUri, getEndpoint());
final String pathAndQuery = URISupport.pathAndQueryOf(uri);
// what http method to use
HttpString method = UndertowHelper.createMethod(exchange, endpoint, exchange.getIn().getBody() != null);
ClientRequest request = new ClientRequest();
request.setProtocol(Protocols.HTTP_1_1);
request.setPath(pathAndQuery);
request.setMethod(method);
final HeaderMap requestHeaders = request.getRequestHeaders();
// Set the Host header
Message message = exchange.getIn();
final String host = message.getHeader("Host", String.class);
requestHeaders.put(Headers.HOST, Optional.ofNullable(host).orElseGet(() -> uri.getAuthority()));
Object body = getRequestBody(request, exchange);
TypeConverter tc = endpoint.getCamelContext().getTypeConverter();
ByteBuffer bodyAsByte = tc.tryConvertTo(ByteBuffer.class, body);
if (body != null) {
requestHeaders.put(Headers.CONTENT_LENGTH, bodyAsByte.array().length);
}
if (getEndpoint().getCookieHandler() != null) {
Map<String, List<String>> cookieHeaders = getEndpoint().getCookieHandler().loadCookies(exchange, uri);
for (Map.Entry<String, List<String>> entry : cookieHeaders.entrySet()) {
requestHeaders.putAll(new HttpString(entry.getKey()), entry.getValue());
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Executing http {} method: {}", method, pathAndQuery);
}
connection = connect.get();
connection.sendRequest(request, new UndertowProducerCallback(connection, bodyAsByte, exchange, callback));
} catch (Exception e) {
IOHelper.close(connection);
exchange.setException(e);
callback.done(true);
return true;
}
// use async routing engine
return false;
}
use of io.undertow.util.HttpString in project camel by apache.
the class DefaultUndertowHttpBinding method populateCamelHeaders.
@Override
public void populateCamelHeaders(HttpServerExchange httpExchange, Map<String, Object> headersMap, Exchange exchange) throws Exception {
LOG.trace("populateCamelHeaders: {}");
// NOTE: these headers is applied using the same logic as camel-http/camel-jetty to be consistent
headersMap.put(Exchange.HTTP_METHOD, httpExchange.getRequestMethod().toString());
// strip query parameters from the uri
headersMap.put(Exchange.HTTP_URL, httpExchange.getRequestURL());
// uri is without the host and port
headersMap.put(Exchange.HTTP_URI, httpExchange.getRequestURI());
headersMap.put(Exchange.HTTP_QUERY, httpExchange.getQueryString());
headersMap.put(Exchange.HTTP_RAW_QUERY, httpExchange.getQueryString());
String path = httpExchange.getRequestPath();
UndertowEndpoint endpoint = (UndertowEndpoint) exchange.getFromEndpoint();
if (endpoint.getHttpURI() != null) {
// need to match by lower case as we want to ignore case on context-path
String endpointPath = endpoint.getHttpURI().getPath();
String matchPath = path.toLowerCase(Locale.US);
String match = endpointPath.toLowerCase(Locale.US);
if (match != null && matchPath.startsWith(match)) {
path = path.substring(endpointPath.length());
}
}
headersMap.put(Exchange.HTTP_PATH, path);
if (LOG.isTraceEnabled()) {
LOG.trace("HTTP-Method {}", httpExchange.getRequestMethod());
LOG.trace("HTTP-Uri {}", httpExchange.getRequestURI());
}
for (HttpString name : httpExchange.getRequestHeaders().getHeaderNames()) {
//String name = httpName.toString();
if (name.toString().toLowerCase(Locale.US).equals("content-type")) {
name = ExchangeHeaders.CONTENT_TYPE;
}
if (name.toString().toLowerCase(Locale.US).equals("authorization")) {
String value = httpExchange.getRequestHeaders().get(name).toString();
// store a special header that this request was authenticated using HTTP Basic
if (value != null && value.trim().startsWith("Basic")) {
if (headerFilterStrategy != null && !headerFilterStrategy.applyFilterToExternalHeaders(Exchange.AUTHENTICATION, "Basic", exchange)) {
UndertowHelper.appendHeader(headersMap, Exchange.AUTHENTICATION, "Basic");
}
}
}
// add the headers one by one, and use the header filter strategy
Iterator<?> it = httpExchange.getRequestHeaders().get(name).iterator();
while (it.hasNext()) {
Object value = it.next();
LOG.trace("HTTP-header: {}", value);
if (headerFilterStrategy != null && !headerFilterStrategy.applyFilterToExternalHeaders(name.toString(), value, exchange)) {
UndertowHelper.appendHeader(headersMap, name.toString(), value);
}
}
}
//process uri parameters as headers
Map<String, Deque<String>> pathParameters = httpExchange.getQueryParameters();
//continue if the map is not empty, otherwise there are no params
if (!pathParameters.isEmpty()) {
for (Map.Entry<String, Deque<String>> entry : pathParameters.entrySet()) {
String name = entry.getKey();
Object values = entry.getValue();
Iterator<?> it = ObjectHelper.createIterator(values);
while (it.hasNext()) {
Object value = it.next();
LOG.trace("URI-Parameter: {}", value);
if (headerFilterStrategy != null && !headerFilterStrategy.applyFilterToExternalHeaders(name, value, exchange)) {
UndertowHelper.appendHeader(headersMap, name, value);
}
}
}
}
// Create headers for REST path placeholder variables
Map<String, Object> predicateContextParams = httpExchange.getAttachment(Predicate.PREDICATE_CONTEXT);
if (predicateContextParams != null) {
// Remove this as it's an unwanted artifact of our Undertow predicate chain
predicateContextParams.remove("remaining");
for (String paramName : predicateContextParams.keySet()) {
LOG.trace("REST Template Variable {}: {})", paramName, predicateContextParams.get(paramName));
headersMap.put(paramName, predicateContextParams.get(paramName));
}
}
}
Aggregations