Search in sources :

Example 6 with HeaderValues

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

the class SavedRequest method trySaveRequest.

public static void trySaveRequest(final HttpServerExchange exchange) {
    int maxSize = exchange.getConnection().getUndertowOptions().get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, 16384);
    if (maxSize > 0) {
        //if this request has a body try and cache the response
        if (!exchange.isRequestComplete()) {
            final long requestContentLength = exchange.getRequestContentLength();
            if (requestContentLength > maxSize) {
                UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
                //failed to save the request, we just return
                return;
            }
            //TODO: we should really be used pooled buffers
            //TODO: we should probably limit the number of saved requests at any given time
            byte[] buffer = new byte[maxSize];
            int read = 0;
            int res = 0;
            InputStream in = exchange.getInputStream();
            try {
                while ((res = in.read(buffer, read, buffer.length - read)) > 0) {
                    read += res;
                    if (read == maxSize) {
                        UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
                        //failed to save the request, we just return
                        return;
                    }
                }
                HeaderMap headers = new HeaderMap();
                for (HeaderValues entry : exchange.getRequestHeaders()) {
                    if (entry.getHeaderName().equals(Headers.CONTENT_LENGTH) || entry.getHeaderName().equals(Headers.TRANSFER_ENCODING) || entry.getHeaderName().equals(Headers.CONNECTION)) {
                        continue;
                    }
                    headers.putAll(entry.getHeaderName(), entry);
                }
                SavedRequest request = new SavedRequest(buffer, read, exchange.getRequestMethod(), exchange.getRelativePath(), exchange.getRequestHeaders());
                final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
                HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true);
                Session underlyingSession;
                if (System.getSecurityManager() == null) {
                    underlyingSession = session.getSession();
                } else {
                    underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
                }
                underlyingSession.setAttribute(SESSION_KEY, request);
            } catch (IOException e) {
                UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
            }
        }
    }
}
Also used : HeaderMap(io.undertow.util.HeaderMap) HttpSessionImpl(io.undertow.servlet.spec.HttpSessionImpl) InputStream(java.io.InputStream) HeaderValues(io.undertow.util.HeaderValues) ServletRequestContext(io.undertow.servlet.handlers.ServletRequestContext) IOException(java.io.IOException) HttpSession(javax.servlet.http.HttpSession) Session(io.undertow.server.session.Session)

Example 7 with HeaderValues

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

the class SavedRequest method tryRestoreRequest.

public static void tryRestoreRequest(final HttpServerExchange exchange, HttpSession session) {
    if (session instanceof HttpSessionImpl) {
        Session underlyingSession;
        if (System.getSecurityManager() == null) {
            underlyingSession = ((HttpSessionImpl) session).getSession();
        } else {
            underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
        }
        SavedRequest request = (SavedRequest) underlyingSession.getAttribute(SESSION_KEY);
        if (request != null) {
            if (request.requestPath.equals(exchange.getRelativePath()) && exchange.isRequestComplete()) {
                UndertowLogger.REQUEST_LOGGER.debugf("restoring request body for request to %s", request.requestPath);
                exchange.setRequestMethod(request.method);
                Connectors.ungetRequestBytes(exchange, new ImmediatePooledByteBuffer(ByteBuffer.wrap(request.data, 0, request.dataLength)));
                underlyingSession.removeAttribute(SESSION_KEY);
                //clear the existing header map of everything except the connection header
                //TODO: are there other headers we should preserve?
                Iterator<HeaderValues> headerIterator = exchange.getRequestHeaders().iterator();
                while (headerIterator.hasNext()) {
                    HeaderValues header = headerIterator.next();
                    if (!header.getHeaderName().equals(Headers.CONNECTION)) {
                        headerIterator.remove();
                    }
                }
                for (Map.Entry<HttpString, List<String>> header : request.headerMap.entrySet()) {
                    exchange.getRequestHeaders().putAll(header.getKey(), header.getValue());
                }
            }
        }
    }
}
Also used : HttpSessionImpl(io.undertow.servlet.spec.HttpSessionImpl) HeaderValues(io.undertow.util.HeaderValues) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) HeaderMap(io.undertow.util.HeaderMap) Map(java.util.Map) HttpSession(javax.servlet.http.HttpSession) Session(io.undertow.server.session.Session) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) HttpString(io.undertow.util.HttpString)

Example 8 with HeaderValues

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

the class HttpResponseConduit method processWrite.

/**
     * Handles writing out the header data. It can also take a byte buffer of user
     * data, to enable both user data and headers to be written out in a single operation,
     * which has a noticeable performance impact.
     * <p/>
     * It is up to the caller to note the current position of this buffer before and after they
     * call this method, and use this to figure out how many bytes (if any) have been written.
     *
     * @param state
     * @param userData
     * @return
     * @throws IOException
     */
