Java Code Examples for io.undertow.server.HttpServerExchange#getResponseHeaders()

The following examples show how to use io.undertow.server.HttpServerExchange#getResponseHeaders() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ResponseHeaderAttribute.java    From quarkus-http with Apache License 2.0 7 votes vote down vote up
@Override
public String readAttribute(final HttpServerExchange exchange) {
    List<String> header = exchange.getResponseHeaders(responseHeader);
    if (header.isEmpty()) {
        return null;
    } else if(header.size() == 1) {
        return header.get(0);
    }
    StringBuilder sb = new StringBuilder();
    sb.append("[");
    for (int i = 0; i < header.size(); ++i) {
        if (i != 0) {
            sb.append(", ");
        }
        sb.append(header.get(i));
    }
    sb.append("]");
    return sb.toString();
}
 
Example 2
Source File: CorsHandler.java    From pivotal-bank-demo with Apache License 2.0 6 votes vote down vote up
/** Statically allows headers used by the api */
void handlePreflight(HttpServerExchange exchange) {
  HeaderMap requestHeaders = exchange.getRequestHeaders();
  String origin = requestHeaders.getFirst(ORIGIN);
  String method = requestHeaders.getFirst(ACCESS_CONTROL_REQUEST_METHOD);
  String requestedHeaders = requestHeaders.getFirst(ACCESS_CONTROL_REQUEST_HEADERS);
  HeaderMap responseHeaders = exchange.getResponseHeaders();

  responseHeaders.put(VARY,
    "origin,access-control-request-method,access-control-request-headers");
  if (
    ("POST".equals(method) || "GET".equals(method))
      && requestedHeadersAllowed(requestedHeaders)
      && setOrigin(origin, responseHeaders)
    ) {
    responseHeaders.put(ACCESS_CONTROL_ALLOW_METHODS, method);
    if (requestedHeaders != null) {
      responseHeaders.put(ACCESS_CONTROL_ALLOW_HEADERS, requestedHeaders);
    }
  }
}
 
Example 3
Source File: DomainUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 6 votes vote down vote up
public static void writeResponse(final HttpServerExchange exchange, final int status, ModelNode response,
        OperationParameter operationParameter) {

    exchange.setStatusCode(status);

    final HeaderMap responseHeaders = exchange.getResponseHeaders();
    final String contentType = operationParameter.isEncode() ? Common.APPLICATION_DMR_ENCODED : Common.APPLICATION_JSON;
    responseHeaders.put(Headers.CONTENT_TYPE, contentType + "; charset=" + Common.UTF_8);

    writeCacheHeaders(exchange, status, operationParameter);

    if (operationParameter.isGet() && status == 200) {
        // For GET request the response is purely the model nodes result. The outcome
        // is not send as part of the response but expressed with the HTTP status code.
        response = response.get(RESULT);
    }
    try {
        byte[] data = getResponseBytes(response, operationParameter);
        responseHeaders.put(Headers.CONTENT_LENGTH, data.length);
        exchange.getResponseSender().send(ByteBuffer.wrap(data));
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}
 
Example 4
Source File: SymjaServer.java    From symja_android_library with GNU General Public License v3.0 6 votes vote down vote up
@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
	String jsonStr;
	HeaderMap responseHeaders = exchange.getResponseHeaders();
	responseHeaders.put(new HttpString("Access-Control-Allow-Origin"), "*");
	responseHeaders.put(Headers.CONTENT_TYPE, "application/json");

	Map<String, Deque<String>> queryParameters = exchange.getQueryParameters();
	String appid = getAppID(queryParameters, "appid");
	if (appid != null) {
		if (appid.equals("DEMO")) {
			String inputStr = SymjaServer.getParam(queryParameters, "input", "i", "");
			String[] formformatStrs = SymjaServer.getParams(queryParameters, "format", "f", Pods.PLAIN_STR);
			int formats = Pods.internFormat(formformatStrs);
			ObjectNode messageJSON = Pods.createResult(inputStr, formats);
			jsonStr = messageJSON.toString();
		} else {
			jsonStr = Pods.errorJSONString("1", "Invalid appid");
		}
	} else {
		jsonStr = Pods.errorJSONString("2", "Appid missing");
	}
	exchange.getResponseSender().send(jsonStr);
}
 
