Search in sources :

Example 11 with HeaderValues

use of io.undertow.util.HeaderValues 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;
}
Also used : HeaderValues(io.undertow.util.HeaderValues) HttpString(io.undertow.util.HttpString) ByteBuffer(java.nio.ByteBuffer) HttpString(io.undertow.util.HttpString)

Example 12 with HeaderValues

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

the class Http2ReceiveListener method handleInitialRequest.

/**
     * Handles the initial request when the exchange was started by a HTTP ugprade.
     *
     *
     * @param initial The initial upgrade request that started the HTTP2 connection
     */
void handleInitialRequest(HttpServerExchange initial, Http2Channel channel) {
    //we have a request
    Http2HeadersStreamSinkChannel sink = channel.createInitialUpgradeResponseStream();
    final Http2ServerConnection connection = new Http2ServerConnection(channel, sink, undertowOptions, bufferSize, rootHandler);
    HeaderMap requestHeaders = new HeaderMap();
    for (HeaderValues hv : initial.getRequestHeaders()) {
        requestHeaders.putAll(hv.getHeaderName(), hv);
    }
    final HttpServerExchange exchange = new HttpServerExchange(connection, requestHeaders, sink.getHeaders(), maxEntitySize);
    connection.setExchange(exchange);
    exchange.setRequestScheme(initial.getRequestScheme());
    exchange.setProtocol(initial.getProtocol());
    exchange.setRequestMethod(initial.getRequestMethod());
    exchange.setQueryString(initial.getQueryString());
    String uri = exchange.getQueryString().isEmpty() ? initial.getRequestURI() : initial.getRequestURI() + '?' + exchange.getQueryString();
    try {
        Connectors.setExchangeRequestPath(exchange, uri, encoding, decode, allowEncodingSlash, decodeBuffer, maxParameters);
    } catch (ParameterLimitException e) {
        exchange.setStatusCode(StatusCodes.BAD_REQUEST);
        exchange.endExchange();
        return;
    }
    SSLSession session = channel.getSslSession();
    if (session != null) {
        connection.setSslSessionInfo(new Http2SslSessionInfo(channel));
    }
    Connectors.terminateRequest(exchange);
    sink.setCompletionListener(new ChannelListener<Http2DataStreamSinkChannel>() {

        @Override
        public void handleEvent(Http2DataStreamSinkChannel channel) {
            Connectors.terminateResponse(exchange);
        }
    });
    Connectors.executeRootHandler(rootHandler, exchange);
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) ParameterLimitException(io.undertow.util.ParameterLimitException) HeaderMap(io.undertow.util.HeaderMap) HeaderValues(io.undertow.util.HeaderValues) SSLSession(javax.net.ssl.SSLSession) HttpString(io.undertow.util.HttpString) Http2DataStreamSinkChannel(io.undertow.protocols.http2.Http2DataStreamSinkChannel)

Example 13 with HeaderValues

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

the class HttpResponseConduit method processStatefulWrite.

/**
     * Handles writing out the header data in the case where is is too big to fit into a buffer. This is a much slower code path.
     */
