Skip to content

Commit 2217238

Browse files
committed
out of box transformatons for proxied requests
path (e.g. prefix addition or removal) query (e.g. transform query param into path param) headers/trailers (filtering and modification) body (e.g. read JSON fully and modify fields) closes eclipse-vertx#65
1 parent c3609af commit 2217238

File tree

1 file changed

+148
-0
lines changed

1 file changed

+148
-0
lines changed

src/main/java/io/vertx/httpproxy/impl/ProxiedRequest.java

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@
2525
import io.vertx.core.impl.ContextInternal;
2626
import io.vertx.core.net.HostAndPort;
2727
import io.vertx.core.net.impl.HostAndPortImpl;
28+
import io.vertx.core.json.JsonObject;
2829
import io.vertx.core.streams.Pipe;
2930
import io.vertx.httpproxy.Body;
3031
import io.vertx.httpproxy.ProxyRequest;
3132
import io.vertx.httpproxy.ProxyResponse;
3233

34+
import java.net.URI;
35+
import java.util.HashMap;
3336
import java.util.Map;
3437
import java.util.Objects;
3538

@@ -228,4 +231,149 @@ public Future<ProxyResponse> send(HttpClientRequest request) {
228231
sendRequest(promise);
229232
return promise.future();
230233
}
234+
235+
236+
/**
237+
* Transforms the request path by adding a prefix.
238+
*
239+
* @param prefix The prefix to add to the request path
240+
* @return This ProxiedRequest instance for method chaining
241+
*/
242+
public io.vertx.httpproxy.impl.ProxiedRequest addPathPrefix(String prefix) {
243+
this.uri = prefix + this.uri;
244+
return this;
245+
}
246+
247+
/**
248+
* Transforms the request path by removing a prefix.
249+
*
250+
* @param prefix The prefix to remove from the request path
251+
* @return This ProxiedRequest instance for method chaining
252+
*/
253+
public io.vertx.httpproxy.impl.ProxiedRequest removePathPrefix(String prefix) {
254+
if (this.uri.startsWith(prefix)) {
255+
this.uri = this.uri.substring(prefix.length());
256+
}
257+
return this;
258+
}
259+
260+
/**
261+
* Transforms query parameters into path parameters.
262+
*
263+
* @return This ProxiedRequest instance for method chaining
264+
*/
265+
public io.vertx.httpproxy.impl.ProxiedRequest transformQueryToPathParams() {
266+
// Parse the original URI to extract query parameters
267+
URI originalUri = URI.create(this.uri);
268+
String originalPath = originalUri.getPath();
269+
String query = originalUri.getQuery();
270+
271+
// If there are query parameters, construct a new URI with them moved to the path
272+
if (query != null && !query.isEmpty()) {
273+
Map<String, String> queryParams = new HashMap<>();
274+
for (String param : query.split("&")) {
275+
String[] pair = param.split("=");
276+
queryParams.put(pair[0], pair[1]);
277+
}
278+
279+
// Reconstruct the path with query parameters replaced by path parameters
280+
StringBuilder newPath = new StringBuilder(originalPath);
281+
for (Map.Entry<String, String> entry : queryParams.entrySet()) {
282+
newPath.append("/").append(entry.getValue());
283+
}
284+
285+
// Update the uri field with the new path
286+
this.uri = newPath.toString();
287+
}
288+
289+
return this;
290+
}
291+
292+
293+
/**
294+
* Adds a header to the request.
295+
*
296+
* @param name The name of the header
297+
* @param value The value of the header
298+
* @return This ProxiedRequest instance for method chaining
299+
*/
300+
public io.vertx.httpproxy.impl.ProxiedRequest addHeader(String name, String value) {
301+
this.headers.add(name, value);
302+
return this;
303+
}
304+
305+
/**
306+
* Removes a header from the request.
307+
*
308+
* @param name The name of the header to remove
309+
* @return This ProxiedRequest instance for method chaining
310+
*/
311+
public io.vertx.httpproxy.impl.ProxiedRequest removeHeader(String name) {
312+
this.headers.remove(name);
313+
return this;
314+
}
315+
316+
/**
317+
* Modifies the value of a header.
318+
*
319+
* @param name The name of the header to modify
320+
* @param newVal The new value of the header
321+
* @return This ProxiedRequest instance for method chaining
322+
*/
323+
public ProxiedRequest modifyHeader(String name, String newVal) {
324+
this.headers.set(name, newVal);
325+
return this;
326+
}
327+
328+
/**
329+
* Modifies the request body by reading JSON fully and modifying specified fields.
330+
*
331+
* @param jsonObject A JsonObject containing fields to update and their new values
332+
* @return This ProxiedRequest instance for method chaining
333+
*/
334+
public ProxiedRequest setBody(JsonObject jsonObject) {
335+
// Buffer newBody = Buffer.buffer(jsonObject.encode());
336+
// ModifiedHttpServerRequest mr = new ModifiedHttpServerRequest(proxiedRequest, newBody);
337+
// body = Body.body(mr, newBody.length()+body.length());
338+
// Buffer modifiedBuffer = Buffer.buffer(jsonObject.encode());
339+
// this.body = Body.body(new BufferingReadStream(body.stream(), modifiedBuffer), body.length()+modifiedBuffer.length());
340+
body = Body.body(jsonObject.toBuffer());
341+
return this;
342+
}
343+
344+
/**
345+
* Retrieves the body content as a JSON object.
346+
*
347+
* @param resultHandler The handler to be called when the operation completes
348+
*/
349+
public void getBodyAsJson(Handler<JsonObject> resultHandler) {
350+
if (body != null) {
351+
BufferingWriteStream ws = new BufferingWriteStream();
352+
body.stream().pipeTo(ws, h->{
353+
if(h.succeeded()){
354+
resultHandler.handle(ws.content().toJsonObject());
355+
}
356+
});
357+
}
358+
}
359+
360+
public Future<JsonObject> getBodyAsJson() {
361+
Promise<JsonObject> promise = Promise.promise();
362+
363+
if (body != null && body.length()>0) {
364+
BufferingWriteStream ws = new BufferingWriteStream();
365+
366+
body.stream().pipeTo(ws, ar -> {
367+
if (ar.succeeded()) {
368+
JsonObject jsonObject = ws.content().toJsonObject();
369+
promise.complete(jsonObject);
370+
} else {
371+
promise.fail(ar.cause());
372+
}
373+
});
374+
} else {
375+
promise.fail("Body is null");
376+
}
377+
return promise.future();
378+
}
231379
}

0 commit comments

Comments
 (0)