Example 5
Source File: CRLRule.java    From keycloak with Apache License 2.0 6 votes vote down vote up
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
    if (exchange.isInIoThread()) {
        exchange.dispatch(this);
        return;
    }

    String fullFile = AbstractX509AuthenticationTest.getAuthServerHome() + File.separator + crlFileName;
    InputStream is = new FileInputStream(new File(fullFile));

    final byte[] responseBytes = IOUtils.toByteArray(is);

    final HeaderMap responseHeaders = exchange.getResponseHeaders();
    responseHeaders.put(Headers.CONTENT_TYPE, "application/pkix-crl");
    // TODO: Add caching support? CRLs provided by well-known CA usually adds them

    final Sender responseSender = exchange.getResponseSender();
    responseSender.send(ByteBuffer.wrap(responseBytes));

    exchange.endExchange();
}
 
Example 6
Source File: CustomResourceHandler.java    From PYX-Reloaded with Apache License 2.0 5 votes vote down vote up
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
    super.handleRequest(exchange);

    HeaderMap headers = exchange.getResponseHeaders();
    if (cacheEnabled) headers.add(Headers.CACHE_CONTROL, "private, no-cache");
    else headers.add(Headers.CACHE_CONTROL, "private, no-store, no-cache");
}
 
Example 7
Source File: StaticHeadersHandler.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
void apply(HttpServerExchange exchange, Predicate<String> putHeader) {
    HeaderMap headers = exchange.getResponseHeaders();
    if (putHeader.test(headerName.toString())) {
        headers.put(headerName, value);
    } else {
        headers.add(headerName, value);
    }
}
 
Example 8
Source File: DomainUtil.java    From wildfly-core with GNU Lesser General Public License v2.1 5 votes vote down vote up
static void writeCacheHeaders(final HttpServerExchange exchange, final int status, final OperationParameter operationParameter) {
    final HeaderMap responseHeaders = exchange.getResponseHeaders();

    // No need to send this in a 304
    // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
    if (operationParameter.getMaxAge() > 0 && status != 304) {
        responseHeaders.put(Headers.CACHE_CONTROL, "max-age=" + operationParameter.getMaxAge() + ", private, must-revalidate");
    }
    if (operationParameter.getEtag() != null) {
        responseHeaders.put(Headers.ETAG, operationParameter.getEtag().toString());
    }
}
 
Example 9
Source File: UndertowAdapter.java    From enkan with Eclipse Public License 1.0 5 votes vote down vote up
private void setResponseHeaders(Headers headers, HttpServerExchange exchange) {
    HeaderMap map = exchange.getResponseHeaders();
    headers.keySet().forEach(headerName -> headers.getList(headerName)
            .forEach(v -> {
                if (v instanceof String) {
                    map.add(HttpString.tryFromString(headerName), (String) v);
                } else if (v instanceof Number) {
                    map.add(HttpString.tryFromString(headerName), ((Number) v).longValue());
                }
            }));
}
 
Example 10
Source File: DateUtils.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
public static void addDateHeaderIfRequired(HttpServerExchange exchange) {
    HeaderMap responseHeaders = exchange.getResponseHeaders();
    if (exchange.getConnection().getUndertowOptions().get(UndertowOptions.ALWAYS_SET_DATE, true) && !responseHeaders.contains(Headers.DATE)) {
        String dateString = getCurrentDateTime(exchange);
        responseHeaders.put(Headers.DATE, dateString);
    }
}
 
Example 11
Source File: DigestAuthenticationMechanism.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
public void sendAuthenticationInfoHeader(final HttpServerExchange exchange) {
    DigestContext context = exchange.getAttachment(DigestContext.ATTACHMENT_KEY);
    DigestQop qop = context.getQop();
    String currentNonce = context.getNonce();
    String nextNonce = nonceManager.nextNonce(currentNonce, exchange);
    if (qop != null || !nextNonce.equals(currentNonce)) {
        StringBuilder sb = new StringBuilder();
        sb.append(NEXT_NONCE).append("=\"").append(nextNonce).append("\"");
        if (qop != null) {
            Map<DigestAuthorizationToken, String> parsedHeader = context.getParsedHeader();
            sb.append(",").append(Headers.QOP.toString()).append("=\"").append(qop.getToken()).append("\"");
            byte[] ha1 = context.getHa1();
            byte[] ha2;

            if (qop == DigestQop.AUTH) {
                ha2 = createHA2Auth(context);
            } else {
                ha2 = createHA2AuthInt();
            }
            String rspauth = new String(createRFC2617RequestDigest(ha1, ha2, context), StandardCharsets.UTF_8);
            sb.append(",").append(Headers.RESPONSE_AUTH.toString()).append("=\"").append(rspauth).append("\"");
            sb.append(",").append(Headers.CNONCE.toString()).append("=\"").append(parsedHeader.get(DigestAuthorizationToken.CNONCE)).append("\"");
            sb.append(",").append(Headers.NONCE_COUNT.toString()).append("=").append(parsedHeader.get(DigestAuthorizationToken.NONCE_COUNT));
        }

        HeaderMap responseHeader = exchange.getResponseHeaders();
        responseHeader.add(AUTHENTICATION_INFO, sb.toString());
    }

    exchange.removeAttachment(DigestContext.ATTACHMENT_KEY);
}
 
