Search in sources :

Example 31 with HttpField

use of org.eclipse.jetty.http.HttpField in project jetty.project by eclipse.

the class GzipHandler method handle.

/* ------------------------------------------------------------ */
/**
     * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
    ServletContext context = baseRequest.getServletContext();
    String path = context == null ? baseRequest.getRequestURI() : URIUtil.addPaths(baseRequest.getServletPath(), baseRequest.getPathInfo());
    LOG.debug("{} handle {} in {}", this, baseRequest, context);
    if (!_dispatchers.contains(baseRequest.getDispatcherType())) {
        LOG.debug("{} excluded by dispatcherType {}", this, baseRequest.getDispatcherType());
        _handler.handle(target, baseRequest, request, response);
        return;
    }
    // Handle request inflation
    if (_inflateBufferSize > 0) {
        HttpField ce = baseRequest.getHttpFields().getField(HttpHeader.CONTENT_ENCODING);
        if (ce != null && "gzip".equalsIgnoreCase(ce.getValue())) {
            // TODO should check ce.contains and then remove just the gzip encoding
            baseRequest.getHttpFields().remove(HttpHeader.CONTENT_ENCODING);
            baseRequest.getHttpFields().add(new HttpField("X-Content-Encoding", ce.getValue()));
            baseRequest.getHttpInput().addInterceptor(new GzipHttpInputInterceptor(baseRequest.getHttpChannel().getByteBufferPool(), _inflateBufferSize));
        }
    }
    // Are we already being gzipped?
    HttpOutput out = baseRequest.getResponse().getHttpOutput();
    HttpOutput.Interceptor interceptor = out.getInterceptor();
    while (interceptor != null) {
        if (interceptor instanceof GzipHttpOutputInterceptor) {
            LOG.debug("{} already intercepting {}", this, request);
            _handler.handle(target, baseRequest, request, response);
            return;
        }
        interceptor = interceptor.getNextInterceptor();
    }
    // If not a supported method - no Vary because no matter what client, this URI is always excluded
    if (!_methods.test(baseRequest.getMethod())) {
        LOG.debug("{} excluded by method {}", this, request);
        _handler.handle(target, baseRequest, request, response);
        return;
    }
    // Use pathInfo because this is be
    if (!isPathGzipable(path)) {
        LOG.debug("{} excluded by path {}", this, request);
        _handler.handle(target, baseRequest, request, response);
        return;
    }
    // Exclude non compressible mime-types known from URI extension. - no Vary because no matter what client, this URI is always excluded
    String mimeType = context == null ? MimeTypes.getDefaultMimeByExtension(path) : context.getMimeType(path);
    if (mimeType != null) {
        mimeType = MimeTypes.getContentTypeWithoutCharset(mimeType);
        if (!isMimeTypeGzipable(mimeType)) {
            LOG.debug("{} excluded by path suffix mime type {}", this, request);
            // handle normally without setting vary header
            _handler.handle(target, baseRequest, request, response);
            return;
        }
    }
    if (_checkGzExists && context != null) {
        String realpath = request.getServletContext().getRealPath(path);
        if (realpath != null) {
            File gz = new File(realpath + ".gz");
            if (gz.exists()) {
                LOG.debug("{} gzip exists {}", this, request);
                // allow default servlet to handle
                _handler.handle(target, baseRequest, request, response);
                return;
            }
        }
    }
    // Special handling for etags
    String etag = baseRequest.getHttpFields().get(HttpHeader.IF_NONE_MATCH);
    if (etag != null) {
        int i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote);
        if (i > 0) {
            baseRequest.setAttribute("o.e.j.s.h.gzip.GzipHandler.etag", etag);
            while (i >= 0) {
                etag = etag.substring(0, i) + etag.substring(i + CompressedContentFormat.GZIP._etag.length());
                i = etag.indexOf(CompressedContentFormat.GZIP._etagQuote, i);
            }
            baseRequest.getHttpFields().put(new HttpField(HttpHeader.IF_NONE_MATCH, etag));
        }
    }
    HttpOutput.Interceptor orig_interceptor = out.getInterceptor();
    try {
        // install interceptor and handle
        out.setInterceptor(new GzipHttpOutputInterceptor(this, getVaryField(), baseRequest.getHttpChannel(), orig_interceptor, isSyncFlush()));
        if (_handler != null)
            _handler.handle(target, baseRequest, request, response);
    } finally {
        // reset interceptor if request not handled
        if (!baseRequest.isHandled() && !baseRequest.isAsyncStarted())
            out.setInterceptor(orig_interceptor);
    }
}
Also used : HttpField(org.eclipse.jetty.http.HttpField) ServletContext(javax.servlet.ServletContext) HttpOutput(org.eclipse.jetty.server.HttpOutput) File(java.io.File)

Example 32 with HttpField

use of org.eclipse.jetty.http.HttpField in project jetty.project by eclipse.

the class HttpClientTest method testAllHeadersDiscarded.

@Test
public void testAllHeadersDiscarded() throws Exception {
    start(new EmptyServerHandler());
    int count = 10;
    final CountDownLatch latch = new CountDownLatch(count);
    for (int i = 0; i < count; ++i) {
        client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).send(new Response.Listener.Adapter() {

            @Override
            public boolean onHeader(Response response, HttpField field) {
                return false;
            }

            @Override
            public void onComplete(Result result) {
                if (result.isSucceeded())
                    latch.countDown();
            }
        });
    }
    Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));
}
Also used : ContentResponse(org.eclipse.jetty.client.api.ContentResponse) Response(org.eclipse.jetty.client.api.Response) HttpServletResponse(javax.servlet.http.HttpServletResponse) FutureResponseListener(org.eclipse.jetty.client.util.FutureResponseListener) BufferingResponseListener(org.eclipse.jetty.client.util.BufferingResponseListener) HttpField(org.eclipse.jetty.http.HttpField) CountDownLatch(java.util.concurrent.CountDownLatch) EndPoint(org.eclipse.jetty.io.EndPoint) Result(org.eclipse.jetty.client.api.Result) Test(org.junit.Test)

Example 33 with HttpField

use of org.eclipse.jetty.http.HttpField in project jetty.project by eclipse.

the class HttpClientURITest method testIDNRedirect.

@Test
public void testIDNRedirect() throws Exception {
    // Internationalized Domain Name.
    // String exampleHost = scheme + "://пример.рф";
    String exampleHost = scheme + "://킿톀킸킼킵톀.톀톄";
    String incorrectlyDecoded = new String(exampleHost.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
    // Simple server that only parses clear-text HTTP/1.1.
    IDNRedirectServer server = new IDNRedirectServer(exampleHost);
    server.start();
    try {
        startClient();
        ContentResponse response = client.newRequest("localhost", server.getLocalPort()).timeout(5, TimeUnit.SECONDS).followRedirects(false).send();
        HttpField location = response.getHeaders().getField(HttpHeader.LOCATION);
        Assert.assertEquals(incorrectlyDecoded, location.getValue());
        expectedException.expect(ExecutionException.class);
        expectedException.expectCause(instanceOf(IllegalArgumentException.class));
        client.newRequest("localhost", server.getLocalPort()).timeout(5, TimeUnit.SECONDS).followRedirects(true).send();
    } finally {
        server.stop();
    }
}
Also used : ContentResponse(org.eclipse.jetty.client.api.ContentResponse) HttpField(org.eclipse.jetty.http.HttpField) Test(org.junit.Test)

Example 34 with HttpField

use of org.eclipse.jetty.http.HttpField in project jetty.project by eclipse.

the class PushCacheFilter method doFilter.

@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest request = (HttpServletRequest) req;
    Request jettyRequest = Request.getBaseRequest(request);
    if (HttpVersion.fromString(request.getProtocol()).getVersion() < 20 || !HttpMethod.GET.is(request.getMethod()) || !jettyRequest.isPushSupported()) {
        chain.doFilter(req, resp);
        return;
    }
    long now = System.nanoTime();
    // Iterating over fields is more efficient than multiple gets
    HttpFields fields = jettyRequest.getHttpFields();
    boolean conditional = false;
    String referrer = null;
    loop: for (int i = 0; i < fields.size(); i++) {
        HttpField field = fields.getField(i);
        HttpHeader header = field.getHeader();
        if (header == null)
            continue;
        switch(header) {
            case IF_MATCH:
            case IF_MODIFIED_SINCE:
            case IF_NONE_MATCH:
            case IF_UNMODIFIED_SINCE:
                conditional = true;
                break loop;
            case REFERER:
                referrer = field.getValue();
                break;
            default:
                break;
        }
    }
    if (LOG.isDebugEnabled())
        LOG.debug("{} {} referrer={} conditional={}", request.getMethod(), request.getRequestURI(), referrer, conditional);
    String path = request.getRequestURI();
    String query = request.getQueryString();
    if (_useQueryInKey && query != null)
        path += "?" + query;
    if (referrer != null) {
        HttpURI referrerURI = new HttpURI(referrer);
        String host = referrerURI.getHost();
        int port = referrerURI.getPort();
        if (port <= 0)
            port = request.isSecure() ? 443 : 80;
        boolean referredFromHere = _hosts.size() > 0 ? _hosts.contains(host) : host.equals(request.getServerName());
        referredFromHere &= _ports.size() > 0 ? _ports.contains(port) : port == request.getServerPort();
        if (referredFromHere) {
            if (HttpMethod.GET.is(request.getMethod())) {
                String referrerPath = _useQueryInKey ? referrerURI.getPathQuery() : referrerURI.getPath();
                if (referrerPath == null)
                    referrerPath = "/";
                if (referrerPath.startsWith(request.getContextPath() + "/")) {
                    if (!referrerPath.equals(path)) {
                        PrimaryResource primaryResource = _cache.get(referrerPath);
                        if (primaryResource != null) {
                            long primaryTimestamp = primaryResource._timestamp.get();
                            if (primaryTimestamp != 0) {
                                if (now - primaryTimestamp < TimeUnit.MILLISECONDS.toNanos(_associatePeriod)) {
                                    Set<String> associated = primaryResource._associated;
                                    // Not strictly concurrent-safe, just best effort to limit associations.
                                    if (associated.size() <= _maxAssociations) {
                                        if (associated.add(path)) {
                                            if (LOG.isDebugEnabled())
                                                LOG.debug("Associated {} to {}", path, referrerPath);
                                        }
                                    } else {
                                        if (LOG.isDebugEnabled())
                                            LOG.debug("Not associated {} to {}, exceeded max associations of {}", path, referrerPath, _maxAssociations);
                                    }
                                } else {
                                    if (LOG.isDebugEnabled())
                                        LOG.debug("Not associated {} to {}, outside associate period of {}ms", path, referrerPath, _associatePeriod);
                                }
                            }
                        }
                    } else {
                        if (LOG.isDebugEnabled())
                            LOG.debug("Not associated {} to {}, referring to self", path, referrerPath);
                    }
                } else {
                    if (LOG.isDebugEnabled())
                        LOG.debug("Not associated {} to {}, different context", path, referrerPath);
                }
            }
        } else {
            if (LOG.isDebugEnabled())
                LOG.debug("External referrer {}", referrer);
        }
    }
    PrimaryResource primaryResource = _cache.get(path);
    if (primaryResource == null) {
        PrimaryResource r = new PrimaryResource();
        primaryResource = _cache.putIfAbsent(path, r);
        primaryResource = primaryResource == null ? r : primaryResource;
        primaryResource._timestamp.compareAndSet(0, now);
        if (LOG.isDebugEnabled())
            LOG.debug("Cached primary resource {}", path);
    } else {
        long last = primaryResource._timestamp.get();
        if (last < _renew && primaryResource._timestamp.compareAndSet(last, now)) {
            primaryResource._associated.clear();
            if (LOG.isDebugEnabled())
                LOG.debug("Clear associated resources for {}", path);
        }
    }
    // Push associated resources.
    if (!conditional && !primaryResource._associated.isEmpty()) {
        PushBuilder pushBuilder = jettyRequest.getPushBuilder();
        // Breadth-first push of associated resources.
        Queue<PrimaryResource> queue = new ArrayDeque<>();
        queue.offer(primaryResource);
        while (!queue.isEmpty()) {
            PrimaryResource parent = queue.poll();
            for (String childPath : parent._associated) {
                PrimaryResource child = _cache.get(childPath);
                if (child != null)
                    queue.offer(child);
                if (LOG.isDebugEnabled())
                    LOG.debug("Pushing {} for {}", childPath, path);
                pushBuilder.path(childPath).push();
            }
        }
    }
    chain.doFilter(request, resp);
}
Also used : Request(org.eclipse.jetty.server.Request) HttpServletRequest(javax.servlet.http.HttpServletRequest) ServletRequest(javax.servlet.ServletRequest) HttpURI(org.eclipse.jetty.http.HttpURI) ArrayDeque(java.util.ArrayDeque) HttpServletRequest(javax.servlet.http.HttpServletRequest) HttpHeader(org.eclipse.jetty.http.HttpHeader) HttpField(org.eclipse.jetty.http.HttpField) HttpFields(org.eclipse.jetty.http.HttpFields) PushBuilder(org.eclipse.jetty.server.PushBuilder)

Example 35 with HttpField

use of org.eclipse.jetty.http.HttpField in project jetty.project by eclipse.

the class ClientGenerator method generateRequestHeaders.

public Result generateRequestHeaders(int request, HttpFields fields, Callback callback) {
    request &= 0xFF_FF;
    final Charset utf8 = StandardCharsets.UTF_8;
    List<byte[]> bytes = new ArrayList<>(fields.size() * 2);
    int fieldsLength = 0;
    for (HttpField field : fields) {
        String name = field.getName();
        byte[] nameBytes = name.getBytes(utf8);
        if (nameBytes.length > MAX_PARAM_LENGTH)
            throw new IllegalArgumentException("Field name " + name + " exceeds max length " + MAX_PARAM_LENGTH);
        bytes.add(nameBytes);
        String value = field.getValue();
        byte[] valueBytes = value.getBytes(utf8);
        if (valueBytes.length > MAX_PARAM_LENGTH)
            throw new IllegalArgumentException("Field value " + value + " exceeds max length " + MAX_PARAM_LENGTH);
        bytes.add(valueBytes);
        int nameLength = nameBytes.length;
        fieldsLength += bytesForLength(nameLength);
        int valueLength = valueBytes.length;
        fieldsLength += bytesForLength(valueLength);
        fieldsLength += nameLength;
        fieldsLength += valueLength;
    }
    // Worst case FCGI_PARAMS frame: long name + long value - both of MAX_PARAM_LENGTH
    int maxCapacity = 4 + 4 + 2 * MAX_PARAM_LENGTH;
    // One FCGI_BEGIN_REQUEST + N FCGI_PARAMS + one last FCGI_PARAMS
    ByteBuffer beginRequestBuffer = byteBufferPool.acquire(16, false);
    BufferUtil.clearToFill(beginRequestBuffer);
    Result result = new Result(byteBufferPool, callback);
    result = result.append(beginRequestBuffer, true);
    // Generate the FCGI_BEGIN_REQUEST frame
    beginRequestBuffer.putInt(0x01_01_00_00 + request);
    beginRequestBuffer.putInt(0x00_08_00_00);
    // Hardcode RESPONDER role and KEEP_ALIVE flag
    beginRequestBuffer.putLong(0x00_01_01_00_00_00_00_00L);
    BufferUtil.flipToFlush(beginRequestBuffer, 0);
    int index = 0;
    while (fieldsLength > 0) {
        int capacity = 8 + Math.min(maxCapacity, fieldsLength);
        ByteBuffer buffer = byteBufferPool.acquire(capacity, true);
        BufferUtil.clearToFill(buffer);
        result = result.append(buffer, true);
        // Generate the FCGI_PARAMS frame
        buffer.putInt(0x01_04_00_00 + request);
        buffer.putShort((short) 0);
        buffer.putShort((short) 0);
        capacity -= 8;
        int length = 0;
        while (index < bytes.size()) {
            byte[] nameBytes = bytes.get(index);
            int nameLength = nameBytes.length;
            byte[] valueBytes = bytes.get(index + 1);
            int valueLength = valueBytes.length;
            int required = bytesForLength(nameLength) + bytesForLength(valueLength) + nameLength + valueLength;
            if (required > capacity)
                break;
            putParamLength(buffer, nameLength);
            putParamLength(buffer, valueLength);
            buffer.put(nameBytes);
            buffer.put(valueBytes);
            length += required;
            fieldsLength -= required;
            capacity -= required;
            index += 2;
        }
        buffer.putShort(4, (short) length);
        BufferUtil.flipToFlush(buffer, 0);
    }
    ByteBuffer lastParamsBuffer = byteBufferPool.acquire(8, false);
    BufferUtil.clearToFill(lastParamsBuffer);
    result = result.append(lastParamsBuffer, true);
    // Generate the last FCGI_PARAMS frame
    lastParamsBuffer.putInt(0x01_04_00_00 + request);
    lastParamsBuffer.putInt(0x00_00_00_00);
    BufferUtil.flipToFlush(lastParamsBuffer, 0);
    return result;
}
Also used : HttpField(org.eclipse.jetty.http.HttpField) ArrayList(java.util.ArrayList) Charset(java.nio.charset.Charset) ByteBuffer(java.nio.ByteBuffer)

Aggregations

HttpField (org.eclipse.jetty.http.HttpField)57 Test (org.junit.Test)29 HttpFields (org.eclipse.jetty.http.HttpFields)19 ByteBuffer (java.nio.ByteBuffer)17 MetaData (org.eclipse.jetty.http.MetaData)16 HostPortHttpField (org.eclipse.jetty.http.HostPortHttpField)12 ArrayList (java.util.ArrayList)8 PreEncodedHttpField (org.eclipse.jetty.http.PreEncodedHttpField)7 Entry (org.eclipse.jetty.http2.hpack.HpackContext.Entry)7 ByteBufferPool (org.eclipse.jetty.io.ByteBufferPool)7 MappedByteBufferPool (org.eclipse.jetty.io.MappedByteBufferPool)7 HttpHeader (org.eclipse.jetty.http.HttpHeader)6 HttpServletResponse (javax.servlet.http.HttpServletResponse)5 ContentResponse (org.eclipse.jetty.client.api.ContentResponse)5 HeaderGenerator (org.eclipse.jetty.http2.generator.HeaderGenerator)5 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)4 HpackEncoder (org.eclipse.jetty.http2.hpack.HpackEncoder)4 Parser (org.eclipse.jetty.http2.parser.Parser)4 CountDownLatch (java.util.concurrent.CountDownLatch)3 HttpServletRequest (javax.servlet.http.HttpServletRequest)3