@Override public HttpHandler wrap(HttpHandler handler) { return new EncodingHandler(handler, new ContentEncodingRepository() .addEncodingHandler("gzip", new GzipEncodingProvider(), 100) .addEncodingHandler("deflate", new DeflateEncodingProvider(), 10)); } };
@Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof EncodingMapping)) return false; EncodingMapping that = (EncodingMapping) o; return this.compareTo(that) == 0; }
@Override public HttpHandler wrap(HttpHandler handler) { return new RequestEncodingHandler(handler) .addEncoding("deflate", InflatingStreamSourceConduit.WRAPPER); } };
@Override public HttpHandler createHttpHandler(final Predicate predicate, ModelNode model, HttpHandler next) { EncodingHandler encodingHandler = new EncodingHandler(new ContentEncodingRepository() .addEncodingHandler("gzip", new GzipEncodingProvider(), 50, predicate != null ? predicate : Predicates.truePredicate())); encodingHandler.setNext(next); return encodingHandler; }
public HttpHandler createHttpHandler() { PathHandler pathHandler = new PathHandler(); pathHandler.addPrefixPath("/v1/invoke", new AllowedMethodsHandler(new HttpInvocationHandler(association, executorService, localTransactionContext, cancellationFlags), Methods.POST)) .addPrefixPath("/v1/open", new AllowedMethodsHandler(new HttpSessionOpenHandler(association, executorService, localTransactionContext), Methods.POST)) .addPrefixPath("/v1/cancel", new AllowedMethodsHandler(new HttpCancelHandler(association, executorService, localTransactionContext, cancellationFlags), Methods.DELETE)); EncodingHandler encodingHandler = new EncodingHandler(pathHandler, new ContentEncodingRepository().addEncodingHandler(Headers.GZIP.toString(), new GzipEncodingProvider(), 1)); RequestEncodingHandler requestEncodingHandler = new RequestEncodingHandler(encodingHandler); requestEncodingHandler.addEncoding(Headers.GZIP.toString(), GzipStreamSourceConduit.WRAPPER); return requestEncodingHandler; }
AllowedContentEncodings encodings = contentEncodingRepository.getContentEncodings(exchange); if (encodings == null || encodings.isNoEncodingsAllowed()) { return null; EncodingMapping encoding = encodings.getEncoding(); if (encoding == null || encoding.getName().equals(ContentEncodingRepository.IDENTITY)) { return null; String newPath = path + ".undertow.encoding." + encoding.getName(); Resource preCompressed = encoded.getResource(newPath); if (preCompressed != null) { return new ContentEncodedResource(preCompressed, encoding.getName()); final LockKey key = new LockKey(path, encoding.getName()); if (fileLocks.putIfAbsent(key, this) != null) { return new ContentEncodedResource(preCompressed, encoding.getName()); StreamSinkConduit conduit = encoding.getEncoding().getResponseWrapper().wrap(new ImmediateConduitFactory<StreamSinkConduit>(new FileConduitTarget(targetFileChannel, exchange)), exchange); final ConduitStreamSinkChannel targetChannel = new ConduitStreamSinkChannel(null, conduit); long transferred = sourceFileChannel.transferTo(0, resource.getContentLength(), targetChannel); encoded.invalidate(newPath); final Resource encodedResource = encoded.getResource(newPath); return new ContentEncodedResource(encodedResource, encoding.getName()); } finally { IoUtils.safeClose(targetFileChannel);
public synchronized ContentEncodingRepository addEncodingHandler(final String encoding, final ContentEncodingProvider encoder, int priority) { addEncodingHandler(encoding, encoder, priority, Predicates.truePredicate()); return this; }
@Override public StreamSinkConduit wrap(final ConduitFactory<StreamSinkConduit> factory, final HttpServerExchange exchange) { if (exchange.getResponseHeaders().contains(Headers.CONTENT_ENCODING)) { //already encoded return factory.create(); } //if this is a zero length response we don't want to encode if (exchange.getResponseContentLength() != 0 && exchange.getStatusCode() != StatusCodes.NO_CONTENT && exchange.getStatusCode() != StatusCodes.NOT_MODIFIED) { EncodingMapping encoding = getEncoding(); if (encoding != null) { exchange.getResponseHeaders().put(Headers.CONTENT_ENCODING, encoding.getName()); if (exchange.getRequestMethod().equals(Methods.HEAD)) { //we don't create an actual encoder for HEAD requests, but we set the header return factory.create(); } else { return encoding.getEncoding().getResponseWrapper().wrap(factory, exchange); } } } return factory.create(); } }
@Override public void handleRequest(final HttpServerExchange exchange) throws Exception { AllowedContentEncodings encodings = contentEncodingRepository.getContentEncodings(exchange); if (encodings == null || !exchange.isResponseChannelAvailable()) { next.handleRequest(exchange); } else if (encodings.isNoEncodingsAllowed()) { noEncodingHandler.handleRequest(exchange); } else { exchange.addResponseWrapper(encodings); exchange.putAttachment(AllowedContentEncodings.ATTACHMENT_KEY, encodings); next.handleRequest(exchange); } }
/** * @return The content encoding that will be set, given the current state of the HttpServerExchange */ public String getCurrentContentEncoding() { for (EncodingMapping encoding : encodings) { if (encoding.getAllowed() == null || encoding.getAllowed().resolve(exchange)) { return encoding.getName(); } } return Headers.IDENTITY.toString(); }
public boolean isIdentity() { return getCurrentContentEncoding().equals(Headers.IDENTITY.toString()); }
@Override public int hashCode() { return getPriority(); }
@Override public void resumeWrites() { wakeupWrites(); }
public synchronized ContentEncodingRepository addEncodingHandler(final String encoding, final ContentEncodingProvider encoder, int priority, final Predicate enabledPredicate) { this.encodingMap.put(encoding, new EncodingMapping(encoding, encoder, priority, enabledPredicate)); return this; }
public EncodingMapping getEncoding() { for (EncodingMapping encoding : encodings) { if (encoding.getAllowed() == null || encoding.getAllowed().resolve(exchange)) { return encoding; } } return null; }
@Override public StreamSinkConduit wrap(final ConduitFactory<StreamSinkConduit> factory, final HttpServerExchange exchange) { if(!responseCache.isResponseCachable()) { return factory.create(); } final AllowedContentEncodings contentEncodings = exchange.getAttachment(AllowedContentEncodings.ATTACHMENT_KEY); if(contentEncodings != null) { if(!contentEncodings.isIdentity()) { //we can't cache content encoded responses, as we have no idea how big they will end up being return factory.create(); } } String lengthString = exchange.getResponseHeaders().getFirst(CONTENT_LENGTH); if(lengthString == null) { //we don't cache chunked requests return factory.create(); } int length = Integer.parseInt(lengthString); final CachedHttpRequest key = new CachedHttpRequest(exchange); final DirectBufferCache.CacheEntry entry = cache.add(key, length); if (entry == null || entry.buffers().length == 0 || !entry.claimEnable()) { return factory.create(); } if (!entry.reference()) { entry.disable(); return factory.create(); } return new ResponseCachingStreamSinkConduit(factory.create(), entry, length); } });
public ResponseEncodeHandler() { contentEncodingRepository = new ContentEncodingRepository(); List<String> encoders = config.getEncoders(); for(int i = 0; i < encoders.size(); i++) { String encoder = encoders.get(i); if(Constants.ENCODE_GZIP.equals(encoder)) { contentEncodingRepository.addEncodingHandler(encoder, new GzipEncodingProvider(), 100); } else if(Constants.ENCODE_DEFLATE.equals(encoder)) { contentEncodingRepository.addEncodingHandler(encoder, new DeflateEncodingProvider(), 10); } else { throw new RuntimeException("Invalid encoder " + encoder + " for ResponseEncodeHandler."); } } }
/** * Optionally wrap the given {@link HttpHandler} for HTTP compression support. * @param compression the HTTP compression configuration * @param httpHandler the HTTP handler to wrap * @return the wrapped HTTP handler if compression is enabled, or the handler itself */ public static HttpHandler configureCompression(Compression compression, HttpHandler httpHandler) { if (compression == null || !compression.getEnabled()) { return httpHandler; } ContentEncodingRepository repository = new ContentEncodingRepository(); repository.addEncodingHandler("gzip", new GzipEncodingProvider(), 50, Predicates.and(getCompressionPredicates(compression))); return new EncodingHandler(repository).setNext(httpHandler); }
@Override public void handleRequest(HttpServerExchange exchange) throws Exception { AllowedContentEncodings encodings = contentEncodingRepository.getContentEncodings(exchange); if (encodings == null || !exchange.isResponseChannelAvailable()) { Handler.next(exchange, next); } else if (encodings.isNoEncodingsAllowed()) { setExchangeStatus(exchange, NO_ENCODING_HANDLER); return; } else { exchange.addResponseWrapper(encodings); exchange.putAttachment(AllowedContentEncodings.ATTACHMENT_KEY, encodings); Handler.next(exchange, next); } } }
public CachedHttpRequest(final HttpServerExchange exchange) { this.path = exchange.getRequestPath(); this.etag = ETagUtils.getETag(exchange); this.contentLocation = exchange.getResponseHeaders().getFirst(Headers.CONTENT_LOCATION); this.language = exchange.getResponseHeaders().getFirst(Headers.CONTENT_LANGUAGE); this.contentType = exchange.getResponseHeaders().getFirst(Headers.CONTENT_TYPE); String lmString = exchange.getResponseHeaders().getFirst(Headers.LAST_MODIFIED); if (lmString == null) { this.lastModified = null; } else { this.lastModified = DateUtils.parseDate(lmString); } //the content encoding can be decided dynamically, based on the current state of the request //as the decision to compress generally depends on size and mime type final AllowedContentEncodings encoding = exchange.getAttachment(AllowedContentEncodings.ATTACHMENT_KEY); if(encoding != null) { this.contentEncoding = encoding.getCurrentContentEncoding(); } else { this.contentEncoding = exchange.getResponseHeaders().getFirst(Headers.CONTENT_ENCODING); } this.responseCode = exchange.getStatusCode(); }