Example 12
Source File: DigestAuthenticationMechanism.java    From lams with GNU General Public License v2.0 5 votes vote down vote up
@Override
public ChallengeResult sendChallenge(final HttpServerExchange exchange, final SecurityContext securityContext) {
    DigestContext context = exchange.getAttachment(DigestContext.ATTACHMENT_KEY);
    boolean stale = context == null ? false : context.isStale();

    StringBuilder rb = new StringBuilder(DIGEST_PREFIX);
    rb.append(Headers.REALM.toString()).append("=\"").append(realmName).append("\",");
    rb.append(Headers.DOMAIN.toString()).append("=\"").append(domain).append("\",");
    // based on security constraints.
    rb.append(Headers.NONCE.toString()).append("=\"").append(nonceManager.nextNonce(null, exchange)).append("\",");
    // Not currently using OPAQUE as it offers no integrity, used for session data leaves it vulnerable to
    // session fixation type issues as well.
    rb.append(Headers.OPAQUE.toString()).append("=\"00000000000000000000000000000000\"");
    if (stale) {
        rb.append(",stale=true");
    }
    if (supportedAlgorithms.size() > 0) {
        // This header will need to be repeated once for each algorithm.
        rb.append(",").append(Headers.ALGORITHM.toString()).append("=%s");
    }
    if (qopString != null) {
        rb.append(",").append(Headers.QOP.toString()).append("=\"").append(qopString).append("\"");
    }

    String theChallenge = rb.toString();
    HeaderMap responseHeader = exchange.getResponseHeaders();
    if (supportedAlgorithms.isEmpty()) {
        responseHeader.add(WWW_AUTHENTICATE, theChallenge);
    } else {
        for (DigestAlgorithm current : supportedAlgorithms) {
            responseHeader.add(WWW_AUTHENTICATE, String.format(theChallenge, current.getToken()));
        }
    }

    return new ChallengeResult(true, UNAUTHORIZED);
}
 
Example 13
Source File: CorsHandler.java    From pivotal-bank-demo with Apache License 2.0 5 votes vote down vote up
boolean validateOrigin(HttpServerExchange exchange) {
  HeaderMap responseHeaders = exchange.getResponseHeaders();
  responseHeaders.put(VARY, "origin");
  String origin = exchange.getRequestHeaders().getFirst(ORIGIN);
  if (origin == null) return true; // just vary
  return setOrigin(origin, responseHeaders);
}
 
