1
1
package com .metlo .spring ;
2
2
3
- import com .google .gson .Gson ;
3
+ import com .metlo .spring .utils .ContentCachingResponseWrapperWithHeaderNames ;
4
+ import com .metlo .spring .utils .RateLimitingRequests ;
5
+
4
6
import org .springframework .web .filter .OncePerRequestFilter ;
5
7
import org .springframework .web .util .ContentCachingRequestWrapper ;
6
- import org .springframework .web .util .ContentCachingResponseWrapper ;
7
8
8
9
import javax .servlet .FilterChain ;
9
10
import javax .servlet .ServletException ;
10
11
import javax .servlet .http .HttpServletRequest ;
11
12
import javax .servlet .http .HttpServletResponse ;
12
13
import java .io .IOException ;
13
- import java .io .OutputStream ;
14
14
import java .io .UnsupportedEncodingException ;
15
- import java .net .HttpURLConnection ;
16
- import java .net .URL ;
17
- import java .net .URLConnection ;
18
- import java .nio .charset .StandardCharsets ;
19
15
import java .util .*;
20
- import java .util .concurrent .SynchronousQueue ;
21
- import java .util .concurrent .ThreadPoolExecutor ;
22
- import java .util .concurrent .TimeUnit ;
23
16
import java .util .function .Function ;
24
17
18
+
25
19
public class Metlo extends OncePerRequestFilter {
26
- private static final int DEFAULT_THREAD_POOL_SIZE = 8 ;
27
- private final static String endpoint = "/api/v1/log-request/single" ;
28
- private final ThreadPoolExecutor pool ;
29
- private final String METLO_KEY ;
30
- private final String METLO_ADDR ;
20
+ private static final int DEFAULT_THREAD_POOL_SIZE = 2 ;
21
+
22
+ private static final int DEFAULT_RPS = 10 ;
23
+ private final static String endpoint = "api/v1/log-request/single" ;
24
+
25
+ private final Boolean enabled ;
26
+
27
+ private final RateLimitingRequests req ;
31
28
32
29
public Metlo (String host , String api_key ) {
33
- this (DEFAULT_THREAD_POOL_SIZE , host , api_key );
30
+ this (DEFAULT_THREAD_POOL_SIZE , host , api_key , DEFAULT_RPS );
34
31
}
35
32
36
- public Metlo (int pool_size , String host , String api_key ) {
37
- this .METLO_KEY = api_key ;
38
- this .METLO_ADDR = host + Metlo .endpoint ;
39
- this .pool = new ThreadPoolExecutor (0 , pool_size ,
40
- 60L , TimeUnit .SECONDS ,
41
- new SynchronousQueue <Runnable >());
33
+ public Metlo (String host , String api_key , Integer rps ) {
34
+ this (DEFAULT_THREAD_POOL_SIZE , host , api_key , rps );
42
35
}
43
36
44
- private void pushRequest (Map <String , Object > data ) throws IOException {
45
- URL url = new URL (this .METLO_ADDR );
46
- URLConnection con = url .openConnection ();
47
- HttpURLConnection http = (HttpURLConnection ) con ;
48
- http .setRequestMethod ("POST" ); // PUT is another valid option
49
- http .setRequestProperty ("Authorization" , this .METLO_KEY );
50
- http .setDoOutput (true );
51
- Gson gson = new Gson ();
52
- String json = gson .toJson (data );
53
-
54
- byte [] out = json .getBytes (StandardCharsets .UTF_8 );
55
- int length = out .length ;
56
-
57
- http .setFixedLengthStreamingMode (length );
58
- http .setRequestProperty ("Content-Type" , "application/json; charset=UTF-8" );
59
- http .connect ();
60
- try (OutputStream os = http .getOutputStream ()) {
61
- os .write (out );
37
+ public Metlo (int pool_size , String host , String api_key , Integer rps ) {
38
+
39
+ String METLO_ADDR = host ;
40
+ if (host .charAt (host .length () - 1 ) == '/' ) {
41
+ METLO_ADDR += endpoint ;
42
+ } else {
43
+ METLO_ADDR += "/" + endpoint ;
44
+ }
45
+ this .req = new RateLimitingRequests (rps , pool_size , METLO_ADDR , api_key );
46
+
47
+ String enabled = System .getenv ("METLO_ENABLED" );
48
+ if (enabled != null ) {
49
+ this .enabled = Boolean .parseBoolean (enabled );
50
+ } else {
51
+ this .enabled = true ;
62
52
}
63
53
}
64
54
55
+
65
56
@ Override
66
57
protected void doFilterInternal (HttpServletRequest request , HttpServletResponse response , FilterChain filterChain )
67
58
throws ServletException , IOException {
59
+
68
60
ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper (request );
69
- ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper (response );
61
+ ContentCachingResponseWrapperWithHeaderNames responseWrapper = new ContentCachingResponseWrapperWithHeaderNames (response );
70
62
71
63
filterChain .doFilter (requestWrapper , responseWrapper );
72
-
73
- String requestBody = getStringValue (requestWrapper .getContentAsByteArray (),
74
- request .getCharacterEncoding ());
75
- String responseBody = getStringValue (responseWrapper .getContentAsByteArray (),
76
- response .getCharacterEncoding ());
77
-
78
- this .pool .submit (() -> {
79
- try {
80
- this .pushRequest (createDataBinding (requestWrapper , responseWrapper , requestBody , responseBody ));
81
- } catch (Exception e ) {
82
- e .printStackTrace ();
83
- }
84
- });
85
- responseWrapper .copyBodyToResponse ();
64
+ if (this .enabled ) {
65
+ String requestBody = getStringValue (requestWrapper .getContentAsByteArray (),
66
+ request .getCharacterEncoding ());
67
+ String responseBody = getStringValue (responseWrapper .getContentAsByteArray (),
68
+ response .getCharacterEncoding ());
69
+
70
+ this .req .send (createDataBinding (requestWrapper , responseWrapper , requestBody , responseBody ));
71
+ responseWrapper .copyBodyToResponse ();
72
+ }
86
73
}
87
74
88
75
private String getStringValue (byte [] contentAsByteArray , String characterEncoding ) {
@@ -94,7 +81,7 @@ private String getStringValue(byte[] contentAsByteArray, String characterEncodin
94
81
return "" ;
95
82
}
96
83
97
- private Map <String , Object > createDataBinding (HttpServletRequest request , HttpServletResponse response , String request_body , String response_body ) throws Exception {
84
+ private Map <String , Object > createDataBinding (HttpServletRequest request , ContentCachingResponseWrapperWithHeaderNames response , String request_body , String response_body ) {
98
85
Map <String , Object > DATA = new HashMap <String , Object >();
99
86
Map <String , Object > REQUEST = new HashMap <>();
100
87
Map <String , Object > REQUEST_URL = new HashMap <>();
@@ -146,8 +133,8 @@ private List<Map<String, String>> listParamFormat(Map<String, String[]> map) {
146
133
List <Map <String , String >> _formatted_params_ = new ArrayList <>();
147
134
for (Map .Entry <String , String []> entry_raw : map .entrySet ()) {
148
135
HashMap <String , String > entry = new HashMap <String , String >();
149
- entry .put ("Name " , entry_raw .getKey ());
150
- entry .put ("Value " , "[" + String .join ("," , entry_raw .getValue ()) + "]" );
136
+ entry .put ("name " , entry_raw .getKey ());
137
+ entry .put ("value " , "[" + String .join ("," , entry_raw .getValue ()) + "]" );
151
138
_formatted_params_ .add (entry );
152
139
}
153
140
return _formatted_params_ ;
@@ -159,8 +146,8 @@ private List<Map<String, String>> listRequestHeaderFormat(Enumeration<String> he
159
146
String headerName = headerNameIter .next ();
160
147
String headerValue = headerValueForName .apply (headerName );
161
148
Map <String , String > individualHeader = new HashMap <String , String >();
162
- individualHeader .put ("Name " , headerName );
163
- individualHeader .put ("Value " , headerValue );
149
+ individualHeader .put ("name " , headerName );
150
+ individualHeader .put ("value " , headerValue );
164
151
headers .add (individualHeader );
165
152
}
166
153
return headers ;
@@ -171,8 +158,8 @@ private List<Map<String, String>> listResponseHeaderFormat(Collection<String> he
171
158
for (String headerName : headerNames ) {
172
159
String headerValue = headerValueForName .apply (headerName );
173
160
Map <String , String > individualHeader = new HashMap <String , String >();
174
- individualHeader .put ("Name " , headerName );
175
- individualHeader .put ("Value " , headerValue );
161
+ individualHeader .put ("name " , headerName );
162
+ individualHeader .put ("value " , headerValue );
176
163
headers .add (individualHeader );
177
164
}
178
165
return headers ;
0 commit comments