Fix gzip support for Jetty

This commit is contained in:
Aurora Lahtela 2022-08-31 19:44:38 +03:00
parent 019a3353ca
commit 6f6b4f149f
2 changed files with 51 additions and 13 deletions

View File

@ -66,6 +66,11 @@ public class ResponseBuilder {
return this;
}
protected ResponseBuilder removeHeader(String header) {
response.headers.remove(header);
return this;
}
/**
* Utility method for building redirects.
*
@ -103,7 +108,8 @@ public class ResponseBuilder {
}
}
return setContent(content.getBytes(charset));
return setContent(content.getBytes(charset))
.removeHeader("Accept-Ranges"); // Can compress
}
/**

View File

@ -16,13 +16,16 @@
*/
package com.djrapitops.plan.delivery.webserver.http;
import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.webserver.Addresses;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jetty.http.HttpHeader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Map;
@ -43,16 +46,23 @@ public class JettyResponseSender {
}
public void send() throws IOException {
setResponseHeaders();
if ("HEAD".equals(servletRequest.getMethod()) || response.getCode() == 204) {
setResponseHeaders();
sendHeadResponse();
} else if ("bytes".equalsIgnoreCase(response.getHeaders().get(HttpHeader.ACCEPT_RANGES.asString()))) {
sendRawBytes();
} else {
} else if (canGzip()) {
sendCompressed();
} else {
setResponseHeaders();
sendRawBytes();
}
}
private boolean canGzip() {
String method = servletRequest.getMethod();
String mimeType = response.getHeaders().get(HttpHeader.CONTENT_TYPE.asString());
return "GET".equals(method) && StringUtils.containsAny(mimeType, MimeType.HTML, MimeType.CSS, MimeType.JS, MimeType.JSON, "text/plain");
}
public void sendHeadResponse() throws IOException {
try {
response.getHeaders().remove(HttpHeader.CONTENT_LENGTH.asString());
@ -72,22 +82,40 @@ public class JettyResponseSender {
}
private void correctRedirect(Map<String, String> responseHeaders) {
String redirect = responseHeaders.get("Location");
String redirect = responseHeaders.get(HttpHeader.LOCATION.asString());
if (redirect != null) {
if (redirect.startsWith("http") || !redirect.startsWith("/")) return;
addresses.getAccessAddress().ifPresent(address -> responseHeaders.put("Location", address + redirect));
addresses.getAccessAddress().ifPresent(address -> responseHeaders.put(HttpHeader.LOCATION.asString(), address + redirect));
}
}
private void sendCompressed() throws IOException {
servletResponse.setHeader(HttpHeader.CONTENT_ENCODING.asString(), "gzip");
beginSend();
try (OutputStream out = new GZIPOutputStream(servletResponse.getOutputStream())) {
send(out);
response.getHeaders().remove(HttpHeader.ACCEPT_RANGES.asString());
response.getHeaders().put(HttpHeader.CONTENT_ENCODING.asString(), "gzip");
byte[] gzipped = gzip();
try (OutputStream out = servletResponse.getOutputStream()) {
response.getHeaders().put(HttpHeader.CONTENT_LENGTH.asString(), String.valueOf(gzipped.length));
setResponseHeaders();
servletResponse.setStatus(response.getCode());
send(out, gzipped);
}
}
private void beginSend() throws IOException {
private byte[] gzip() throws IOException {
try (ByteArrayOutputStream bufferStream = new ByteArrayOutputStream();
GZIPOutputStream gzipStream = new GZIPOutputStream(bufferStream)
) {
gzipStream.write(response.getBytes());
gzipStream.finish();
gzipStream.flush();
return bufferStream.toByteArray();
}
}
private void beginSend() {
String length = response.getHeaders().get(HttpHeader.CONTENT_LENGTH.asString());
if (length == null || "0".equals(length) || response.getCode() == 204 || "HEAD".equals(servletRequest.getMethod())) {
servletResponse.setHeader(HttpHeader.CONTENT_LENGTH.asString(), null);
@ -105,8 +133,12 @@ public class JettyResponseSender {
}
private void send(OutputStream out) throws IOException {
send(out, response.getBytes());
}
private void send(OutputStream out, byte[] bytes) throws IOException {
try (
ByteArrayInputStream bis = new ByteArrayInputStream(response.getBytes())
ByteArrayInputStream bis = new ByteArrayInputStream(bytes)
) {
byte[] buffer = new byte[2048];
int count;