3 releases
0.1.2 | Mar 7, 2023 |
---|---|
0.1.1 | Dec 27, 2022 |
0.1.0 | Dec 27, 2022 |
#387 in HTTP server
51 downloads per month
41KB
933 lines
reverse-proxy-service
is tower's Service
s that perform reverse proxy.
These Service
s are implemented to be used in axum, but they can be used in a more general situation.
See the documentation.
lib.rs
:
reverse-proxy-service
is tower Service
s that performs "reverse
proxy" with various rewriting rules.
Internally these services use [hyper::Client
] to send an incoming request to the another
server. The connector
for a client can be
HttpConnector
, HttpsConnector
,
or any ones whichever you want.
Examples
There are two types of services, [OneshotService
] and [ReusedService
]. The
[OneshotService
] owns the Client
, while the [ReusedService
] shares the Client
via Arc
.
General usage
# async fn run_test() {
use reverse_proxy_service::ReusedServiceBuilder;
use reverse_proxy_service::{ReplaceAll, ReplaceN};
use hyper::body::Body;
use http::Request;
use tower_service::Service as _;
let svc_builder = reverse_proxy_service::builder_http("example.com:1234").unwrap();
let req1 = Request::builder()
.method("GET")
.uri("https://myserver.com/foo/bar/foo")
.body(Body::empty())
.unwrap();
// Clones Arc<Client>
let mut svc1 = svc_builder.build(ReplaceAll("foo", "baz"));
// http://example.com:1234/baz/bar/baz
let _res = svc1.call(req1).await.unwrap();
let req2 = Request::builder()
.method("POST")
.uri("https://myserver.com/foo/bar/foo")
.header("Content-Type", "application/x-www-form-urlencoded")
.body(Body::from("key=value"))
.unwrap();
let mut svc2 = svc_builder.build(ReplaceN("foo", "baz", 1));
// http://example.com:1234/baz/bar/foo
let _res = svc2.call(req2).await.unwrap();
# }
In this example, the svc1
and svc2
shares the same Client
, holding the Arc<Client>
s
inside them.
For more information of rewriting rules (ReplaceAll
, ReplaceN
etc.), see the
documentations of [rewrite
].
With axum
use reverse_proxy_service::ReusedServiceBuilder;
use reverse_proxy_service::{TrimPrefix, AppendSuffix, Static};
use axum::Router;
#[tokio::main]
async fn main() {
let host1 = reverse_proxy_service::builder_http("example.com").unwrap();
let host2 = reverse_proxy_service::builder_http("example.net:1234").unwrap();
let app = Router::new()
.route_service("/healthcheck", host1.build(Static("/")))
.route_service("/users/*path", host1.build(TrimPrefix("/users")))
.route_service("/posts", host2.build(AppendSuffix("/")));
axum::Server::bind(&"0.0.0.0:3000".parse().unwrap())
.serve(app.into_make_service())
.await
.unwrap();
}
Return Types
The return type (Future::Output
) of [ReusedService
] and
[OneshotService
] is Result<Result<Response, Error>, Infallible>
. This is because axum's
Router
accepts only such Service
s.
The [Error
] type implements IntoResponse
if you enable the
axum
feature.
It returns an empty body, with the status code INTERNAL_SERVER_ERROR
. The description of this
error will be logged out at error level in the
into_response()
method.
Features
http1
: default onhttp2
: default offhttps
: default offaxum
: default off
You must turn on either http1
or http2
. You cannot use the services if, for example, only
the https
feature is on.
Dependencies
~5–12MB
~221K SLoC