private int processStatefulWrite(int state, final Object userData, int pos, int len) throws IOException {
    ByteBuffer buffer = pooledBuffer.getBuffer();
    long fiCookie = this.fiCookie;
    int valueIdx = this.valueIdx;
    int charIndex = this.charIndex;
    int length;
    String string = this.string;
    HeaderValues headerValues = this.headerValues;
    int res;
    // BUFFER IS FLIPPED COMING IN
    if (buffer.hasRemaining()) {
        do {
            res = next.write(buffer);
            if (res == 0) {
                return state;
            }
        } while (buffer.hasRemaining());
    }
    buffer.clear();
    HeaderMap headers = exchange.getResponseHeaders();
    // BUFFER IS NOW EMPTY FOR FILLING
    for (; ; ) {
        switch(state) {
            case STATE_HDR_NAME:
                {
                    final HttpString headerName = headerValues.getHeaderName();
                    length = headerName.length();
                    while (charIndex < length) {
                        if (buffer.hasRemaining()) {
                            buffer.put(headerName.byteAt(charIndex++));
                        } else {
                            buffer.flip();
                            do {
                                res = next.write(buffer);
                                if (res == 0) {
                                    this.string = string;
                                    this.headerValues = headerValues;
                                    this.charIndex = charIndex;
                                    this.fiCookie = fiCookie;
                                    this.valueIdx = valueIdx;
                                    return STATE_HDR_NAME;
                                }
                            } while (buffer.hasRemaining());
                            buffer.clear();
                        }
                    }
                // fall thru
                }
            case STATE_HDR_D:
                {
                    if (!buffer.hasRemaining()) {
                        buffer.flip();
                        do {
                            res = next.write(buffer);
                            if (res == 0) {
                                this.string = string;
                                this.headerValues = headerValues;
                                this.charIndex = charIndex;
                                this.fiCookie = fiCookie;
                                this.valueIdx = valueIdx;
                                return STATE_HDR_D;
                            }
                        } while (buffer.hasRemaining());
                        buffer.clear();
                    }
                    buffer.put((byte) ':');
                // fall thru
                }
            case STATE_HDR_DS:
                {
                    if (!buffer.hasRemaining()) {
                        buffer.flip();
                        do {
                            res = next.write(buffer);
                            if (res == 0) {
                                this.string = string;
                                this.headerValues = headerValues;
                                this.charIndex = charIndex;
                                this.fiCookie = fiCookie;
                                this.valueIdx = valueIdx;
                                return STATE_HDR_DS;
                            }
                        } while (buffer.hasRemaining());
                        buffer.clear();
                    }
                    buffer.put((byte) ' ');
                    //if (valueIterator == null) {
                    //    valueIterator = exchange.getResponseHeaders().get(headerName).iterator();
                    //}
                    string = headerValues.get(valueIdx++);
                    charIndex = 0;
                // fall thru
                }
            case STATE_HDR_VAL:
                {
                    length = string.length();
                    while (charIndex < length) {
                        if (buffer.hasRemaining()) {
                            buffer.put((byte) string.charAt(charIndex++));
                        } else {
                            buffer.flip();
                            do {
                                res = next.write(buffer);
                                if (res == 0) {
                                    this.string = string;
                                    this.headerValues = headerValues;
                                    this.charIndex = charIndex;
                                    this.fiCookie = fiCookie;
                                    this.valueIdx = valueIdx;
                                    return STATE_HDR_VAL;
                                }
                            } while (buffer.hasRemaining());
                            buffer.clear();
                        }
                    }
                    charIndex = 0;
                    if (valueIdx == headerValues.size()) {
                        if (!buffer.hasRemaining()) {
                            if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                                return STATE_HDR_EOL_CR;
                        }
                        // CR
                        buffer.put((byte) 13);
                        if (!buffer.hasRemaining()) {
                            if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                                return STATE_HDR_EOL_LF;
                        }
                        // LF
                        buffer.put((byte) 10);
                        if ((fiCookie = headers.fiNextNonEmpty(fiCookie)) != -1L) {
                            headerValues = headers.fiCurrent(fiCookie);
                            valueIdx = 0;
                            state = STATE_HDR_NAME;
                            break;
                        } else {
                            if (!buffer.hasRemaining()) {
                                if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                                    return STATE_HDR_FINAL_CR;
                            }
                            // CR
                            buffer.put((byte) 13);
                            if (!buffer.hasRemaining()) {
                                if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                                    return STATE_HDR_FINAL_LF;
                            }
                            // LF
                            buffer.put((byte) 10);
                            this.fiCookie = -1;
                            this.valueIdx = 0;
                            this.string = null;
                            buffer.flip();
                            //for performance reasons we use a gather write if there is user data
                            if (userData == null) {
                                do {
                                    res = next.write(buffer);
                                    if (res == 0) {
                                        return STATE_BUF_FLUSH;
                                    }
                                } while (buffer.hasRemaining());
                            } else if (userData instanceof ByteBuffer) {
                                ByteBuffer[] b = { buffer, (ByteBuffer) userData };
                                do {
                                    long r = next.write(b, 0, b.length);
                                    if (r == 0 && buffer.hasRemaining()) {
                                        return STATE_BUF_FLUSH;
                                    }
                                } while (buffer.hasRemaining());
                            } else {
                                ByteBuffer[] b = new ByteBuffer[1 + len];
                                b[0] = buffer;
                                System.arraycopy(userData, pos, b, 1, len);
                                do {
                                    long r = next.write(b, 0, b.length);
                                    if (r == 0 && buffer.hasRemaining()) {
                                        return STATE_BUF_FLUSH;
                                    }
                                } while (buffer.hasRemaining());
                            }
                            bufferDone();
                            return STATE_BODY;
                        }
                    // not reached
                    }
                // fall thru
                }
            // Clean-up states
            case STATE_HDR_EOL_CR:
                {
                    if (!buffer.hasRemaining()) {
                        if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                            return STATE_HDR_EOL_CR;
                    }
                    // CR
                    buffer.put((byte) 13);
                }
            case STATE_HDR_EOL_LF:
                {
                    if (!buffer.hasRemaining()) {
                        if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                            return STATE_HDR_EOL_LF;
                    }
                    // LF
                    buffer.put((byte) 10);
                    if (valueIdx < headerValues.size()) {
                        state = STATE_HDR_NAME;
                        break;
                    } else if ((fiCookie = headers.fiNextNonEmpty(fiCookie)) != -1L) {
                        headerValues = headers.fiCurrent(fiCookie);
                        valueIdx = 0;
                        state = STATE_HDR_NAME;
                        break;
                    }
                // fall thru
                }
            case STATE_HDR_FINAL_CR:
                {
                    if (!buffer.hasRemaining()) {
                        if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                            return STATE_HDR_FINAL_CR;
                    }
                    // CR
                    buffer.put((byte) 13);
                // fall thru
                }
            case STATE_HDR_FINAL_LF:
                {
                    if (!buffer.hasRemaining()) {
                        if (flushHeaderBuffer(buffer, string, headerValues, charIndex, fiCookie, valueIdx))
                            return STATE_HDR_FINAL_LF;
                    }
                    // LF
                    buffer.put((byte) 10);
                    this.fiCookie = -1L;
                    this.valueIdx = 0;
                    this.string = null;
                    buffer.flip();
                    //for performance reasons we use a gather write if there is user data
                    if (userData == null) {
                        do {
                            res = next.write(buffer);
                            if (res == 0) {
                                return STATE_BUF_FLUSH;
                            }
                        } while (buffer.hasRemaining());
                    } else if (userData instanceof ByteBuffer) {
                        ByteBuffer[] b = { buffer, (ByteBuffer) userData };
                        do {
                            long r = next.write(b, 0, b.length);
                            if (r == 0 && buffer.hasRemaining()) {
                                return STATE_BUF_FLUSH;
                            }
                        } while (buffer.hasRemaining());
                    } else {
                        ByteBuffer[] b = new ByteBuffer[1 + len];
                        b[0] = buffer;
                        System.arraycopy(userData, pos, b, 1, len);
                        do {
                            long r = next.write(b, 0, b.length);
                            if (r == 0 && buffer.hasRemaining()) {
                                return STATE_BUF_FLUSH;
                            }
                        } while (buffer.hasRemaining());
                    }
                // fall thru
                }
            case STATE_BUF_FLUSH:
                {
                    // buffer was successfully flushed above
                    bufferDone();
                    return STATE_BODY;
                }
            default:
                {
                    throw new IllegalStateException();
                }
        }
    }
}
Also used : HeaderMap(io.undertow.util.HeaderMap) HeaderValues(io.undertow.util.HeaderValues) HttpString(io.undertow.util.HttpString) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) HttpString(io.undertow.util.HttpString)