Example 14
Source File: HttpTransferEncoding.java    From lams with GNU General Public License v2.0 4 votes vote down vote up
static StreamSinkConduit createSinkConduit(final HttpServerExchange exchange) {
    DateUtils.addDateHeaderIfRequired(exchange);

    boolean headRequest = exchange.getRequestMethod().equals(Methods.HEAD);
    HttpServerConnection serverConnection = (HttpServerConnection) exchange.getConnection();

    HttpResponseConduit responseConduit = serverConnection.getResponseConduit();
    responseConduit.reset(exchange);
    StreamSinkConduit channel = responseConduit;
    if (headRequest) {
        //if this is a head request we add a head channel underneath the content encoding channel
        //this will just discard the data
        //we still go through with the rest of the logic, to make sure all headers are set correctly
        channel = new HeadStreamSinkConduit(channel, terminateResponseListener(exchange));
    } else if(!Connectors.isEntityBodyAllowed(exchange)) {
        //we are not allowed to send an entity body for some requests
        exchange.getResponseHeaders().remove(Headers.CONTENT_LENGTH);
        exchange.getResponseHeaders().remove(Headers.TRANSFER_ENCODING);
        channel = new HeadStreamSinkConduit(channel, terminateResponseListener(exchange));
        return channel;
    }

    final HeaderMap responseHeaders = exchange.getResponseHeaders();
    // test to see if we're still persistent
    String connection = responseHeaders.getFirst(Headers.CONNECTION);
    if (!exchange.isPersistent()) {
        responseHeaders.put(Headers.CONNECTION, Headers.CLOSE.toString());
    } else if (exchange.isPersistent() && connection != null) {
        if (HttpString.tryFromString(connection).equals(Headers.CLOSE)) {
            exchange.setPersistent(false);
        }
    } else if (exchange.getConnection().getUndertowOptions().get(UndertowOptions.ALWAYS_SET_KEEP_ALIVE, true)) {
        responseHeaders.put(Headers.CONNECTION, Headers.KEEP_ALIVE.toString());
    }
    //according to the HTTP RFC we should ignore content length if a transfer coding is specified
    final String transferEncodingHeader = responseHeaders.getLast(Headers.TRANSFER_ENCODING);
    if(transferEncodingHeader == null) {
        final String contentLengthHeader = responseHeaders.getFirst(Headers.CONTENT_LENGTH);
        if (contentLengthHeader != null) {
            StreamSinkConduit res = handleFixedLength(exchange, headRequest, channel, responseHeaders, contentLengthHeader, serverConnection);
            if (res != null) {
                return res;
            }
        }
    } else {
        responseHeaders.remove(Headers.CONTENT_LENGTH); //if there is a transfer-encoding header we remove content length if present
    }
    return handleResponseConduit(exchange, headRequest, channel, responseHeaders, terminateResponseListener(exchange), transferEncodingHeader);
}
 
Example 15
Source File: OcspHandler.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    if (exchange.isInIoThread()) {
        exchange.dispatch(this);
        return;
    }

    final byte[] buffy = new byte[16384];
    try (InputStream requestStream = exchange.getInputStream()) {
        requestStream.read(buffy);
    }

    final OCSPReq request = new OCSPReq(buffy);
    final Req[] requested = request.getRequestList();

    final Extension nonce = request.getExtension(OCSPObjectIdentifiers.id_pkix_ocsp_nonce);

    final DigestCalculator sha1Calculator = new JcaDigestCalculatorProviderBuilder().build()
            .get(AlgorithmIdentifier.getInstance(RespID.HASH_SHA1));

    final BasicOCSPRespBuilder responseBuilder = new BasicOCSPRespBuilder(subjectPublicKeyInfo, sha1Calculator);

    if (nonce != null) {
        responseBuilder.setResponseExtensions(new Extensions(nonce));
    }

    for (final Req req : requested) {
        final CertificateID certId = req.getCertID();

        final BigInteger certificateSerialNumber = certId.getSerialNumber();
        responseBuilder.addResponse(certId, REVOKED_CERTIFICATES_STATUS.get(certificateSerialNumber));
    }

    final ContentSigner contentSigner = new BcRSAContentSignerBuilder(
            new AlgorithmIdentifier(PKCSObjectIdentifiers.sha256WithRSAEncryption),
            new AlgorithmIdentifier(NISTObjectIdentifiers.id_sha256)).build(privateKey);

    final OCSPResp response = new OCSPRespBuilder().build(OCSPResp.SUCCESSFUL,
            responseBuilder.build(contentSigner, chain, new Date()));

    final byte[] responseBytes = response.getEncoded();

    final HeaderMap responseHeaders = exchange.getResponseHeaders();
    responseHeaders.put(Headers.CONTENT_TYPE, "application/ocsp-response");

    final Sender responseSender = exchange.getResponseSender();
    responseSender.send(ByteBuffer.wrap(responseBytes));

    exchange.endExchange();
}
 
Example 16
Source File: GZipPredicate.java    From core-ng-project with Apache License 2.0 4 votes vote down vote up
@Override
public boolean resolve(HttpServerExchange exchange) {
    HeaderMap headers = exchange.getResponseHeaders();
    return resolve(headers);
}
 
