use of io.undertow.util.HttpString in project undertow by undertow-io.
the class HpackDecoder method readHeaderName.
private HttpString readHeaderName(ByteBuffer buffer, int prefixLength) throws HpackException {
//unget the byte
buffer.position(buffer.position() - 1);
int index = Hpack.decodeInteger(buffer, prefixLength);
if (index == -1) {
return null;
} else if (index != 0) {
return handleIndexedHeaderName(index);
} else {
String string = readHpackString(buffer);
if (string == null) {
return null;
}
return new HttpString(string);
}
}
use of io.undertow.util.HttpString in project undertow by undertow-io.
the class HpackEncoder method encode.
/**
* Encodes the headers into a buffer.
*
* @param headers
* @param target
*/
public State encode(HeaderMap headers, ByteBuffer target) {
if (overflowData != null) {
for (int i = overflowPos; i < overflowLength; ++i) {
if (!target.hasRemaining()) {
overflowPos = i;
return State.OVERFLOW;
}
target.put(overflowData[i]);
}
overflowData = null;
}
long it = headersIterator;
if (headersIterator == -1) {
handleTableSizeChange(target);
//new headers map
it = headers.fastIterate();
currentHeaders = headers;
} else {
if (headers != currentHeaders) {
throw new IllegalStateException();
}
}
while (it != -1) {
HeaderValues values = headers.fiCurrent(it);
boolean skip = false;
if (firstPass) {
if (values.getHeaderName().byteAt(0) != ':') {
skip = true;
}
} else {
if (values.getHeaderName().byteAt(0) == ':') {
skip = true;
}
}
if (SKIP.contains(values.getHeaderName())) {
//ignore connection specific headers
skip = true;
}
if (!skip) {
for (int i = 0; i < values.size(); ++i) {
HttpString headerName = values.getHeaderName();
//we use 11 to make sure we have enough room for the variable length itegers
int required = 11 + headerName.length();
String val = values.get(i);
for (int v = 0; v < val.length(); ++v) {
char c = val.charAt(v);
if (c == '\r' || c == '\n') {
val = val.replace('\r', ' ').replace('\n', ' ');
break;
}
}
TableEntry tableEntry = findInTable(headerName, val);
required += (1 + val.length());
boolean overflowing = false;
ByteBuffer current = target;
if (current.remaining() < required) {
overflowing = true;
current = ByteBuffer.wrap(overflowData = new byte[required]);
overflowPos = 0;
}
//only index if it will fit
boolean canIndex = hpackHeaderFunction.shouldUseIndexing(headerName, val) && (headerName.length() + val.length() + 32) < maxTableSize;
if (tableEntry == null && canIndex) {
//add the entry to the dynamic table
current.put((byte) (1 << 6));
writeHuffmanEncodableName(current, headerName);
writeHuffmanEncodableValue(current, headerName, val);
addToDynamicTable(headerName, val);
} else if (tableEntry == null) {
//literal never indexed
current.put((byte) (1 << 4));
writeHuffmanEncodableName(current, headerName);
writeHuffmanEncodableValue(current, headerName, val);
} else {
//so we know something is already in the table
if (val.equals(tableEntry.value)) {
//the whole thing is in the table
current.put((byte) (1 << 7));
encodeInteger(current, tableEntry.getPosition(), 7);
} else {
if (canIndex) {
//add the entry to the dynamic table
current.put((byte) (1 << 6));
encodeInteger(current, tableEntry.getPosition(), 6);
writeHuffmanEncodableValue(current, headerName, val);
addToDynamicTable(headerName, val);
} else {
current.put((byte) (1 << 4));
encodeInteger(current, tableEntry.getPosition(), 4);
writeHuffmanEncodableValue(current, headerName, val);
}
}
}
if (overflowing) {
it = headers.fiNext(it);
this.headersIterator = it;
this.overflowLength = current.position();
return State.OVERFLOW;
}
}
}
it = headers.fiNext(it);
if (it == -1 && firstPass) {
firstPass = false;
it = headers.fastIterate();
}
}
headersIterator = -1;
firstPass = true;
return State.COMPLETE;
}
use of io.undertow.util.HttpString in project undertow by undertow-io.
the class AjpClientRequestClientStreamSinkChannel method createFrameHeaderImpl.
private SendFrameHeader createFrameHeaderImpl() {
if (discardMode) {
getBuffer().clear();
getBuffer().flip();
return new SendFrameHeader(new ImmediatePooledByteBuffer(ByteBuffer.wrap(new byte[0])));
}
PooledByteBuffer pooledHeaderBuffer = getChannel().getBufferPool().allocate();
try {
final ByteBuffer buffer = pooledHeaderBuffer.getBuffer();
ByteBuffer dataBuffer = getBuffer();
int dataInBuffer = dataBuffer.remaining();
if (!firstFrameWritten && requestedChunkSize == 0) {
//we are waiting on a read body chunk
return new SendFrameHeader(dataInBuffer, null);
}
int maxData = getChannel().getSettings().get(UndertowOptions.MAX_AJP_PACKET_SIZE, DEFAULT_MAX_DATA_SIZE) - 6;
if (!firstFrameWritten) {
String contentLength = headers.getFirst(Headers.CONTENT_LENGTH);
if (contentLength != null) {
dataSize = Long.parseLong(contentLength);
requestedChunkSize = maxData;
if (dataInBuffer > dataSize) {
throw UndertowMessages.MESSAGES.fixedLengthOverflow();
}
} else if (isWritesShutdown() && !headers.contains(Headers.TRANSFER_ENCODING)) {
//writes are shut down, go to fixed length
headers.put(Headers.CONTENT_LENGTH, dataInBuffer);
dataSize = dataInBuffer;
requestedChunkSize = maxData;
} else {
headers.put(Headers.TRANSFER_ENCODING, Headers.CHUNKED.toString());
dataSize = -1;
requestedChunkSize = 0;
}
firstFrameWritten = true;
final String path;
final String queryString;
int qsIndex = this.path.indexOf('?');
if (qsIndex == -1) {
path = this.path;
queryString = null;
} else {
path = this.path.substring(0, qsIndex);
queryString = this.path.substring(qsIndex + 1);
}
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
//we fill the size in later
buffer.put((byte) 0);
buffer.put((byte) 0);
buffer.put((byte) 2);
boolean storeMethod = false;
Integer methodNp = AjpConstants.HTTP_METHODS_MAP.get(method);
if (methodNp == null) {
methodNp = 0xFF;
storeMethod = true;
}
buffer.put((byte) (int) methodNp);
AjpUtils.putHttpString(buffer, protocol);
putString(buffer, path);
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.REMOTE_ADDRESS)));
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.REMOTE_HOST)));
putString(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.SERVER_NAME)));
AjpUtils.putInt(buffer, notNull(attachable.getAttachment(ProxiedRequestAttachments.SERVER_PORT)));
buffer.put((byte) (notNull(attachable.getAttachment(ProxiedRequestAttachments.IS_SSL)) ? 1 : 0));
int headers = 0;
//we need to count the headers
final HeaderMap responseHeaders = this.headers;
for (HttpString name : responseHeaders.getHeaderNames()) {
headers += responseHeaders.get(name).size();
}
AjpUtils.putInt(buffer, headers);
for (final HttpString header : responseHeaders.getHeaderNames()) {
for (String headerValue : responseHeaders.get(header)) {
Integer headerCode = AjpConstants.HEADER_MAP.get(header);
if (headerCode != null) {
AjpUtils.putInt(buffer, headerCode);
} else {
AjpUtils.putHttpString(buffer, header);
}
putString(buffer, headerValue);
}
}
if (queryString != null) {
//query_string
buffer.put((byte) ATTR_QUERY_STRING);
putString(buffer, queryString);
}
String remoteUser = attachable.getAttachment(ProxiedRequestAttachments.REMOTE_USER);
if (remoteUser != null) {
buffer.put((byte) ATTR_REMOTE_USER);
putString(buffer, remoteUser);
}
String authType = attachable.getAttachment(ProxiedRequestAttachments.AUTH_TYPE);
if (authType != null) {
buffer.put((byte) ATTR_AUTH_TYPE);
putString(buffer, authType);
}
String route = attachable.getAttachment(ProxiedRequestAttachments.ROUTE);
if (route != null) {
buffer.put((byte) ATTR_ROUTE);
putString(buffer, route);
}
String sslCert = attachable.getAttachment(ProxiedRequestAttachments.SSL_CERT);
if (sslCert != null) {
buffer.put((byte) ATTR_SSL_CERT);
putString(buffer, sslCert);
}
String sslCypher = attachable.getAttachment(ProxiedRequestAttachments.SSL_CYPHER);
if (sslCypher != null) {
buffer.put((byte) ATTR_SSL_CIPHER);
putString(buffer, sslCypher);
}
byte[] sslSession = attachable.getAttachment(ProxiedRequestAttachments.SSL_SESSION_ID);
if (sslSession != null) {
buffer.put((byte) ATTR_SSL_SESSION);
putString(buffer, FlexBase64.encodeString(sslSession, false));
}
Integer sslKeySize = attachable.getAttachment(ProxiedRequestAttachments.SSL_KEY_SIZE);
if (sslKeySize != null) {
buffer.put((byte) ATTR_SSL_KEY_SIZE);
putString(buffer, sslKeySize.toString());
}
String secret = attachable.getAttachment(ProxiedRequestAttachments.SECRET);
if (secret != null) {
buffer.put((byte) ATTR_SECRET);
putString(buffer, secret);
}
if (storeMethod) {
buffer.put((byte) ATTR_STORED_METHOD);
putString(buffer, method.toString());
}
buffer.put((byte) 0xFF);
int dataLength = buffer.position() - 4;
buffer.put(2, (byte) ((dataLength >> 8) & 0xFF));
buffer.put(3, (byte) (dataLength & 0xFF));
}
if (dataSize == 0) {
//no data, just write out this frame and we are done
buffer.flip();
return new SendFrameHeader(pooledHeaderBuffer);
} else if (requestedChunkSize > 0) {
if (isWritesShutdown() && dataInBuffer == 0) {
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
buffer.put((byte) 0x00);
buffer.put((byte) 0x02);
buffer.put((byte) 0x00);
buffer.put((byte) 0x00);
buffer.flip();
return new SendFrameHeader(pooledHeaderBuffer);
}
int remaining = dataInBuffer;
remaining = Math.min(remaining, maxData);
remaining = Math.min(remaining, requestedChunkSize);
int bodySize = remaining + 2;
buffer.put((byte) 0x12);
buffer.put((byte) 0x34);
buffer.put((byte) ((bodySize >> 8) & 0xFF));
buffer.put((byte) (bodySize & 0xFF));
buffer.put((byte) ((remaining >> 8) & 0xFF));
buffer.put((byte) (remaining & 0xFF));
requestedChunkSize = 0;
if (remaining < dataInBuffer) {
dataBuffer.limit(getBuffer().position() + remaining);
buffer.flip();
return new SendFrameHeader(dataInBuffer - remaining, pooledHeaderBuffer, dataSize < 0);
} else {
buffer.flip();
return new SendFrameHeader(0, pooledHeaderBuffer, dataSize < 0);
}
} else {
//chunked. We just write the headers, and leave all the data in the buffer
//they need to send us a read body chunk in order to get any data
buffer.flip();
if (buffer.remaining() == 0) {
pooledHeaderBuffer.close();
return new SendFrameHeader(dataInBuffer, null, true);
}
dataBuffer.limit(dataBuffer.position());
return new SendFrameHeader(dataInBuffer, pooledHeaderBuffer, true);
}
} catch (BufferOverflowException e) {
//TODO: UNDERTOW-901
pooledHeaderBuffer.close();
markBroken();
throw e;
}
}
use of io.undertow.util.HttpString in project undertow by undertow-io.
the class RoutingHandler method addAll.
public synchronized RoutingHandler addAll(RoutingHandler routingHandler) {
for (Entry<HttpString, PathTemplateMatcher<RoutingMatch>> entry : routingHandler.getMatches().entrySet()) {
HttpString method = entry.getKey();
PathTemplateMatcher<RoutingMatch> matcher = matches.get(method);
if (matcher == null) {
matches.put(method, matcher = new PathTemplateMatcher<>());
}
matcher.addAll(entry.getValue());
// PathTemplates which we want to ignore here so it does not crash.
for (PathTemplate template : entry.getValue().getPathTemplates()) {
if (allMethodsMatcher.get(template.getTemplateString()) == null) {
allMethodsMatcher.add(template, new RoutingMatch());
}
}
}
return this;
}
use of io.undertow.util.HttpString in project undertow by undertow-io.
the class MCMPHandler method parseFormData.
/**
* Transform the form data into an intermediate request data which can me used
* by the web manager
*
* @param exchange the http server exchange
* @return
* @throws IOException
*/
RequestData parseFormData(final HttpServerExchange exchange) throws IOException {
// Read post parameters
final FormDataParser parser = parserFactory.createParser(exchange);
final FormData formData = parser.parseBlocking();
final RequestData data = new RequestData();
for (String name : formData) {
final HttpString key = new HttpString(name);
data.add(key, formData.get(name));
}
return data;
}
Aggregations