Example 14 with HeaderValues

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

the class ChunkedRequestTrailersTestCase method setup.

@BeforeClass
public static void setup() {
    final BlockingHandler blockingHandler = new BlockingHandler();
    existing = DefaultServer.getUndertowOptions();
    DefaultServer.setUndertowOptions(OptionMap.create(UndertowOptions.ALWAYS_SET_DATE, false));
    DefaultServer.setRootHandler(blockingHandler);
    blockingHandler.setRootHandler(new HttpHandler() {

        @Override
        public void handleRequest(final HttpServerExchange exchange) {
            try {
                if (connection == null) {
                    connection = (HttpServerConnection) exchange.getConnection();
                } else if (!DefaultServer.isProxy() && connection != exchange.getConnection()) {
                    exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
                    final OutputStream outputStream = exchange.getOutputStream();
                    outputStream.write("Connection not persistent".getBytes());
                    outputStream.close();
                    return;
                }
                final OutputStream outputStream = exchange.getOutputStream();
                final InputStream inputStream = exchange.getInputStream();
                String m = HttpClientUtils.readResponse(inputStream);
                Assert.assertEquals("abcdefghi", m);
                HeaderMap headers = exchange.getAttachment(HttpAttachments.REQUEST_TRAILERS);
                for (HeaderValues header : headers) {
                    for (String val : header) {
                        outputStream.write(header.getHeaderName().toString().getBytes());
                        outputStream.write(": ".getBytes());
                        outputStream.write(val.getBytes());
                        outputStream.write("\r\n".getBytes());
                    }
                }
                inputStream.close();
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
    });
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) HttpHandler(io.undertow.server.HttpHandler) HttpServerConnection(io.undertow.server.protocol.http.HttpServerConnection) HeaderMap(io.undertow.util.HeaderMap) InputStream(java.io.InputStream) OutputStream(java.io.OutputStream) HeaderValues(io.undertow.util.HeaderValues) IOException(java.io.IOException) BeforeClass(org.junit.BeforeClass)

Example 15 with HeaderValues

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

the class CrawlerBindingListener method handleRequest.

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
    boolean isBot = false;
    String sessionId = null;
    String clientIp = null;
    ServletRequestContext src = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
    // If the incoming request has a valid session ID, no action is required
    if (src.getOriginalRequest().getSession(false) == null) {
        // Is this a crawler - check the UA headers
        HeaderValues userAgentHeaders = exchange.getRequestHeaders().get(Headers.USER_AGENT);
        if (userAgentHeaders != null) {
            Iterator<String> uaHeaders = userAgentHeaders.iterator();
            String uaHeader = null;
            if (uaHeaders.hasNext()) {
                uaHeader = uaHeaders.next();
            }
            // If more than one UA header - assume not a bot
            if (uaHeader != null && !uaHeaders.hasNext()) {
                if (uaPattern.matcher(uaHeader).matches()) {
                    isBot = true;
                    if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
                        UndertowLogger.REQUEST_LOGGER.debug(exchange + ": Bot found. UserAgent=" + uaHeader);
                    }
                }
            }
            // If this is a bot, is the session ID known?
            if (isBot) {
                clientIp = src.getServletRequest().getRemoteAddr();
                sessionId = clientIpSessionId.get(clientIp);
                if (sessionId != null) {
                    src.setOverridenSessionId(sessionId);
                    if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
                        UndertowLogger.REQUEST_LOGGER.debug(exchange + ": SessionID=" + sessionId);
                    }
                }
            }
        }
    }
    if (isBot) {
        final String finalSessionId = sessionId;
        final String finalClientId = clientIp;
        exchange.addExchangeCompleteListener(new ExchangeCompletionListener() {

            @Override
            public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) {
                try {
                    ServletRequestContext src = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
                    if (finalSessionId == null) {
                        // Has bot just created a session, if so make a note of it
                        HttpSession s = src.getOriginalRequest().getSession(false);
                        if (s != null) {
                            clientIpSessionId.put(finalClientId, s.getId());
                            sessionIdClientIp.put(s.getId(), finalClientId);
                            // #valueUnbound() will be called on session expiration
                            s.setAttribute(SESSION_ATTRIBUTE_NAME, new CrawlerBindingListener(clientIpSessionId, sessionIdClientIp));
                            s.setMaxInactiveInterval(config.getSessionInactiveInterval());
                            if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
                                UndertowLogger.REQUEST_LOGGER.debug(exchange + ": New bot session. SessionID=" + s.getId());
                            }
                        }
                    } else {
                        if (UndertowLogger.REQUEST_LOGGER.isDebugEnabled()) {
                            UndertowLogger.REQUEST_LOGGER.debug(exchange + ": Bot session accessed. SessionID=" + finalSessionId);
                        }
                    }
                } finally {
                    nextListener.proceed();
                }
            }
        });
    }
    next.handleRequest(exchange);
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) HttpSession(javax.servlet.http.HttpSession) HeaderValues(io.undertow.util.HeaderValues) ExchangeCompletionListener(io.undertow.server.ExchangeCompletionListener)

