{"id":15649629,"url":"https://github.com/klausi/rustnish","last_synced_at":"2025-04-30T16:28:04.747Z","repository":{"id":138159298,"uuid":"75544035","full_name":"klausi/rustnish","owner":"klausi","description":"Experimenting with Rustlang by writing a reverse proxy","archived":false,"fork":false,"pushed_at":"2019-11-17T13:14:54.000Z","size":382,"stargazers_count":39,"open_issues_count":1,"forks_count":8,"subscribers_count":5,"default_branch":"goal-11","last_synced_at":"2025-03-30T17:51:14.249Z","etag":null,"topics":["rust"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/klausi.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":"2016-12-04T14:55:39.000Z","updated_at":"2025-03-13T02:51:54.000Z","dependencies_parsed_at":null,"dependency_job_id":"2f4d6c40-fd49-4cd4-b304-bd98398cd562","html_url":"https://github.com/klausi/rustnish","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klausi%2Frustnish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klausi%2Frustnish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klausi%2Frustnish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/klausi%2Frustnish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/klausi","download_url":"https://codeload.github.com/klausi/rustnish/tar.gz/refs/heads/goal-11","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251741727,"owners_count":21636308,"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":["rust"],"created_at":"2024-10-03T12:30:33.774Z","updated_at":"2025-04-30T16:28:04.609Z","avatar_url":"https://github.com/klausi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Rustnish\n\n[![Build Status](https://travis-ci.org/klausi/rustnish.svg?branch=goal-05)](https://travis-ci.org/klausi/rustnish)\n\nExperimental project to learn Rust. A reverse proxy.\n\nhttps://klausi.github.io/rustnish/\n\n## Goal 1: Just pipe HTTP requests through\n\nCompleted: yes\n\nA webserver like Apache is listening on port 80. Write a reverse proxy service\nthat does nothing but forwarding HTTP requests to port 80. The service must\nlisten on port 9090. The service must not modify the HTTP response in any way.\n\n## Goal 2: One integration test\n\nCompleted: yes\n\nWrite an integration test that confirms that the reverse proxy is working as\nexpected. The test should issue a real HTTP request and check that passing\nthrough upstream responses works. Refactor the code to accept arbitrary port\nnumbers so that the tests can simulate a real backend without requiring root\naccess to bind on port 80.\n\n## Goal 3: Convert Hyper server to Tokio\n\nCompleted: yes\n\nA new version of the [Hyper library](https://hyper.rs/) has been released which\nis based on the [Tokio library](https://tokio.rs/). Convert the existing code to\nuse that new version and provide one integration test case.\n\n## Goal 4: Full integration tests\n\nCompleted: yes\n\nExpand the integration tests to confirm that the reverse proxy is working as\nexpected. Add tests with broken HTTP requests to cover error handling of the\nreverse proxy. All ```unwrap()``` calls in none test code should be removed and\ncovered by proper error handling.\n\n## Goal 5: Continuous integration testing with Travis CI\n\nCompleted: yes\n\nEnable [Travis CI](http://travis-ci.org/) so that the automated tests are run\nafter every Git push to the Rustnish repository. Enable\n[Clippy](https://github.com/rust-lang-nursery/rust-clippy) that also checks for\nRust best practices.\n\n## Goal 6: Add HTTP headers to requests/responses\n\nCompleted: yes\n\nAdd the following HTTP headers to requests/responses passed through Rustnish:\n\nHeaders for requests forwarded upstream:\n\n* `X-Forwarded-For`: the originating IP address of the client connecting to the\n  proxy. Append IP address if already set.\n* `X-Forwarded-Port`: the originating port of the HTTP request (example: 443).\n  Append port if already set.\n\nHeaders for responses returned downstream:\n\n* `Via`: a code name for the Rustnish proxy, with the value rustnish-0.0.1.\n  Append if already set.\n* `Server`: will be added to the response (\"rustnish\") if the upstream server\n  didn't add it first.\n\n## Goal 7: Add integration test that watches for memory leaks\n\nCompleted: no, because impossible\n\nAdd an integration test that ensures that the proxy server is not leaking memory\n(growing RAM usage without shrinking again). Use /proc information to compare\nmemory usage of the current process before and after the test.\n\n**Update**: The test case was not stable enough, it had random test fails and\nhad to be removed. Watching and asserting /proc memory information is not\nreliable.\n\n## Goal 8: Make Tokio/Hyper server resilient\n\nCompleted: partially\n\nThere is a [known flaw](https://github.com/hyperium/hyper/issues/1358) in the\nTokio/Hyper libraries that stops server execution under high load. Implement a\nworkaround to make the proxy more resilient. Ensure that the server does not\nstop under such an attack and still delivers valid responses after the attack.\n\n**Update**: The test case was not stable enough, it had random test fails and\nhad to be removed. Simulating an attack with millions of requests was not\nreliable and made different parts of the test case fail.\n\n## Goal 9: Benchmark against Varnish\n\nCompleted: yes\n\nWrite benchmark code that compares runtime performance of Rustnish against\n[Varnish](https://varnish-cache.org/). Use `cargo bench` to execute the benchmarks.\n\n## Goal 10: Cache 20 upstream responses\n\nCompleted: yes\n\nCreate an in-memory store that caches GET HTTP responses for anonymous users.\n* A response is considered cachable if the Cache-Control HTTP header contains\n\"public\" and a \"max-age\" value.\n* A request is considered anonymous if the Cookie HTTP header does not contain a key that starts with \"SESS\".\n* The cache key is the full URL path (including query parameters).\n* Cache entries should be kept for 1 minute.\n* A maximum of 20 cache entries should be used.\n\n\n## Goal 11: Build a memory constrained cache\n\nCompleted: no\n\nImprove the in-memory store of cached responses. Make the cache be limited by\nmemory size and not by number of cache entries. Use a default of 256MB allowed\ncache memory size.\n\n\n## Possible future goals\n\n* Add HTTP Age header\n* Read proxy config from config file\n* Read proxy config from Varnish syntax config file\n* Support Vary HTTP header in responses\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklausi%2Frustnish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fklausi%2Frustnish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fklausi%2Frustnish/lists"}