1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.filter;
17
18 import java.io.IOException;
19
20 import org.apache.logging.log4j.LogManager;
21 import org.apache.logging.log4j.Logger;
22 import org.codelibs.fess.helper.RateLimitHelper;
23 import org.codelibs.fess.util.ComponentUtil;
24
25 import jakarta.servlet.Filter;
26 import jakarta.servlet.FilterChain;
27 import jakarta.servlet.ServletException;
28 import jakarta.servlet.ServletRequest;
29 import jakarta.servlet.ServletResponse;
30 import jakarta.servlet.http.HttpServletRequest;
31 import jakarta.servlet.http.HttpServletResponse;
32
33
34
35
36
37 public class RateLimitFilter implements Filter {
38
39 private static final Logger logger = LogManager.getLogger(RateLimitFilter.class);
40
41
42
43
44 public RateLimitFilter() {
45
46 }
47
48 @Override
49 public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
50 throws IOException, ServletException {
51 if (!ComponentUtil.available()) {
52 chain.doFilter(request, response);
53 return;
54 }
55
56 final RateLimitHelper rateLimitHelper = ComponentUtil.getRateLimitHelper();
57
58 if (!rateLimitHelper.isEnabled()) {
59 chain.doFilter(request, response);
60 return;
61 }
62
63 final HttpServletRequest httpRequest = (HttpServletRequest) request;
64 final HttpServletResponse httpResponse = (HttpServletResponse) response;
65 final String clientIp = rateLimitHelper.getClientIp(httpRequest);
66
67 if (logger.isDebugEnabled()) {
68 logger.debug("Rate limit check: clientIp={}, path={}", clientIp, httpRequest.getRequestURI());
69 }
70
71
72 if (rateLimitHelper.isBlocked(clientIp)) {
73 if (logger.isDebugEnabled()) {
74 logger.debug("Request blocked: clientIp={}", clientIp);
75 }
76 sendBlockedResponse(httpResponse);
77 return;
78 }
79
80
81 if (!rateLimitHelper.allowRequest(clientIp)) {
82 if (logger.isDebugEnabled()) {
83 logger.debug("Rate limit exceeded: clientIp={}", clientIp);
84 }
85 sendRateLimitResponse(httpResponse, rateLimitHelper.getRetryAfterSeconds());
86 return;
87 }
88
89 chain.doFilter(request, response);
90 }
91
92
93
94
95
96
97 protected void sendBlockedResponse(final HttpServletResponse response) throws IOException {
98 response.setStatus(HttpServletResponse.SC_FORBIDDEN);
99 response.setContentType("application/json;charset=UTF-8");
100 response.getWriter().write("{\"error\":\"ip_blocked\",\"message\":\"Access denied.\"}");
101 }
102
103
104
105
106
107
108
109 protected void sendRateLimitResponse(final HttpServletResponse response, final int retryAfterSeconds) throws IOException {
110 response.setStatus(429);
111 response.setContentType("application/json;charset=UTF-8");
112 response.setHeader("Retry-After", String.valueOf(retryAfterSeconds));
113 response.getWriter()
114 .write("{\"error\":\"rate_limit_exceeded\",\"message\":\"Too many requests. Please retry after " + retryAfterSeconds
115 + " seconds.\",\"retry_after\":" + retryAfterSeconds + "}");
116 }
117 }