Aggregations

HeaderValues (io.undertow.util.HeaderValues)16 HeaderMap (io.undertow.util.HeaderMap)10 HttpString (io.undertow.util.HttpString)9 HttpServerExchange (io.undertow.server.HttpServerExchange)6 ByteBuffer (java.nio.ByteBuffer)4 PooledByteBuffer (io.undertow.connector.PooledByteBuffer)3 IOException (java.io.IOException)3 HttpSession (javax.servlet.http.HttpSession)3 ExchangeCompletionListener (io.undertow.server.ExchangeCompletionListener)2 HttpHandler (io.undertow.server.HttpHandler)2 Session (io.undertow.server.session.Session)2 HttpSessionImpl (io.undertow.servlet.spec.HttpSessionImpl)2 ImmediatePooledByteBuffer (io.undertow.util.ImmediatePooledByteBuffer)2 InputStream (java.io.InputStream)2 Map (java.util.Map)2 BeforeClass (org.junit.BeforeClass)2 AuthenticationTypeExchangeAttribute (io.undertow.attribute.AuthenticationTypeExchangeAttribute)1 CompositeExchangeAttribute (io.undertow.attribute.CompositeExchangeAttribute)1 ConstantExchangeAttribute (io.undertow.attribute.ConstantExchangeAttribute)1 CookieAttribute (io.undertow.attribute.CookieAttribute)1