Skip to content

Commit ac16d4b

Browse files
committed
Make the BodyTransformer asynchronous instead of being synchronous.
Motivation: The design of BodyTransformer is synchronous as currently it only applies to buffering functions. We should make this contract asynchronous and move the synchronous part in the implementations we currently support. Changes: BodyTransform transforms Body->Future<Body> instead of Buffer->Buffer Synchronous transformations are moved to a BodyTransfomers class Buffering overflow moves to the synchronous transformer instead of being in the interceptor since now the interceptor only sees an asynchronous transformation.
1 parent d21940f commit ac16d4b

File tree

8 files changed

+240
-213
lines changed

8 files changed

+240
-213
lines changed

src/main/java/examples/HttpProxyExamples.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import io.vertx.core.net.SocketAddress;
1414
import io.vertx.httpproxy.*;
1515
import io.vertx.httpproxy.cache.CacheOptions;
16-
import io.vertx.httpproxy.BodyTransformer;
1716

1817
import java.util.Set;
1918

@@ -136,7 +135,7 @@ public void bodyInterceptorJson(HttpProxy proxy) {
136135
ProxyInterceptor
137136
.builder()
138137
.transformingResponseBody(
139-
BodyTransformer.transformJsonObject(
138+
BodyTransformers.jsonObject(
140139
jsonObject -> removeSomeFields(jsonObject)
141140
)
142141
).build());

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

Lines changed: 11 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,7 @@
33
import io.vertx.codegen.annotations.GenIgnore;
44
import io.vertx.codegen.annotations.Unstable;
55
import io.vertx.codegen.annotations.VertxGen;
6-
import io.vertx.core.buffer.Buffer;
7-
import io.vertx.core.json.JsonArray;
8-
import io.vertx.core.json.JsonObject;
9-
import io.vertx.httpproxy.impl.BodyTransformerImpl;
10-
11-
import java.util.Collections;
12-
import java.util.List;
13-
import java.util.function.Function;
6+
import io.vertx.core.Future;
147

158
/**
169
* A synchronous function that transforms an HTTP body entity.
@@ -21,73 +14,29 @@ public interface BodyTransformer {
2114

2215
/**
2316
* @return whether this transformer consumes the {@code mediaType}, {@code mediaType} can be {@code null}
24-
* when the HTTP head does not present a body, the default implementation returns {@code false}
17+
* when the HTTP head does not present a body, the default implementation returns {@code true}
2518
*/
2619
default boolean consumes(MediaType mediaType) {
27-
return false;
20+
return true;
2821
}
2922

3023
/**
31-
* @return the media type produced by this transformer, the default implementation returns {@code application/octet-stream}
24+
* @return the media type produced by this transformer, the default implementation returns the same media type
3225
*/
3326
default MediaType produces(MediaType mediaType) {
3427
return mediaType;
3528
}
3629

37-
@GenIgnore
38-
Function<Buffer, Buffer> transformer(MediaType mediaType);
39-
40-
@GenIgnore(GenIgnore.PERMITTED_TYPE)
41-
static BodyTransformer transformer(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> transformer) {
42-
return new BodyTransformerImpl(transformer, consumedMediaType, producedMediaType);
43-
}
44-
4530
/**
46-
* Create a transformer that transforms JSON object to JSON object, the transformer accepts and produces {@code application/json}.
31+
* Return the future body, transformed.
4732
*
48-
* @param fn the operation to transform data
49-
* @return the transformer instance
50-
*/
51-
static BodyTransformer transformJsonObject(Function<JsonObject, JsonObject> fn) {
52-
return BodyTransformerImpl.transformJsonObject(fn);
53-
}
54-
55-
/**
56-
* Create a transformer that transforms JSON array to JSON array, the transformer accepts and produces {@code application/json}.
33+
* The default implementation returns the same body.
5734
*
58-
* @param fn the operation to transform data
59-
* @return the transformer instance
35+
* @param body the body to rewrite
36+
* @return a future of the transformed body
6037
*/
61-
static BodyTransformer transformJsonArray(Function<JsonArray, JsonArray> fn) {
62-
return BodyTransformerImpl.transformJsonArray(fn);
63-
}
64-
65-
/**
66-
* Create a transformer that transforms JSON value to JSON value, the transformer accepts and produces {@code application/json}.
67-
*
68-
* @param fn the operation to transform data
69-
* @return the transformer instance
70-
*/
71-
static BodyTransformer transformJson(Function<Object, Object> fn) {
72-
return BodyTransformerImpl.transformJson(fn);
73-
}
74-
75-
/**
76-
* Create a transformer that transforms text to text, the transformer accepts and produces {@code text/plain}.
77-
*
78-
* @param fn the operation to transform data
79-
* @return the transformer instance
80-
*/
81-
static BodyTransformer transformText(Function<String, String> fn, String encoding) {
82-
return BodyTransformerImpl.transformText(fn, encoding);
83-
}
84-
85-
/**
86-
* Create a transformer that discards the body, the transformer accepts any media type.
87-
*
88-
* @return the transformer instance
89-
*/
90-
static BodyTransformer discard() {
91-
return BodyTransformerImpl.discard();
38+
@GenIgnore
39+
default Future<Body> transform(Body body) {
40+
return Future.succeededFuture(body);
9241
}
9342
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package io.vertx.httpproxy;
2+
3+
import io.vertx.codegen.annotations.GenIgnore;
4+
import io.vertx.codegen.annotations.VertxGen;
5+
import io.vertx.core.buffer.Buffer;
6+
import io.vertx.core.json.JsonArray;
7+
import io.vertx.core.json.JsonObject;
8+
import io.vertx.httpproxy.impl.BodyTransformerImpl;
9+
10+
import java.util.function.Function;
11+
12+
/**
13+
* Range of transformers ready to be used.
14+
*/
15+
@VertxGen
16+
public interface BodyTransformers {
17+
18+
/**
19+
* The default maximum amount of bytes synchronous transformers apply
20+
*/
21+
long DEFAULT_MAX_BUFFERED_SIZE = 256 * 1024;
22+
23+
@GenIgnore(GenIgnore.PERMITTED_TYPE)
24+
static BodyTransformer transform(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> transformer) {
25+
return transform(consumedMediaType, producedMediaType, DEFAULT_MAX_BUFFERED_SIZE, transformer);
26+
}
27+
28+
@GenIgnore(GenIgnore.PERMITTED_TYPE)
29+
static BodyTransformer transform(MediaType consumedMediaType, MediaType producedMediaType, long maxBufferedBytes, Function<Buffer, Buffer> transformer) {
30+
return new BodyTransformerImpl(transformer, maxBufferedBytes, consumedMediaType, producedMediaType);
31+
}
32+
33+
/**
34+
* Create a transformer that transforms JSON object to JSON object, the transformer accepts and produces {@code application/json}.
35+
*
36+
* @param fn the operation to transform data
37+
* @return the transformer instance
38+
*/
39+
static BodyTransformer jsonObject(Function<JsonObject, JsonObject> fn) {
40+
return BodyTransformerImpl.transformJsonObject(fn);
41+
}
42+
43+
/**
44+
* Create a transformer that transforms JSON array to JSON array, the transformer accepts and produces {@code application/json}.
45+
*
46+
* @param fn the operation to transform data
47+
* @return the transformer instance
48+
*/
49+
static BodyTransformer jsonArray(Function<JsonArray, JsonArray> fn) {
50+
return BodyTransformerImpl.transformJsonArray(fn);
51+
}
52+
53+
/**
54+
* Create a transformer that transforms JSON value to JSON value, the transformer accepts and produces {@code application/json}.
55+
*
56+
* @param fn the operation to transform data
57+
* @return the transformer instance
58+
*/
59+
static BodyTransformer jsonValue(Function<Object, Object> fn) {
60+
return BodyTransformerImpl.transformJson(fn);
61+
}
62+
63+
/**
64+
* Create a transformer that transforms text to text, the transformer accepts and produces {@code text/plain}.
65+
*
66+
* @param fn the operation to transform data
67+
* @return the transformer instance
68+
*/
69+
static BodyTransformer text(Function<String, String> fn, String encoding) {
70+
return BodyTransformerImpl.transformText(encoding, fn);
71+
}
72+
73+
/**
74+
* Create a transformer that discards the body, the transformer accepts any media type.
75+
*
76+
* @return the transformer instance
77+
*/
78+
static BodyTransformer discard() {
79+
return BodyTransformerImpl.discard();
80+
}
81+
}

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

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
@Unstable
4141
public interface ProxyInterceptorBuilder {
4242

43-
long DEFAULT_MAX_BUFFERED_SIZE = 256 * 1024;
44-
4543
/**
4644
* @return the proxy interceptor build according to builder requirements
4745
*/
@@ -140,32 +138,23 @@ public interface ProxyInterceptorBuilder {
140138
@Fluent
141139
ProxyInterceptorBuilder filteringResponseHeaders(Set<CharSequence> forbiddenResponseHeaders);
142140

143-
/**
144-
* Like {@link #transformingRequestBody(BodyTransformer, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
145-
*/
146-
@Fluent
147-
default ProxyInterceptorBuilder transformingRequestBody(BodyTransformer requestTransformer) {
148-
return transformingRequestBody(requestTransformer, DEFAULT_MAX_BUFFERED_SIZE);
149-
}
150-
151141
/**
152142
* <p>Apply a transformation to change the request body when the proxy receives it.</p>
153143
*
154144
* <p>The interceptor fully buffers the request body and then applies the transformation.</p>
155145
*
156146
* @param requestTransformer the operation to apply to the request body
157-
* @param maxBufferedSize the maximum number of buffered bytes, when the buffered amount exceeds an HTTP error is sent
158147
* @return the created interceptor
159148
*/
160149
@Fluent
161-
ProxyInterceptorBuilder transformingRequestBody(BodyTransformer requestTransformer, long maxBufferedSize);
150+
ProxyInterceptorBuilder transformingRequestBody(BodyTransformer requestTransformer);
162151

163152
/**
164-
* Like {@link #transformingRequestBody(MediaType, MediaType, Function, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
153+
* Like {@link #transformingRequestBody(MediaType, MediaType, Function, long)} with {@code maxBufferedSize} = {@link BodyTransformers#DEFAULT_MAX_BUFFERED_SIZE}
165154
*/
166155
@Fluent
167156
default ProxyInterceptorBuilder transformingRequestBody(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> requestTransformer) {
168-
return transformingRequestBody(consumedMediaType, producedMediaType, requestTransformer, DEFAULT_MAX_BUFFERED_SIZE);
157+
return transformingRequestBody(consumedMediaType, producedMediaType, requestTransformer, BodyTransformers.DEFAULT_MAX_BUFFERED_SIZE);
169158
}
170159

171160
/**
@@ -181,15 +170,7 @@ default ProxyInterceptorBuilder transformingRequestBody(MediaType consumedMediaT
181170
*/
182171
@Fluent
183172
default ProxyInterceptorBuilder transformingRequestBody(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> requestTransformer, long maxBufferedSize) {
184-
return transformingRequestBody(new BodyTransformerImpl(requestTransformer, consumedMediaType, producedMediaType), maxBufferedSize);
185-
}
186-
187-
/**
188-
* Like {@link #transformingResponseBody(BodyTransformer, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
189-
*/
190-
@Fluent
191-
default ProxyInterceptorBuilder transformingResponseBody(BodyTransformer responseTransformer) {
192-
return transformingResponseBody(responseTransformer, DEFAULT_MAX_BUFFERED_SIZE);
173+
return transformingRequestBody(new BodyTransformerImpl(requestTransformer, maxBufferedSize, consumedMediaType, producedMediaType));
193174
}
194175

195176
/**
@@ -198,18 +179,17 @@ default ProxyInterceptorBuilder transformingResponseBody(BodyTransformer respons
198179
* <p>The interceptor fully buffers the response body and then applies the transformation.</p>
199180
*
200181
* @param responseTransformer the operation to apply to the response body
201-
* @param maxBufferedSize the maximum number of buffered bytes, when the buffered amount exceeds an HTTP error is sent
202182
* @return the created interceptor
203183
*/
204184
@Fluent
205-
ProxyInterceptorBuilder transformingResponseBody(BodyTransformer responseTransformer, long maxBufferedSize);
185+
ProxyInterceptorBuilder transformingResponseBody(BodyTransformer responseTransformer);
206186

207187
/**
208-
* Like {@link #transformingResponseBody(MediaType, MediaType, Function, long)} with {@code maxBufferedSize} = {@link #DEFAULT_MAX_BUFFERED_SIZE}
188+
* Like {@link #transformingResponseBody(MediaType, MediaType, Function, long)} with {@code maxBufferedSize} = {@link BodyTransformers#DEFAULT_MAX_BUFFERED_SIZE}
209189
*/
210190
@Fluent
211191
default ProxyInterceptorBuilder transformingResponseBody(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> responseTransformer) {
212-
return transformingResponseBody(consumedMediaType, producedMediaType, responseTransformer, DEFAULT_MAX_BUFFERED_SIZE);
192+
return transformingResponseBody(consumedMediaType, producedMediaType, responseTransformer, BodyTransformers.DEFAULT_MAX_BUFFERED_SIZE);
213193
}
214194

215195
/**
@@ -225,7 +205,7 @@ default ProxyInterceptorBuilder transformingResponseBody(MediaType consumedMedia
225205
*/
226206
@Fluent
227207
default ProxyInterceptorBuilder transformingResponseBody(MediaType consumedMediaType, MediaType producedMediaType, Function<Buffer, Buffer> responseTransformer, long maxBufferedSize) {
228-
return transformingResponseBody(new BodyTransformerImpl(responseTransformer, consumedMediaType, producedMediaType), maxBufferedSize);
208+
return transformingResponseBody(new BodyTransformerImpl(responseTransformer, maxBufferedSize, consumedMediaType, producedMediaType));
229209
}
230210

231211
}

0 commit comments

Comments
 (0)