{"id":13825835,"url":"https://github.com/felipenoris/hyper-reverse-proxy","last_synced_at":"2025-04-14T00:51:50.542Z","repository":{"id":38019314,"uuid":"97291418","full_name":"felipenoris/hyper-reverse-proxy","owner":"felipenoris","description":"A simple reverse proxy for use with Hyper and Tokio","archived":false,"fork":false,"pushed_at":"2025-02-20T16:28:24.000Z","size":64,"stargazers_count":190,"open_issues_count":14,"forks_count":65,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-06T10:40:45.745Z","etag":null,"topics":["async","http","http-proxy","hyper","reverse-proxy","rust","tokio"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felipenoris.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-15T04:11:35.000Z","updated_at":"2025-03-27T18:06:06.000Z","dependencies_parsed_at":"2024-01-07T22:48:53.398Z","dependency_job_id":"42504b69-a57e-440c-9694-98fb17540cf3","html_url":"https://github.com/felipenoris/hyper-reverse-proxy","commit_stats":{"total_commits":68,"total_committers":7,"mean_commits":9.714285714285714,"dds":0.5588235294117647,"last_synced_commit":"e73a76600ce9e51e962de5266b03be596e6c1d50"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipenoris%2Fhyper-reverse-proxy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipenoris%2Fhyper-reverse-proxy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipenoris%2Fhyper-reverse-proxy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felipenoris%2Fhyper-reverse-proxy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felipenoris","download_url":"https://codeload.github.com/felipenoris/hyper-reverse-proxy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248804773,"owners_count":21164131,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","http","http-proxy","hyper","reverse-proxy","rust","tokio"],"created_at":"2024-08-04T09:01:27.787Z","updated_at":"2025-04-14T00:51:50.524Z","avatar_url":"https://github.com/felipenoris.png","language":"Rust","funding_links":[],"categories":["\u003ca id=\"01e6651181d405ecdcd92a452989e7e0\"\u003e\u003c/a\u003e工具"],"sub_categories":["\u003ca id=\"e9f97504fbd14c8bb4154bd0680e9e62\"\u003e\u003c/a\u003e反向代理"],"readme":"\n# hyper-reverse-proxy\n\n[![License][license-img]](LICENSE)\n[![CI][ci-img]][ci-url]\n[![docs][docs-img]][docs-url]\n[![version][version-img]][version-url]\n\n[license-img]: https://img.shields.io/crates/l/hyper-reverse-proxy.svg\n[ci-img]: https://github.com/felipenoris/hyper-reverse-proxy/workflows/CI/badge.svg\n[ci-url]: https://github.com/felipenoris/hyper-reverse-proxy/actions/workflows/main.yml\n[docs-img]: https://docs.rs/hyper-reverse-proxy/badge.svg\n[docs-url]: https://docs.rs/hyper-reverse-proxy\n[version-img]: https://img.shields.io/crates/v/hyper-reverse-proxy.svg\n[version-url]: https://crates.io/crates/hyper-reverse-proxy\n\nA simple reverse proxy, to be used with [Hyper].\n\nThe implementation ensures that [Hop-by-hop headers] are stripped correctly in both directions,\nand adds the client's IP address to a comma-space-separated list of forwarding addresses in the\n`X-Forwarded-For` header.\n\nThe implementation is based on Go's [`httputil.ReverseProxy`].\n\n[Hyper]: http://hyper.rs/\n[Hop-by-hop headers]: http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html\n[`httputil.ReverseProxy`]: https://golang.org/pkg/net/http/httputil/#ReverseProxy\n\n# Example\n\nAdd these dependencies to your `Cargo.toml` file.\n\n```toml\n[dependencies]\nhyper-reverse-proxy = \"?\"\nhyper = { version = \"?\", features = [\"full\"] }\ntokio = { version = \"?\", features = [\"full\"] }\nlazy_static = \"?\"\nhyper-trust-dns = { version = \"?\", features = [\n  \"rustls-http2\",\n  \"dnssec-ring\",\n  \"dns-over-https-rustls\",\n  \"rustls-webpki\",\n  \"https-only\"\n] }\n```\n\nThe following example will set up a reverse proxy listening on `127.0.0.1:13900`,\nand will proxy these calls:\n\n* `\"/target/first\"` will be proxied to `http://127.0.0.1:13901`\n\n* `\"/target/second\"` will be proxied to `http://127.0.0.1:13902`\n\n* All other URLs will be handled by `debug_request` function, that will display request information.\n\n```rust\nuse hyper::server::conn::AddrStream;\nuse hyper::service::{make_service_fn, service_fn};\nuse hyper::{Body, Request, Response, Server, StatusCode};\nuse hyper_reverse_proxy::ReverseProxy;\nuse hyper_trust_dns::{RustlsHttpsConnector, TrustDnsResolver};\nuse std::net::IpAddr;\nuse std::{convert::Infallible, net::SocketAddr};\n\nlazy_static::lazy_static! {\n    static ref  PROXY_CLIENT: ReverseProxy\u003cRustlsHttpsConnector\u003e = {\n        ReverseProxy::new(\n            hyper::Client::builder().build::\u003c_, hyper::Body\u003e(TrustDnsResolver::default().into_rustls_webpki_https_connector()),\n        )\n    };\n}\n\nfn debug_request(req: \u0026Request\u003cBody\u003e) -\u003e Result\u003cResponse\u003cBody\u003e, Infallible\u003e {\n    let body_str = format!(\"{:?}\", req);\n    Ok(Response::new(Body::from(body_str)))\n}\n\nasync fn handle(client_ip: IpAddr, req: Request\u003cBody\u003e) -\u003e Result\u003cResponse\u003cBody\u003e, Infallible\u003e {\n    if req.uri().path().starts_with(\"/target/first\") {\n        match PROXY_CLIENT.call(client_ip, \"http://127.0.0.1:13901\", req)\n            .await\n        {\n            Ok(response) =\u003e {\n                Ok(response)\n            },\n            Err(_error) =\u003e {\n                Ok(Response::builder()\n                .status(StatusCode::INTERNAL_SERVER_ERROR)\n                .body(Body::empty())\n                .unwrap())},\n        }\n    } else if req.uri().path().starts_with(\"/target/second\") {\n        match PROXY_CLIENT.call(client_ip, \"http://127.0.0.1:13902\", req)\n            .await\n        {\n            Ok(response) =\u003e Ok(response),\n            Err(_error) =\u003e Ok(Response::builder()\n                .status(StatusCode::INTERNAL_SERVER_ERROR)\n                .body(Body::empty())\n                .unwrap()),\n        }\n    } else {\n        debug_request(\u0026req)\n    }\n}\n\n#[tokio::main]\nasync fn main() {\n    let bind_addr = \"127.0.0.1:8000\";\n    let addr: SocketAddr = bind_addr.parse().expect(\"Could not parse ip:port.\");\n\n    let make_svc = make_service_fn(|conn: \u0026AddrStream| {\n        let remote_addr = conn.remote_addr().ip();\n        async move { Ok::\u003c_, Infallible\u003e(service_fn(move |req| handle(remote_addr, req))) }\n    });\n\n    let server = Server::bind(\u0026addr).serve(make_svc);\n\n    println!(\"Running server on {:?}\", addr);\n\n    if let Err(e) = server.await {\n        eprintln!(\"server error: {}\", e);\n    }\n}\n```\n\n### A word about Security\n\nHandling outgoing requests can be a security nightmare. This crate does not control the client for the outgoing requests, as it needs to be supplied to the proxy call. The following chapters may give you an overview on how you can secure your client using the `hyper-trust-dns` crate.\n\n\u003e You can see them being used in the example. \n\n#### HTTPS\n\nYou should use a secure transport in order to know who you are talking to and so you can trust the connection. By default `hyper-trust-dns` enables the feature flag `https-only` which will panic if you supply a transport scheme which isn't `https`. It is a healthy default as it's not only you needing to trust the source but also everyone else seeing the content on unsecure connections.\n\n\u003e ATTENTION: if you are running on a host with added certificates in your cert store, make sure to audit them in a interval, so neither old certificates nor malicious certificates are considered as valid by your client.\n\n#### TLS 1.2\n\nBy default `tls 1.2` is disabled in favor of `tls 1.3`, because many parts of `tls 1.2` can be considered as attach friendly. As not yet all services support it `tls 1.2` can be enabled via the `rustls-tls-12` feature.\n\n\u003e ATTENTION: make sure to audit the services you connect to on an interval\n\n#### DNSSEC\n\nAs dns queries and entries aren't \"trustworthy\" by default from a security standpoint. `DNSSEC` adds a new cryptographic layer for verification. To enable it use the `dnssec-ring` feature.\n\n#### HTTP/2\n\nBy default only rustlss `http1` feature is enabled for dns queries. While `http/3` might be just around the corner. `http/2` support can be enabled using the `rustls-http2` feature.\n\n#### DoT \u0026 DoH\n\nDoT and DoH provide you with a secure transport between you and your dns.\n\nBy default none of them are enabled. If you would like to enabled them, you can do so using the features `doh` and `dot`.\n\nRecommendations:\n - If you need to monitor network activities in relation to accessed ports, use dot with the `dns-over-rustls` feature flag\n - If you are out in the wild and have no need to monitor based on ports, doh with the `dns-over-https-rustls` feature flag as it will blend in with other `https` traffic\n\nIt is highly recommended to use one of them.\n\n\u003e Currently only includes dns queries as `esni` or `ech` is still in draft by the `ietf`","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelipenoris%2Fhyper-reverse-proxy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelipenoris%2Fhyper-reverse-proxy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelipenoris%2Fhyper-reverse-proxy/lists"}