Example 17
Source File: LogoutHandler.java    From wildfly-core with GNU Lesser General Public License v2.1 4 votes vote down vote up
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
    final HeaderMap requestHeaders = exchange.getRequestHeaders();
    final HeaderMap responseHeaders = exchange.getResponseHeaders();

    String referrer = responseHeaders.getFirst(REFERER);
    String protocol = exchange.getRequestScheme();
    String host = null;
    if (referrer != null) {
        try {
            URI uri = new URI(referrer);
            protocol = uri.getScheme();
            host = uri.getHost() + portPortion(protocol, uri.getPort());
        } catch (URISyntaxException e) {
        }
    }
    if (host == null) {
        host = requestHeaders.getFirst(HOST);
        if (host == null) {
            exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR);
            return;
        }
    }

    /*
     * Main sequence of events:
     *
     * 1. Redirect to self using user:pass@host form of authority. This forces Safari to overwrite its cache. (Also
     * forces FF and Chrome, but not absolutely necessary) Set the exit flag as a state signal for step 3
     *
     * 2. Send 401 digest without a nonce stale marker, this will force FF and Chrome and likely other browsers to
     * assume an invalid (old) password. In the case of Opera, which doesn't invalidate under such a circumstance,
     * send an invalid realm. This will overwrite its auth cache, since it indexes it by host and not realm.
     *
     * 3. The credentials in 307 redirect wlll be transparently accepted and a final redirect to the console is
     * performed. Opera ignores these, so the user must hit escape which will use javascript to perform the redirect
     *
     * In the case of Internet Explorer, all of this will be bypassed and will simply redirect to the console. The console
     * MUST use a special javascript call before redirecting to logout.
     */
    String userAgent = requestHeaders.getFirst(USER_AGENT);
    boolean opera = userAgent != null && userAgent.contains("Opera");
    boolean win = !opera && userAgent != null && (userAgent.contains("MSIE") || userAgent.contains("Trident"));

    String rawQuery = exchange.getQueryString();
    boolean exit = rawQuery != null && rawQuery.contains(EXIT);



    if (win) {
        responseHeaders.add(LOCATION, protocol + "://" + host + "/");
        exchange.setStatusCode(StatusCodes.TEMPORARY_REDIRECT);
    } else {
        // Do the redirects to finish the logout
        String authorization = requestHeaders.getFirst(AUTHORIZATION);

        boolean digest = true;
        Map<String, Deque<String>> parameters = exchange.getQueryParameters();
        if (parameters.containsKey(MECHANISM)) {
            digest = !BASIC.equals(parameters.get(MECHANISM).getFirst());
        }
        if (authorization != null && authorization.length() > BASIC.length()
                && BASIC.equalsIgnoreCase(authorization.substring(0, BASIC.length()))) {
            digest = false;
            ByteBuffer decode = FlexBase64.decode(authorization.substring(6));
            authorization = new String(decode.array(), decode.arrayOffset(), decode.limit(), UTF_8);
        }

        if (authorization == null || !authorization.contains("enter-login-here")) {
            if (!exit) {
                responseHeaders.add(LOCATION, protocol + "://enter-login-here:blah@" + host + "/logout?" + EXIT + "&"
                        + MECHANISM + "=" + (digest ? DIGEST : BASIC));
                exchange.setStatusCode(StatusCodes.TEMPORARY_REDIRECT);
                return;
            }

            mechanism(opera, digest).sendChallenge(exchange, null);
            String reply = "<html><script type='text/javascript'>window.location=\"" + protocol + "://" + host
                    + "/\";</script></html>";
            exchange.setStatusCode(StatusCodes.UNAUTHORIZED);
            exchange.getResponseSender().send(reply, IoCallback.END_EXCHANGE);
            return;
        }

        // Success, now back to the login screen
        responseHeaders.add(LOCATION, protocol + "://" + host + "/");
        exchange.setStatusCode(StatusCodes.TEMPORARY_REDIRECT);
    }
}
 