private int processWrite(int state, final Object userData, int pos, int length) throws IOException {
    if (done || exchange == null) {
        throw new ClosedChannelException();
    }
    try {
        assert state != STATE_BODY;
        if (state == STATE_BUF_FLUSH) {
            final ByteBuffer byteBuffer = pooledBuffer.getBuffer();
            do {
                long res = 0;
                ByteBuffer[] data;
                if (userData == null || length == 0) {
                    res = next.write(byteBuffer);
                } else if (userData instanceof ByteBuffer) {
                    data = writevBuffer;
                    if (data == null) {
                        data = writevBuffer = new ByteBuffer[2];
                    }
                    data[0] = byteBuffer;
                    data[1] = (ByteBuffer) userData;
                    res = next.write(data, 0, 2);
                } else {
                    data = writevBuffer;
                    if (data == null || data.length < length + 1) {
                        data = writevBuffer = new ByteBuffer[length + 1];
                    }
                    data[0] = byteBuffer;
                    System.arraycopy(userData, pos, data, 1, length);
                    res = next.write(data, 0, data.length);
                }
                if (res == 0) {
                    return STATE_BUF_FLUSH;
                }
            } while (byteBuffer.hasRemaining());
            bufferDone();
            return STATE_BODY;
        } else if (state != STATE_START) {
            return processStatefulWrite(state, userData, pos, length);
        }
        //merge the cookies into the header map
        Connectors.flattenCookies(exchange);
        if (pooledBuffer == null) {
            pooledBuffer = pool.allocate();
        }
        ByteBuffer buffer = pooledBuffer.getBuffer();
        assert buffer.remaining() >= 50;
        exchange.getProtocol().appendTo(buffer);
        buffer.put((byte) ' ');
        int code = exchange.getStatusCode();
        assert 999 >= code && code >= 100;
        buffer.put((byte) (code / 100 + '0'));
        buffer.put((byte) (code / 10 % 10 + '0'));
        buffer.put((byte) (code % 10 + '0'));
        buffer.put((byte) ' ');
        String string = exchange.getReasonPhrase();
        if (string == null) {
            string = StatusCodes.getReason(code);
        }
        if (string.length() > buffer.remaining()) {
            pooledBuffer.close();
            pooledBuffer = null;
            truncateWrites();
            throw UndertowMessages.MESSAGES.reasonPhraseToLargeForBuffer(string);
        }
        writeString(buffer, string);
        buffer.put((byte) '\r').put((byte) '\n');
        int remaining = buffer.remaining();
        HeaderMap headers = exchange.getResponseHeaders();
        long fiCookie = headers.fastIterateNonEmpty();
        while (fiCookie != -1) {
            HeaderValues headerValues = headers.fiCurrent(fiCookie);
            HttpString header = headerValues.getHeaderName();
            int headerSize = header.length();
            int valueIdx = 0;
            while (valueIdx < headerValues.size()) {
                remaining -= (headerSize + 2);
                if (remaining < 0) {
                    this.fiCookie = fiCookie;
                    this.string = string;
                    this.headerValues = headerValues;
                    this.valueIdx = valueIdx;
                    this.charIndex = 0;
                    this.state = STATE_HDR_NAME;
                    buffer.flip();
                    return processStatefulWrite(STATE_HDR_NAME, userData, pos, length);
                }
                header.appendTo(buffer);
                buffer.put((byte) ':').put((byte) ' ');
                string = headerValues.get(valueIdx++);
                remaining -= (string.length() + 2);
                if (remaining < 2) {
                    //we use 2 here, to make sure we always have room for the final \r\n
                    this.fiCookie = fiCookie;
                    this.string = string;
                    this.headerValues = headerValues;
                    this.valueIdx = valueIdx;
                    this.charIndex = 0;
                    this.state = STATE_HDR_VAL;
                    buffer.flip();
                    return processStatefulWrite(STATE_HDR_VAL, userData, pos, length);
                }
                writeString(buffer, string);
                buffer.put((byte) '\r').put((byte) '\n');
            }
            fiCookie = headers.fiNextNonEmpty(fiCookie);
        }
        buffer.put((byte) '\r').put((byte) '\n');
        buffer.flip();
        do {
            long res = 0;
            ByteBuffer[] data;
            if (userData == null) {
                res = next.write(buffer);
            } else if (userData instanceof ByteBuffer) {
                data = writevBuffer;
                if (data == null) {
                    data = writevBuffer = new ByteBuffer[2];
                }
                data[0] = buffer;
                data[1] = (ByteBuffer) userData;
                res = next.write(data, 0, 2);
            } else {
                data = writevBuffer;
                if (data == null || data.length < length + 1) {
                    data = writevBuffer = new ByteBuffer[length + 1];
                }
                data[0] = buffer;
                System.arraycopy(userData, pos, data, 1, length);
                res = next.write(data, 0, length + 1);
            }
            if (res == 0) {
                return STATE_BUF_FLUSH;
            }
        } while (buffer.hasRemaining());
        bufferDone();
        return STATE_BODY;
    } catch (IOException | RuntimeException e) {
        //WFLY-4696, just to be safe
        if (pooledBuffer != null) {
            pooledBuffer.close();
            pooledBuffer = null;
        }
        throw e;
    }
}
Also used : ClosedChannelException(java.nio.channels.ClosedChannelException) HeaderMap(io.undertow.util.HeaderMap) HeaderValues(io.undertow.util.HeaderValues) HttpString(io.undertow.util.HttpString) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) HttpString(io.undertow.util.HttpString)

