-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathPrerenderFilter.java
More file actions
111 lines (94 loc) · 4.1 KB
/
Copy pathPrerenderFilter.java
File metadata and controls
111 lines (94 loc) · 4.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package io.prerender;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
public class PrerenderFilter implements Filter {
public static final String VERSION = "1.0.0";
private static final Logger logger = Logger.getLogger(PrerenderFilter.class.getName());
private HttpClient httpClient;
private PrerenderConfig config;
public PrerenderFilter() {}
PrerenderFilter(HttpClient httpClient, PrerenderConfig config) {
this.httpClient = httpClient;
this.config = config;
}
@Override
public void init(FilterConfig filterConfig) {
this.httpClient = HttpClient.newHttpClient();
this.config = PrerenderConfig.fromInitParams(
filterConfig.getInitParameter("prerenderToken"),
filterConfig.getInitParameter("prerenderServiceUrl")
);
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpReq = (HttpServletRequest) request;
HttpServletResponse httpRes = (HttpServletResponse) response;
if (!shouldPrerender(httpReq)) {
chain.doFilter(request, response);
return;
}
try {
sendPrerendered(httpReq, httpRes);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
chain.doFilter(request, response);
} catch (IOException e) {
logger.log(Level.WARNING, "Prerender service unreachable, falling back", e);
chain.doFilter(request, response);
}
}
@Override
public void destroy() {}
private boolean shouldPrerender(HttpServletRequest request) {
if (!"GET".equalsIgnoreCase(request.getMethod())) return false;
if (PrerenderConfig.isStaticAsset(request.getRequestURI())) return false;
if (request.getParameter("_escaped_fragment_") != null) return true;
if (request.getHeader("X-Bufferbot") != null) return true;
String ua = request.getHeader("User-Agent");
return ua != null && !ua.isBlank() && PrerenderConfig.isBot(ua);
}
private void sendPrerendered(HttpServletRequest request, HttpServletResponse response)
throws IOException, InterruptedException {
HttpResponse<String> prerenderResponse = httpClient.send(
buildPrerenderRequest(buildApiUrl(request), request.getHeader("User-Agent")),
HttpResponse.BodyHandlers.ofString()
);
response.setStatus(prerenderResponse.statusCode());
response.getWriter().write(prerenderResponse.body());
}
private String buildApiUrl(HttpServletRequest request) {
String serviceUrl = config.getServiceUrl();
if (!serviceUrl.endsWith("/")) serviceUrl += "/";
String url = request.getRequestURL().toString();
String qs = request.getQueryString();
return serviceUrl + (qs != null && !qs.isBlank() ? url + "?" + qs : url);
}
private HttpRequest buildPrerenderRequest(String apiUrl, String userAgent) {
HttpRequest.Builder builder = HttpRequest.newBuilder()
.uri(URI.create(apiUrl))
.header("User-Agent", userAgent != null ? userAgent : "")
.GET();
if (config.getToken() != null && !config.getToken().isBlank()) {
builder.header("X-Prerender-Token", config.getToken());
}
builder.header("X-Prerender-Int-Type", "Java");
builder.header("X-Prerender-Int-Version", VERSION);
builder.header("X-Prerender-Request-Id", UUID.randomUUID().toString());
return builder.build();
}
}