Example 18
Source File: EventBusToServerSentEvents.java    From syndesis with Apache License 2.0 4 votes vote down vote up
protected boolean reservationCheck(HttpServerExchange exchange) {
    HeaderMap requestHeaders = exchange.getRequestHeaders();
    String origin = requestHeaders.getFirst(CorsHeaders.ORIGIN);
    if (cors.getAllowedOrigins().contains("*") || cors.getAllowedOrigins().contains(origin)) {
        HeaderMap responseHeaders = exchange.getResponseHeaders();
        responseHeaders.put(new HttpString(CorsHeaders.ACCESS_CONTROL_ALLOW_ORIGIN), origin);

        String value = requestHeaders.getFirst(CorsHeaders.ACCESS_CONTROL_REQUEST_HEADERS);
        if (value != null) {
            responseHeaders.put(new HttpString(CorsHeaders.ACCESS_CONTROL_ALLOW_HEADERS), value);
        }

        value = requestHeaders.getFirst(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS);
        if (value != null) {
            responseHeaders.put(new HttpString(CorsHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS), value);
        }

        value = requestHeaders.getFirst(CorsHeaders.ACCESS_CONTROL_REQUEST_METHOD);
        if (value != null) {
            responseHeaders.put(new HttpString(CorsHeaders.ACCESS_CONTROL_ALLOW_METHODS), value);
        }
    }

    String uri = exchange.getRequestURI();
    if (uri.indexOf(path + "/") != 0) {
        exchange.setStatusCode(404);
        return false;
    }

    final String subscriptionId = uri.substring(path.length() + 1);
    if (subscriptionId.isEmpty()) {
        exchange.setStatusCode(404);
        return false;
    }

    EventReservationsHandler.Reservation reservation = eventReservationsHandler.existsReservation(subscriptionId);
    if (reservation == null) {
        exchange.setStatusCode(404);
        return false;
    }
    return true;
}
 
Example 19
Source File: UndertowServerHttpResponse.java    From java-technology-stack with MIT License 4 votes vote down vote up
private static HttpHeaders createHeaders(HttpServerExchange exchange) {
	UndertowHeadersAdapter headersMap =
			new UndertowHeadersAdapter(exchange.getResponseHeaders());
	return new HttpHeaders(headersMap);
}
 
Example 20
Source File: JavaScriptHandler.java    From divolte-collector with Apache License 2.0 4 votes vote down vote up
@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
    if (logger.isDebugEnabled()) {
        logger.debug("Requested received for {} from {}",
                     resource.getResourceName(), exchange.getSourceAddress().getHostString());
    }
    // Start with headers that we always set the same way.
    final HeaderMap responseHeaders = exchange.getResponseHeaders();
    responseHeaders.put(Headers.CACHE_CONTROL, CACHE_CONTROL_HEADER_VALUE);

    // Figure out if we possibly need to deal with a compressed response,
    // based on client capability.
    final GzippableHttpBody uncompressedBody = resource.getEntityBody();
    final Optional<HttpBody> gzippedBody = uncompressedBody.getGzippedBody();
    final HttpBody bodyToSend;
    if (gzippedBody.isPresent()) {
        /*
         * Compressed responses can use Content-Encoding and/or Transfer-Encoding.
         * The semantics differ slightly, but it is suffice to say that most user
         * agents don't advertise their Transfer-Encoding support.
         * So for now we only support the Content-Encoding mechanism.
         * Some other notes:
         *  - Some clients implement 'deflate' incorrectly. Hence we only support 'gzip',
         *    despite it having slightly more overhead.
         *  - We don't use Undertow's built-in compression support because we've
         *    pre-calculated the compressed response and expect to serve it up
         *    repeatedly, instead of calculating it on-the-fly for every request.
         */
        responseHeaders.put(Headers.VARY, Headers.ACCEPT_ENCODING_STRING);
        final HeaderValues acceptEncoding =
                exchange.getRequestHeaders().get(Headers.ACCEPT_ENCODING);
        if (null != acceptEncoding &&
                acceptEncoding.stream()
                              .anyMatch((header) -> Iterables.contains(HEADER_SPLITTER.split(header), "gzip"))) {
            responseHeaders.put(Headers.CONTENT_ENCODING, "gzip");
            bodyToSend = gzippedBody.get();
        } else {
            bodyToSend = uncompressedBody;
        }
    } else {
        bodyToSend = uncompressedBody;
    }

    // Now we know which version of the entity is visible to this user-agent,
    // figure out if the client already has the current version or not.
    final ETag eTag = bodyToSend.getETag();
    responseHeaders.put(Headers.ETAG, eTag.toString());
    if (ETagUtils.handleIfNoneMatch(exchange, eTag, true)) {
        final ByteBuffer entityBody = bodyToSend.getBody();
        responseHeaders.put(Headers.CONTENT_TYPE, "application/javascript");
        exchange.getResponseSender().send(entityBody);
    } else {
        exchange.setStatusCode(StatusCodes.NOT_MODIFIED);
        exchange.endExchange();
    }
}