Java 实现
package com.onemsg.proxy;
import io.vertx.core.AbstractVerticle;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Future;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientRequest;
import io.vertx.core.http.HttpClientResponse;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerResponse;
import io.vertx.core.http.RequestOptions;
import io.vertx.ext.web.Router;
public class ProxyVerticle extends AbstractVerticle{
static final String LOCATION = "https://github.com";
static final String HOST = "github.com";
private HttpClient client;
@Override
public void start(Promise<Void> startPromise) throws Exception {
client = vertx.createHttpClient();
HttpServer server = vertx.createHttpServer();
Router router = Router.router(vertx);
router.route("/*").handler(ctx -> {
String url = LOCATION + ctx.request().uri();
RequestOptions requestOptions = new RequestOptions()
.setMethod(ctx.request().method())
.setAbsoluteURI(url)
.setHeaders(ctx.request().headers().set("Host", HOST) );
forward(requestOptions, ctx.getBody())
.onSuccess(clientResponse -> {
HttpServerResponse serverResponse = ctx.response().setStatusCode(clientResponse.statusCode());
serverResponse.headers().addAll(clientResponse.headers());
clientResponse.body().onSuccess(serverResponse::end);
});
});
server.requestHandler(router)
.listen(9070)
.onComplete(http -> {
startPromise.complete();
System.out.println("HTTP server started on port 9070");
}).onFailure(startPromise::fail);
}
Future<HttpClientResponse> forward(RequestOptions options, Buffer body){
return client.request(options)
.onSuccess(clientRequest -> {
if(body != null){
clientRequest.write(body);
}
clientRequest.end();
}).flatMap(HttpClientRequest::response);
}
public static void main(String[] args) {
Vertx.vertx().deployVerticle(ProxyVerticle.class, new DeploymentOptions());
}
}

NodeJS 实现
const https = require('https');
const http = require('http');
const LOCALTION = 'developer.mozilla.org';
const server = http.createServer((req, res) => {
const options = {
hostname: LOCALTION,
port: 443,
path: req.url,
method: req.method,
headers: req.headers
};
options.headers['host'] = LOCALTION
const proxyReq = https.request(options, proxyRes => {
const body = []
proxyRes.on("data", data => {
body.push(data)
})
proxyRes.on("end", () => {
const data = Buffer.concat(body)
res.statusCode = proxyRes.statusCode
for (const headerName in proxyRes.headers) {
const headerValue = proxyRes.headers[headerName];
if(headerValue == null ){
continue
}
res.setHeader(headerName, headerValue)
}
res.setHeader("server", "PROXY SERVER")
res.end(data)
})
})
const body = []
req.on("error", error => {
console.log(error)
})
req.on("data", data => {
body.push(data)
})
req.on("end", () => {
const data = Buffer.concat(body)
proxyReq.end(data)
})
});
const hostname = '127.0.0.1';
const port = 3000;
server.listen(port, hostname, () => {
console.log(`Proxy Server running at http://${hostname}:${port}/`);
});
server.on("error", error => {
console.log(error)
})
Python 实现
"""
API Gateway for frontend
@autor: onemsg
@since: 2022-03
"""
from email import header
from typing import Tuple
from aiohttp import ClientResponse, web
import aiohttp
import logging
log = logging.getLogger("API-Gateway-Server")
SERVICE_STORE = {
"app-1": ("127.0.0.1", 9001),
"app-2": ("127.0.0.1", 9002),
"app-3": ("127.0.0.1", 9003),
}
DEFAULT_SERVICE_NAME_HEADER = "X-POLARIS-NAME"
def find_service(service_name: str) -> Tuple[str, int]:
"""
服务发现
"""
return SERVICE_STORE.get(service_name, (None, None))
async def proxy_handler(request: web.Request) -> web.Response:
"""
服务代理
"""
if DEFAULT_SERVICE_NAME_HEADER not in request.headers:
return web.Response(status=400, text="没有指定具体服务")
service_name = request.headers.getone(DEFAULT_SERVICE_NAME_HEADER)
host, port = find_service(service_name)
if host == None:
return web.Response(status=404, text="没有找到具体服务 [{}]".format(service_name))
return await forward(request, host, port)
async def forward(request: web.Request, host: str, port: int) -> web.Response:
"""
请求转发
"""
target_url = f"http://{host}:{port}" + request.rel_url.path
async with aiohttp.ClientSession() as session:
async with session.request(request.method, target_url, headers=request.headers, data=await request.read()) as origin_response:
return web.Response(
status=origin_response.status,
headers=origin_response.headers,
body=await origin_response.read() )
if __name__ == "__main__":
app = web.Application()
app.add_routes([
web.route("*", "/{path:.*?}", proxy_handler)
])
web.run_app(app, port=9870)