Skip to content

Commit 1b1e0e7

Browse files
committed
- Unify body and head interceptor in a single builder
- Add max buffered size during body interception - Handle body and head interception failures Motivation: The body and head interception API can be unified further more by providing a single interceptor instead of two interceptors. The current body transformation API assumes buffering and therefore uses buffer cumulation, therefore it should have an upper bound regarding this cumulation. The interceptor implementation does not handle failures such as a transformation failure or a buffer overflow.
1 parent 81f788a commit 1b1e0e7

19 files changed

+567
-370
lines changed

src/main/asciidoc/index.adoc

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -134,26 +134,24 @@ You can filter body by simply replacing the original {@link io.vertx.httpproxy.B
134134
{@link io.vertx.httpproxy.ProxyContext#sendRequest} and {@link io.vertx.httpproxy.ProxyContext#sendResponse} continue the
135135
current interception chain and then send the result to the origin server or the user-agent.
136136

137-
You can change the control, e.g you can send a response immediately to the user-agent without even requesting the origin server
137+
You can change the control, e.g. you can send a response immediately to the user-agent without even requesting the origin server
138138

139139
[source,java]
140140
----
141141
{@link examples.HttpProxyExamples#immediateResponse}
142142
----
143143

144-
==== Head interceptor
144+
==== Customizable interceptor
145145

146-
You can use the {@link io.vertx.httpproxy.interceptors.HeadInterceptor} to change HTTP request/response heads:
146+
You can use {@link io.vertx.httpproxy.ProxyInterceptor#builder()} that facilitates the implementation of an interceptor
147+
that modifies the request/response heads and bodies:
147148

148149
- request path
149150
- query params
150151
- request and response headers
152+
- body transformation
151153

152-
A {@link io.vertx.httpproxy.interceptors.HeadInterceptor} is created and configured with a {@link io.vertx.httpproxy.interceptors.HeadInterceptorBuilder}.
153-
154-
The builder methods can be invoked several times.
155-
Operations on the path will be invoked in the order of configuration.
156-
That goes for operations on query parameters, request headers and response headers.
154+
Such interceptor is created and configured with a {@link io.vertx.httpproxy.ProxyInterceptorBuilder}.
157155

158156
===== Headers interception
159157

@@ -164,7 +162,9 @@ You can apply the interceptor to change headers from the request and response wi
164162
{@link examples.HttpProxyExamples#headerInterceptorFilter}
165163
----
166164

167-
Check out {@link io.vertx.httpproxy.interceptors.HeadInterceptorBuilder} for details about the available methods.
165+
Headers modifying methods can be invoked several times, operations are applied in the order of configuration.
166+
167+
Check out {@link io.vertx.httpproxy.ProxyInterceptorBuilder} for details about the available methods.
168168

169169
===== Query params interception
170170

@@ -175,18 +175,27 @@ You can apply the interceptor to update or remove query parameters:
175175
{@link examples.HttpProxyExamples#queryInterceptorAdd}
176176
----
177177

178-
You can also refer to {@link io.vertx.httpproxy.interceptors.HeadInterceptorBuilder} for more information.
178+
Query params modifying methods can be invoked several times, operations are applied in the order of configuration.
179+
180+
You can also refer to {@link io.vertx.httpproxy.ProxyInterceptorBuilder} for more information.
179181

180182
==== Body interceptor
181183

182-
You can use body interceptor to create body transformations for common data types, like {@link io.vertx.core.json.JsonObject}:
184+
You can use body interceptor to create body transformations.
185+
186+
[source,java]
187+
----
188+
{@link examples.HttpProxyExamples#bodyInterceptorJson}
189+
----
190+
191+
{@link io.vertx.httpproxy.BodyTransformer} provides transformation for common data types, like {@link io.vertx.core.json.JsonObject}:
183192

184193
[source,java]
185194
----
186195
{@link examples.HttpProxyExamples#bodyInterceptorJson}
187196
----
188197

189-
Please check the {@link io.vertx.httpproxy.interceptors.BodyTransformer} for other supported transformations.
198+
Please check the {@link io.vertx.httpproxy.BodyTransformer} for other supported transformations.
190199

191200
==== Interception and WebSocket upgrades
192201

src/main/java/examples/HttpProxyExamples.java

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@
1313
import io.vertx.core.net.SocketAddress;
1414
import io.vertx.httpproxy.*;
1515
import io.vertx.httpproxy.cache.CacheOptions;
16-
import io.vertx.httpproxy.interceptors.BodyInterceptor;
17-
import io.vertx.httpproxy.interceptors.BodyTransformer;
18-
import io.vertx.httpproxy.interceptors.HeadInterceptor;
16+
import io.vertx.httpproxy.BodyTransformer;
1917

2018
import java.util.Set;
2119

@@ -111,25 +109,39 @@ public Future<Void> handleProxyResponse(ProxyContext context) {
111109
public void headerInterceptorFilter(HttpProxy proxy, Set<CharSequence> shouldRemove) {
112110
// remove a set of headers
113111
proxy.addInterceptor(
114-
HeadInterceptor.builder().filteringResponseHeaders(shouldRemove).build());
112+
ProxyInterceptor.builder().filteringResponseHeaders(shouldRemove).build());
115113
}
116114

117115
public void queryInterceptorAdd(HttpProxy proxy, String key, String value) {
118116
proxy.addInterceptor(
119-
HeadInterceptor.builder().settingQueryParam(key, value).build());
117+
ProxyInterceptor.builder().settingQueryParam(key, value).build());
118+
}
119+
120+
public void bodyInterceptorTransformer(HttpProxy proxy) {
121+
proxy.addInterceptor(
122+
ProxyInterceptor
123+
.builder()
124+
.transformingResponseBody(
125+
buffer -> {
126+
// Apply some transformation
127+
return buffer;
128+
}
129+
).build());
120130
}
121131

122132
public void bodyInterceptorJson(HttpProxy proxy) {
123133
proxy.addInterceptor(
124-
BodyInterceptor.modifyResponseBody(
125-
BodyTransformer.transformJsonObject(
126-
jsonObject -> removeSomeFields(jsonObject)
127-
)
128-
));
134+
ProxyInterceptor
135+
.builder()
136+
.transformingResponseBody(
137+
BodyTransformer.transformJsonObject(
138+
jsonObject -> removeSomeFields(jsonObject)
139+
)
140+
).build());
129141
}
130142

131143
public void webSocketInterceptorPath(HttpProxy proxy) {
132-
HeadInterceptor interceptor = HeadInterceptor.builder()
144+
ProxyInterceptor interceptor = ProxyInterceptor.builder()
133145
.addingPathPrefix("/api")
134146
.build();
135147
proxy.addInterceptor(interceptor, true);

src/main/java/io/vertx/httpproxy/interceptors/BodyTransformer.java renamed to src/main/java/io/vertx/httpproxy/BodyTransformer.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
package io.vertx.httpproxy.interceptors;
1+
package io.vertx.httpproxy;
22

33
import io.vertx.codegen.annotations.Unstable;
44
import io.vertx.codegen.annotations.VertxGen;
55
import io.vertx.core.buffer.Buffer;
66
import io.vertx.core.json.JsonArray;
77
import io.vertx.core.json.JsonObject;
8-
import io.vertx.httpproxy.interceptors.impl.BodyTransformerImpl;
8+
import io.vertx.httpproxy.impl.BodyTransformerImpl;
99

1010
import java.util.function.Function;
1111

1212
/**
13-
* The callback to transform the request or response body.
13+
* A synchronous function that transforms an HTTP body entity.
1414
*/
1515
@VertxGen
1616
@Unstable

src/main/java/io/vertx/httpproxy/ProxyInterceptor.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,24 @@
22

33
import io.vertx.codegen.annotations.VertxGen;
44
import io.vertx.core.Future;
5+
import io.vertx.httpproxy.impl.interceptor.ProxyInterceptorBuilderImpl;
56

67
/**
78
* A {@link HttpProxy} interceptor.
89
*/
9-
@VertxGen(concrete = false)
10+
@VertxGen
1011
public interface ProxyInterceptor {
1112

13+
/**
14+
* Create a builder for implementing common HTTP interception hooks such as modifying headers or transforming
15+
* the HTTP entity stream.
16+
*
17+
* @return a builder for common interception
18+
*/
19+
static ProxyInterceptorBuilder builder() {
20+
return new ProxyInterceptorBuilderImpl();
21+
}
22+
1223
/**
1324
* Handle the proxy request at the stage of this interceptor.
1425
*

src/main/java/io/vertx/httpproxy/interceptors/HeadInterceptorBuilder.java renamed to src/main/java/io/vertx/httpproxy/ProxyInterceptorBuilder.java

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
1010
*/
1111

12-
package io.vertx.httpproxy.interceptors;
12+
package io.vertx.httpproxy;
1313

1414
import io.vertx.codegen.annotations.Fluent;
1515
import io.vertx.codegen.annotations.GenIgnore;
@@ -24,20 +24,26 @@
2424
import static io.vertx.codegen.annotations.GenIgnore.PERMITTED_TYPE;
2525

2626
/**
27-
* Configuration for an interceptor updating HTTP request/response head attributes (headers, path, query params).
28-
* <p>
29-
* All configuration methods can be invoked several times.
30-
* Operations on the path will be invoked in the order of configuration.
31-
* That goes for operations on request headers, response headers and query parameters.
27+
* <p>>Builder class for a customizable interceptor capable of transforming HTTP request/response head attributes
28+
* (headers, path, query params) as well as transforming the HTTP body.</p
29+
*
30+
* <p>Head transformation methods can be invoked multiple times. Operations on the path will be invoked in the order
31+
* of configuration, that goes for operations on request headers, response headers and query parameters.</p>
32+
*
33+
* <p>Body transformation can be achieved with {@link #transformingResponseBody(BodyTransformer)} and
34+
* {@link #transformingRequestBody(BodyTransformer)}. Body transformation buffer the body content and then apply
35+
* a transforming function before sending the response.</p>
3236
*/
3337
@VertxGen
3438
@Unstable
35-
public interface HeadInterceptorBuilder {
39+
public interface ProxyInterceptorBuilder {
40+
41+
long DEFAULT_MAX_BUFFERED_SIZE = 256 * 1024;
3642

3743
/**
38-
* @return an interceptor build according to builder requirements
44+
* @return the proxy interceptor build according to builder requirements
3945
*/
40-
HeadInterceptor build();
46+
ProxyInterceptor build();
4147

4248
/**
4349
* Apply modifications to the query parameters.
@@ -46,7 +52,7 @@ public interface HeadInterceptorBuilder {
4652
* @return a reference to this, so the API can be used fluently
4753
*/
4854
@Fluent
49-
HeadInterceptorBuilder updatingQueryParams(Handler<MultiMap> updater);
55+
ProxyInterceptorBuilder transformingQueryParams(Handler<MultiMap> updater);
5056

5157
/**
5258
* Add a query parameter to the request.
@@ -56,7 +62,7 @@ public interface HeadInterceptorBuilder {
5662
* @return a reference to this, so the API can be used fluently
5763
*/
5864
@Fluent
59-
HeadInterceptorBuilder settingQueryParam(String name, String value);
65+
ProxyInterceptorBuilder settingQueryParam(String name, String value);
6066

6167
/**
6268
* Remove a query parameter from the request.
@@ -65,7 +71,7 @@ public interface HeadInterceptorBuilder {
6571
* @return a reference to this, so the API can be used fluently
6672
*/
6773
@Fluent
68-
HeadInterceptorBuilder removingQueryParam(String name);
74+
ProxyInterceptorBuilder removingQueryParam(String name);
6975

7076
/**
7177
* Apply a callback to change the request URI when the proxy receives it.
@@ -74,7 +80,7 @@ public interface HeadInterceptorBuilder {
7480
* @return a reference to this, so the API can be used fluently
7581
*/
7682
@Fluent
77-
HeadInterceptorBuilder updatingPath(Function<String, String> mutator);
83+
ProxyInterceptorBuilder transformingPath(Function<String, String> mutator);
7884

7985
/**
8086
* Add a prefix to the URI.
@@ -83,7 +89,7 @@ public interface HeadInterceptorBuilder {
8389
* @return a reference to this, so the API can be used fluently
8490
*/
8591
@Fluent
86-
HeadInterceptorBuilder addingPathPrefix(String prefix);
92+
ProxyInterceptorBuilder addingPathPrefix(String prefix);
8793

8894
/**
8995
* Remove a prefix to the URI. Do nothing if it doesn't exist.
@@ -92,7 +98,7 @@ public interface HeadInterceptorBuilder {
9298
* @return a reference to this, so the API can be used fluently
9399
*/
94100
@Fluent
95-
HeadInterceptorBuilder removingPathPrefix(String prefix);
101+
ProxyInterceptorBuilder removingPathPrefix(String prefix);
96102

97103
/**
98104
* Apply callbacks to change the request headers when the proxy receives them.
@@ -101,7 +107,7 @@ public interface HeadInterceptorBuilder {
101107
* @return a reference to this, so the API can be used fluently
102108
*/
103109
@Fluent
104-
HeadInterceptorBuilder updatingRequestHeaders(Handler<MultiMap> requestHeadersUpdater);
110+
ProxyInterceptorBuilder transformingRequestHeaders(Handler<MultiMap> requestHeadersUpdater);
105111

106112
/**
107113
* Apply callbacks to change the response headers when the proxy receives them.
@@ -110,7 +116,7 @@ public interface HeadInterceptorBuilder {
110116
* @return a reference to this, so the API can be used fluently
111117
*/
112118
@Fluent
113-
HeadInterceptorBuilder updatingResponseHeaders(Handler<MultiMap> responseHeadersUpdater);
119+
ProxyInterceptorBuilder transformingResponseHeaders(Handler<MultiMap> responseHeadersUpdater);
114120

115121
/**
116122
* Filter the request headers in the given set.
@@ -120,7 +126,7 @@ public interface HeadInterceptorBuilder {
120126
*/
121127
@GenIgnore(PERMITTED_TYPE)
122128
@Fluent
123-
HeadInterceptorBuilder filteringRequestHeaders(Set<CharSequence> forbiddenRequestHeaders);
129+
ProxyInterceptorBuilder filteringRequestHeaders(Set<CharSequence> forbiddenRequestHeaders);
124130

125131
/**
126132
* Filter the response headers in the given set.
@@ -130,5 +136,46 @@ public interface HeadInterceptorBuilder {
130136
*/
131137
@GenIgnore(PERMITTED_TYPE)
132138
@Fluent
133-
HeadInterceptorBuilder filteringResponseHeaders(Set<CharSequence> forbiddenResponseHeaders);
139+
ProxyInterceptorBuilder filteringResponseHeaders(Set<CharSequence> forbiddenResponseHeaders);
140+
141+
/**
142+
* Like {@link #transformingRequestBody(BodyTransformer, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
143+
*/
144+
@Fluent
145+
default ProxyInterceptorBuilder transformingRequestBody(BodyTransformer requestTransformer) {
146+
return transformingRequestBody(requestTransformer, DEFAULT_MAX_BUFFERED_SIZE);
147+
}
148+
149+
/**
150+
* <p>Apply a transformation to change the request body when the proxy receives it.</p>
151+
*
152+
* <p>The interceptor fully buffers the request body and then apply the transformation.</p>
153+
*
154+
* @param requestTransformer the operation to apply to the request body
155+
* @param maxBufferedSize the maximum number of buffered bytes, when the buffered amount exceeds an HTTP error is sent
156+
* @return the created interceptor
157+
*/
158+
@Fluent
159+
ProxyInterceptorBuilder transformingRequestBody(BodyTransformer requestTransformer, long maxBufferedSize);
160+
161+
/**
162+
* Like {@link #transformingResponseBody(BodyTransformer, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
163+
*/
164+
@Fluent
165+
default ProxyInterceptorBuilder transformingResponseBody(BodyTransformer responseTransformer) {
166+
return transformingResponseBody(responseTransformer, DEFAULT_MAX_BUFFERED_SIZE);
167+
}
168+
169+
/**
170+
* <p>Apply a transformation to change the response body when the proxy receives it.</p>
171+
*
172+
* <p>The interceptor fully buffers the response body and then apply the transformation.</p>
173+
*
174+
* @param responseTransformer the operation to apply to the response body
175+
* @param maxBufferedSize the maximum number of buffered bytes, when the buffered amount exceeds an HTTP error is sent
176+
* @return the created interceptor
177+
*/
178+
@Fluent
179+
ProxyInterceptorBuilder transformingResponseBody(BodyTransformer responseTransformer, long maxBufferedSize);
180+
134181
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
package io.vertx.httpproxy.interceptors.impl;
1+
package io.vertx.httpproxy.impl;
22

33
import io.vertx.core.buffer.Buffer;
44
import io.vertx.core.json.Json;
55
import io.vertx.core.json.JsonArray;
66
import io.vertx.core.json.JsonObject;
7-
import io.vertx.httpproxy.interceptors.BodyTransformer;
7+
import io.vertx.httpproxy.BodyTransformer;
88

99
import java.util.Objects;
1010
import java.util.function.Function;

0 commit comments

Comments
 (0)