Example 9 with HeaderValues

use of io.undertow.util.HeaderValues in project indy by Commonjava.

the class HeaderDebugger method handleRequest.

@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    if (logger.isTraceEnabled()) {
        logger.trace("{} {}", exchange.getRequestMethod(), exchange.getRequestPath());
        logger.trace("FROM: {}", exchange.getSourceAddress());
        final HeaderMap headerMap = exchange.getRequestHeaders();
        final Collection<HttpString> names = headerMap.getHeaderNames();
        logger.trace("HEADERS: ");
        for (final HttpString name : names) {
            final HeaderValues values = headerMap.get(name);
            for (final String value : values) {
                logger.trace("{}: {}", name, value);
            }
        }
        logger.trace("COOKIES: ");
        final Map<String, Cookie> cookies = exchange.getRequestCookies();
        for (final String key : cookies.keySet()) {
            final Cookie cookie = cookies.get(key);
            if (cookie == null) {
                continue;
            }
            logger.trace("Cookie({}):\n  Domain: {}\n  Name: {}\n  Path: {}\n  Value: {}\n  Expires: {}\n  Max-Age: {}\n  Comment: {}\n  Version: {}\n\n", key, cookie.getDomain(), cookie.getName(), cookie.getPath(), cookie.getValue(), cookie.getExpires(), cookie.getMaxAge(), cookie.getComment(), cookie.getVersion());
        }
    }
    handler.handleRequest(exchange);
}
Also used : Cookie(io.undertow.server.handlers.Cookie) HeaderMap(io.undertow.util.HeaderMap) HeaderValues(io.undertow.util.HeaderValues) HttpString(io.undertow.util.HttpString) HttpString(io.undertow.util.HttpString)

Example 10 with HeaderValues

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

the class ChunkedStreamSinkConduit method createLastChunk.

private void createLastChunk(final boolean writeFinal) throws UnsupportedEncodingException {
    PooledByteBuffer lastChunkBufferPooled = bufferPool.allocate();
    ByteBuffer lastChunkBuffer = lastChunkBufferPooled.getBuffer();
    if (writeFinal) {
        lastChunkBuffer.put(CRLF);
    } else if (chunkingSepBuffer.hasRemaining()) {
        //the end of chunk /r/n has not been written yet
        //just add it to this buffer to make managing state easier
        lastChunkBuffer.put(chunkingSepBuffer);
    }
    lastChunkBuffer.put(LAST_CHUNK);
    //we just assume it will fit
    HeaderMap trailers = attachable.getAttachment(HttpAttachments.RESPONSE_TRAILERS);
    if (trailers != null && trailers.size() != 0) {
        for (HeaderValues trailer : trailers) {
            for (String val : trailer) {
                trailer.getHeaderName().appendTo(lastChunkBuffer);
                lastChunkBuffer.put((byte) ':');
                lastChunkBuffer.put((byte) ' ');
                lastChunkBuffer.put(val.getBytes(StandardCharsets.US_ASCII));
                lastChunkBuffer.put(CRLF);
            }
        }
        lastChunkBuffer.put(CRLF);
    } else {
        lastChunkBuffer.put(CRLF);
    }
    //horrible hack
    //there is a situation where we can get a buffer leak here if the connection is terminated abnormaly
    //this should be fixed once this channel has its lifecycle tied to the connection, same as fixed length
    lastChunkBuffer.flip();
    ByteBuffer data = ByteBuffer.allocate(lastChunkBuffer.remaining());
    data.put(lastChunkBuffer);
    data.flip();
    this.lastChunkBuffer = new ImmediatePooledByteBuffer(data);
    lastChunkBufferPooled.close();
}
Also used : HeaderMap(io.undertow.util.HeaderMap) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) HeaderValues(io.undertow.util.HeaderValues) ByteBuffer(java.nio.ByteBuffer) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer) PooledByteBuffer(io.undertow.connector.PooledByteBuffer) ImmediatePooledByteBuffer(io.undertow.util.ImmediatePooledByteBuffer)

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