{"id":13906727,"url":"https://github.com/scottlamb/http-serve","last_synced_at":"2025-04-04T08:04:53.372Z","repository":{"id":18204881,"uuid":"77008067","full_name":"scottlamb/http-serve","owner":"scottlamb","description":"Rust helpers for conditional GET, HEAD, byte range serving, and gzip content encoding for static files and more with hyper and tokio.","archived":false,"fork":false,"pushed_at":"2025-02-15T17:54:23.000Z","size":567,"stargazers_count":34,"open_issues_count":2,"forks_count":9,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-28T07:03:29.299Z","etag":null,"topics":["http","hyper","rust"],"latest_commit_sha":null,"homepage":"https://crates.io/crates/http-serve","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/scottlamb.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-21T02:20:16.000Z","updated_at":"2025-02-15T17:54:27.000Z","dependencies_parsed_at":"2025-01-03T15:10:21.433Z","dependency_job_id":"9f84b7d7-144a-42d8-a24c-23371affb051","html_url":"https://github.com/scottlamb/http-serve","commit_stats":{"total_commits":186,"total_committers":5,"mean_commits":37.2,"dds":"0.16666666666666663","last_synced_commit":"82028dc67cb5e3467ab264eac5ea6206eb9b785d"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fhttp-serve","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fhttp-serve/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fhttp-serve/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scottlamb%2Fhttp-serve/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scottlamb","download_url":"https://codeload.github.com/scottlamb/http-serve/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247138386,"owners_count":20890036,"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":["http","hyper","rust"],"created_at":"2024-08-06T23:01:41.349Z","updated_at":"2025-04-04T08:04:53.357Z","avatar_url":"https://github.com/scottlamb.png","language":"Rust","readme":"# http-serve\n\n[![crates.io](https://img.shields.io/crates/v/http-serve.svg)](https://crates.io/crates/http-serve)\n[![Released API docs](https://docs.rs/http-serve/badge.svg)](https://docs.rs/http-serve/)\n[![CI](https://github.com/scottlamb/http-serve/workflows/CI/badge.svg)](https://github.com/scottlamb/http-serve/actions?query=workflow%3ACI)\n\nRust helpers for serving HTTP GET and HEAD responses with\n[hyper](https://crates.io/crates/hyper) 1.x and\n[tokio](https://crates.io/crates/tokio).\n\nThis crate supplies two ways to respond to HTTP GET and HEAD requests:\n\n*   the `serve` function can be used to serve an `Entity`, a trait representing\n    reusable, byte-rangeable HTTP entities. `Entity` must be able to produce\n    exactly the same data on every call, know its size in advance, and be able\n    to produce portions of the data on demand.\n*   the `streaming_body` function can be used to add a body to an\n    otherwise-complete response.  If a body is needed (on `GET` rather than `HEAD`\n    requests, it returns a `BodyWriter` (which implements `std::io::Writer`).\n    The caller should produce the complete body or call `BodyWriter::abort`,\n    causing the HTTP stream to terminate abruptly.\n\nIt supplies a static file `Entity` implementation and a (currently Unix-only)\nhelper for serving a full directory tree from the local filesystem, including\nautomatically looking for `.gz`-suffixed files when the client advertises\n`Accept-Encoding: gzip`.\n\n## Why two ways?\n\nThey have pros and cons. This table shows some of them:\n\n\u003ctable\u003e\n  \u003ctr\u003e\u003cth\u003e\u003cth\u003e\u003ccode\u003eserve\u003c/code\u003e\u003cth\u003e\u003ccode\u003estreaming_body\u003c/code\u003e\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003eautomatic byte range serving\u003ctd\u003eyes\u003ctd\u003eno [\u003ca href=\"#range\"\u003e1\u003c/a\u003e]\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003ebackpressure\u003ctd\u003eyes\u003ctd\u003eno [\u003ca href=\"#backpressure\"\u003e2\u003c/a\u003e]\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003econditional GET\u003ctd\u003eyes\u003ctd\u003eno [\u003ca href=\"#conditional_get\"\u003e3\u003c/a\u003e]\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003esends first byte before length known\u003ctd\u003eno\u003ctd\u003eyes\u003c/tr\u003e\n  \u003ctr\u003e\u003ctd\u003eautomatic gzip content encoding\u003ctd\u003eno [\u003ca href=\"#gzip\"\u003e4\u003c/a\u003e]\u003ctd\u003eyes\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ca name=\"range\"\u003e\\[1\\]\u003c/a\u003e: `streaming_body` always sends the full body. Byte range serving\nwouldn't make much sense with its interface. The application will generate all the bytes\nevery time anyway, and `http-serve`'s buffering logic would have to be complex\nto handle multiple ranges well.\n\n\u003ca name=\"backpressure\"\u003e\\[2\\]\u003c/a\u003e: `streaming_body` is often appended to while holding\na lock or open database transaction, where backpressure is undesired. It'd be\npossible to add support for \"wait points\" where the caller explicitly wants backpressure. This\nwould make it more suitable for large streams, even infinite streams like\n[Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events).\n\n\u003ca name=\"conditional_get\"\u003e\\[3\\]\u003c/a\u003e: `streaming_body` doesn't yet support\ngenerating etags or honoring conditional GET requests. PRs welcome!\n\n\u003ca name=\"gzip\"\u003e\\[4\\]\u003c/a\u003e: `serve` doesn't automatically apply `Content-Encoding:\ngzip` because the content encoding is a property of the entity you supply. The\nentity's etag, length, and byte range boundaries must match the encoding. You\ncan use the `http_serve::should_gzip` helper to decide between supplying a plain\nor gzipped entity. `serve` could automatically apply the related\n`Transfer-Encoding: gzip` where the browser requests it via `TE: gzip`, but\ncommon browsers have\n[chosen](https://bugs.chromium.org/p/chromium/issues/detail?id=94730) to avoid\nrequesting or handling `Transfer-Encoding`.\n\nSee the [documentation](https://docs.rs/http-serve/) for more.\n\nThere's a built-in `Entity` implementation, `ChunkedReadFile`. It serves\nstatic files from the local filesystem, reading chunks in a separate thread\npool to avoid blocking the tokio reactor thread.\n\nYou're not limited to the built-in entity type(s), though. You could supply\nyour own that do anything you desire:\n\n*   bytes built into the binary via `include_bytes!`.\n*   bytes retrieved from another HTTP server or network filesystem.\n*   memcached-based caching of another entity.\n*   anything else for which it's cheaper to compute the etag, size, and a byte\n    range than the entirety of the data. (See\n    [moonfire-nvr](https://github.com/scottlamb/moonfire-nvr)'s logic for\n    generating `.mp4` files to represent arbitrary time ranges.)\n\n`http_serve::serve` is similar to golang's\n[http.ServeContent](https://golang.org/pkg/net/http/#ServeContent). It was\nextracted from [moonfire-nvr](https://github.com/scottlamb/moonfire-nvr)'s\n`.mp4` file serving.\n\nExamples:\n\n*   Serve a single file:\n    ```\n    $ cargo run --example serve_file /usr/share/dict/words\n    ```\n*   Serve a directory tree:\n    ```\n    $ cargo run --features dir --example serve_dir .\n    ```\n\n## Authors\n\nSee the [AUTHORS](AUTHORS) file for details.\n\n## License\n\nYour choice of MIT or Apache; see [LICENSE-MIT.txt](LICENSE-MIT.txt) or\n[LICENSE-APACHE](LICENSE-APACHE.txt), respectively.\n","funding_links":[],"categories":["HarmonyOS"],"sub_categories":["Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottlamb%2Fhttp-serve","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscottlamb%2Fhttp-serve","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscottlamb%2Fhttp-serve/lists"}