{"id":20721509,"url":"https://github.com/cleancut/examine","last_synced_at":"2025-10-14T19:32:42.068Z","repository":{"id":187909668,"uuid":"677792841","full_name":"CleanCut/examine","owner":"CleanCut","description":"Practice creating grpc services and clients with buf.build, Rust, and tonic","archived":false,"fork":false,"pushed_at":"2023-08-12T20:00:28.000Z","size":30,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-14T19:32:27.715Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CleanCut.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":"2023-08-12T16:44:01.000Z","updated_at":"2025-03-16T20:40:22.000Z","dependencies_parsed_at":null,"dependency_job_id":"df69ced3-d909-4a78-8ad6-00c88d0fd3ea","html_url":"https://github.com/CleanCut/examine","commit_stats":null,"previous_names":["cleancut/examine"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/CleanCut/examine","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleanCut%2Fexamine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleanCut%2Fexamine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleanCut%2Fexamine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleanCut%2Fexamine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CleanCut","download_url":"https://codeload.github.com/CleanCut/examine/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CleanCut%2Fexamine/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279020649,"owners_count":26086898,"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","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-17T03:28:10.466Z","updated_at":"2025-10-14T19:32:42.052Z","avatar_url":"https://github.com/CleanCut.png","language":"Rust","readme":"# \"Examine\" Client \u0026 Service\n\nPractice creating grpc services and clients with buf.build, Rust, and tonic.\n\n# The Task\n\n\u003e You are implementing an API which must analyze an HTTP user agent and make a decision as to whether to block or allow it. If the user agent header is from a Safari browser, it should return a decision to block the request. If it is from a Firefox browser, it should allow the request.\n\u003e \n\u003e Create a gRPC client and server in Rust or Go which implements a single endpoint that receives the user agent string, analyzes it, and returns the result. Create a terminal CLI which uses the client to call the API. Include appropriate tests and documentation.\n\n# Built-in Tests\n\nTo run the built-in unit, integration, and doc tests, do:\n\n```shell\ncargo test\n```\n\n- Doc tests are in [`src/service.rs`](https://github.com/CleanCut/examine/blob/main/src/service.rs#L14-L26)\n- Unit tests are (also) in [`src/service.rs`](https://github.com/CleanCut/examine/blob/main/src/service.rs#L66-L88)\n- Integration tests are in [`tests/integration.rs`](https://github.com/CleanCut/examine/blob/main/tests/integration.rs)\n\n# Protobuf Definitions\n\nThe (handwritten) protobuf file is in `proto/examine/v1/examine.proto`. `buf.build` was used to\ngenerate the code.\n\n- [Generated documentation for the `ExamineService` is hosted on a public `buf.build` repo.](https://buf.build/nathanstocks/examine)\n\n# Rust Library Documentation\n\n_Most_ of the documentation for this project is right here in this readme, but there is also some Rust API documentation available. View it by running the command locally:\n\n```shell\ncargo doc --no-deps --open\n```\n\n# Server\n\nThe code for the server binary is in [`src/bin/server.rs`](https://github.com/CleanCut/examine/blob/main/src/bin/server.rs), while the logic for the service it runs\nis in the library file [`src/service.rs`](https://github.com/CleanCut/examine/blob/main/src/service.rs).\n\n### Running the server...\n\n```shell\ncargo run -r --bin server\n```\n\nOR...\n\n```shell\ncargo build -r\ntarget/release/server\n```\n\n### Testing the server...\n\nTo test the server in isolation using `grpcurl`, first run the server, and then run commands like the one below. (Replace `USER-AGENT-STRING` with the actual User-Agent value.)\n\n```shell\ngrpcurl -plaintext -import-path ./proto -proto proto/examine/v1/examine.proto -d '{\"user_agent\": \"USER-AGENT-STRING\"}' 127.0.0.1:8080 examine.v1.ExamineService/Examine\n```\n\n### Safari User-Agent Example\n\n```shell\ngrpcurl -plaintext -import-path ./proto -proto proto/examine/v1/examine.proto -d '{\"user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15\"}' 127.0.0.1:8080 examine.v1.ExamineService/Examine\n```\n\n...which outputs:\n\n```json\n{\n  \"action\": \"ACTION_BLOCK\"\n}\n```\n\n### Firefox User-Agent Example\n\n```shell\ngrpcurl -plaintext -import-path ./proto -proto proto/examine/v1/examine.proto -d '{\"user_agent\": \"Mozilla/5.0 (Macintosh; Intel Mac OS X 13.5; rv:109.0) Gecko/20100101 Firefox/116.0\"}' 127.0.0.1:8080 examine.v1.ExamineService/Examine\n```\n\n...which outputs\n\n```json\n{\n  \"action\": \"ACTION_ALLOW\"\n}\n```\n\n# Client\n\nThe client reads in User-Agent string(s) and then outputs either `Allow` or `Block` for each input value, one per line.\n\n### Running the client\n\nWhile you can run the client through cargo, it's a bit...verbose. (`ARGUMENT` is the User-Agent string(s), separated by newlines)\n\n```shell\ncargo run -r --bin client -- ARGUMENT\n```\n\nIt's probably easier to run the client by calling the binary directly:\n\n```shell\ncargo build -r\ntarget/release/client ARGUMENT\n```\n\n### Client Usage\n\n\u003e Note: First run the server using the instructions [above](#server)!\n\nFor the client help output, pass in `-h`:\n\n```shell\ntarget/release/client -h\n```\n\nWhich should output something like:\n\n```text\n`client` checks user agent string(s)and emits whether to Allow or Block for each one\n\nUsage: client \u003cUSER_AGENT\u003e\n\nArguments:\n  \u003cUSER_AGENT\u003e  User-Agent string of the browser. Use `-` to indicate reading from stdin instead\n\nOptions:\n  -h, --help     Print help\n  -V, --version  Print version\n```\n\n### Stdin\n\nIf you would rather pass your User-Agent string(s) via `stdin`, use `-` as the argument:\n\n```shell\n# One argument via pipe\necho \"some user agent\" | target/release/client -\n\n# Multiple arguments via pipe\necho \"user agent string 1\\nuser agent string 2\" | target/release/client -\n\n# Any number of arguments via file\ntarget/release/client - \u003c somefile.txt\n```\n\n### Safari User-Agent Example (via positional argument)\n\n```shell\ntarget/release/client \"Mozilla/5.0 (Macintosh; Intel Mac OS X 13_5) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.5 Safari/605.1.15\"\n```\n\n...which outputs:\n\n```text\nBlock\n```\n\n### Firefox User-Agent Example (via stdin)\n\n```shell\necho \"Mozilla/5.0 (Macintosh; Intel Mac OS X 13.5; rv:109.0) Gecko/20100101 Firefox/116.0\" | target/release/client -\n```\n\n...which outputs:\n\n```text\nAllow\n```\n\n### Multiple User-Agents via a file\n\n\u003e This file is present in the repository if you would like to use it.\n\n```shell\ntarget/release/client - \u003c tests/user_agents.txt\n```\n\n```text\nBlock\nAllow\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcleancut%2Fexamine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcleancut%2Fexamine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcleancut%2Fexamine/lists"}