Skip to content

Commit

Permalink
HTTP Proxy examples
Browse files Browse the repository at this point in the history
Signed-off-by: Thomas Segismont <tsegismont@gmail.com>
  • Loading branch information
tsegismont committed Nov 28, 2024
1 parent 50b8cd4 commit 3109483
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 0 deletions.
57 changes: 57 additions & 0 deletions http-proxy-examples/README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
= Vert.x HTTP Proxy examples

Here you will find examples demonstrating Vert.x HTTP Proxy.

Vert.x HTTP Proxy is a reverse proxy based on Vert.x, it aims to implement reusable reverse proxy logic to focus on higher concerns.

[#_simple_reverse_proxy]
== Simple reverse proxy
In this example, there are two verticles:
* the backend verticle, which is a simple HTTP server replying to requests with a greeting, and
* the proxy verticle, which configures a `ReverseProxy` that relays incoming traffic to the backend.
After starting the backend and the proxy, browse to http://localhost:8080 or your use your favorite command-line tool, such as `curl` or `HTTPie`.
link:src/main/java/io/vertx/example/proxy/simple/Backend.java[`Backend`]
link:src/main/java/io/vertx/example/proxy/simple/Proxy.java[`Proxy`]
== Proxy interceptors
This example is a follow-up of the <<_simple_reverse_proxy,simple reverse proxy>> example.
The backend replies with a success code (200) only to requests starting with the `/app` prefix.
Besides, it puts an internal HTTP header value on responses.
The proxy uses two types of interceptors: head and body interceptors.
The head interceptor is configured to:
- add the `/app` prefix to the path of HTTP requests
- remove the internal HTTP header from HTTP responses
The body interceptor is configured to replace `Hello` with `Hi in the response text.
After starting the backend and the proxy, browse to http://localhost:8080 or your use your favorite command-line tool, such as `curl` or `HTTPie`.
link:src/main/java/io/vertx/example/proxy/interception/Backend.java[`Backend`]
link:src/main/java/io/vertx/example/proxy/interception/Proxy.java[`Proxy`]
== WebSocket support
In this example, there are three verticles:
* the backend verticle, which is a simple WebSocket server sending messages periodically to clients, and
* the proxy verticle, which configures a `ReverseProxy` for WebSocket support, and
* the client verticle, which connects a WebSocket to the proxy
After starting the different parts, the client should print this message every 3 seconds:
----
Received message: Hello World
----
link:src/main/java/io/vertx/example/proxy/websocket/Backend.java[`Backend`]
link:src/main/java/io/vertx/example/proxy/websocket/Proxy.java[`Proxy`]
link:src/main/java/io/vertx/example/proxy/websocket/Client.java[`Client`]
38 changes: 38 additions & 0 deletions http-proxy-examples/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>io.vertx</groupId>
<artifactId>vertx-examples</artifactId>
<version>5.0.0.CR2</version>
</parent>

<artifactId>http-proxy-examples</artifactId>

<dependencies>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-launcher-application</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-http-proxy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>io.vertx</groupId>
<artifactId>vertx-web</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.vertx.example.proxy.interception;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.launcher.application.VertxApplication;

public class Backend extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Backend.class.getName()});
}

@Override
public Future<?> start() {
return vertx
.createHttpServer()
.requestHandler(req -> {
if (req.path().equals("/app") || req.path().startsWith("/app")) {
req.response()
.putHeader("x-internal-header", "some-internal-header-value")
.putHeader("content-type", "text/html")
.end("<html><body><h1>Hello from Vert.x!</h1></body></html>");
} else {
req.response().setStatusCode(400).end();
}
}).listen(7070);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.vertx.example.proxy.interception;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.httpproxy.HttpProxy;
import io.vertx.httpproxy.interceptors.BodyInterceptor;
import io.vertx.httpproxy.interceptors.BodyTransformer;
import io.vertx.httpproxy.interceptors.HeadInterceptor;
import io.vertx.launcher.application.VertxApplication;

import java.util.Set;

public class Proxy extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Proxy.class.getName()});
}

@Override
public Future<?> start() {
HttpClient proxyClient = vertx.createHttpClient();

HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.origin(7070, "localhost");

HeadInterceptor headInterceptor = HeadInterceptor.builder()
.addingPathPrefix("/app")
.filteringResponseHeaders(Set.of("x-internal-header"))
.build();
proxy.addInterceptor(headInterceptor);

BodyTransformer responseTransformer = BodyTransformer.transformText(txt -> {
return txt.replace("Hello", "Hi");
}, "ISO-8859-1");
proxy.addInterceptor(BodyInterceptor.modifyResponseBody(responseTransformer));

HttpServer proxyServer = vertx.createHttpServer();

return proxyServer.requestHandler(proxy).listen(8080);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.vertx.example.proxy.simple;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.launcher.application.VertxApplication;

public class Backend extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Backend.class.getName()});
}

@Override
public Future<?> start() {
return vertx
.createHttpServer()
.requestHandler(req -> {
req.response().putHeader("content-type", "text/html").end("<html><body><h1>Hello from Vert.x!</h1></body></html>");
}).listen(7070);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.vertx.example.proxy.simple;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.httpproxy.HttpProxy;
import io.vertx.httpproxy.ProxyOptions;
import io.vertx.launcher.application.VertxApplication;

public class Proxy extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Proxy.class.getName()});
}

@Override
public Future<?> start() {
HttpClient proxyClient = vertx.createHttpClient();

HttpProxy proxy = HttpProxy.reverseProxy(new ProxyOptions().setSupportWebSocket(true), proxyClient);
proxy.origin(7070, "localhost");

HttpServer proxyServer = vertx.createHttpServer();

return proxyServer.requestHandler(proxy).listen(8080);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.vertx.example.proxy.websocket;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.launcher.application.VertxApplication;

public class Backend extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Backend.class.getName()});
}

@Override
public Future<?> start() {
return vertx
.createHttpServer()
.webSocketHandler(ws -> {
vertx.setPeriodic(3000, tid -> {
if (ws.isClosed()) {
vertx.cancelTimer(tid);
return;
}
ws.writeTextMessage("Hello World");
});
}).listen(7070);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package io.vertx.example.proxy.websocket;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.http.WebSocketClient;
import io.vertx.core.http.WebSocketConnectOptions;
import io.vertx.launcher.application.VertxApplication;

public class Client extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Client.class.getName()});
}

private WebSocketClient client;

@Override
public Future<?> start() throws Exception {
client = vertx.createWebSocketClient();
return client.connect(new WebSocketConnectOptions().setHost("localhost").setPort(8080))
.onSuccess(ws -> ws.textMessageHandler(msg -> {
System.out.println("Received message: " + msg);
}));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.vertx.example.proxy.websocket;

import io.vertx.core.Future;
import io.vertx.core.VerticleBase;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpServer;
import io.vertx.httpproxy.HttpProxy;
import io.vertx.launcher.application.VertxApplication;

public class Proxy extends VerticleBase {

public static void main(String[] args) {
VertxApplication.main(new String[]{Proxy.class.getName()});
}

@Override
public Future<?> start() {
HttpClient proxyClient = vertx.createHttpClient();

HttpProxy proxy = HttpProxy.reverseProxy(proxyClient);
proxy.origin(7070, "localhost");

HttpServer proxyServer = vertx.createHttpServer();

return proxyServer.requestHandler(proxy).listen(8080);
}
}
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
<module>json-schema-examples</module>
<module>config-examples</module>
<module>health-check-examples</module>
<module>http-proxy-examples</module>
</modules>

<build>
Expand Down

0 comments on commit 3109483

Please sign in to comment.