Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP Proxy examples #471

Merged
merged 1 commit into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading