An http file server written in rust using tokio and
hyper.
Includes support for:
- http 1.1 / 2
- boxed responses (send large files frame by frame)
headrequestsrangerequests- encoded requests
Bash the following commands:
git clone https://github.com/herebythere/file_server
cargo install --path file_server/file_serverBash the following command:
file_serverThis will start file_server with using the cwd as a base directory.
Now files can be requested from the cwd at localhost:3000:
curl localhost:3000The following command-line arguments are valid paramters:
file_server /
--host=0.0.0.0 /
--port=4000 /
--directory=../another_directory /
--content-encodings=gzip,deflate,br,zstdWhen a request has an accept-encoding header, file_server will return a corresponding zip-ed version of file if available.
So if a request has the following header:
Accept-Encoding: gzip;
And the target file has a correspponding gziped file:
index.html # source file
index.html.gz # gzipped fileFile_server will send the encoded file, if available. Otherwise, it serves the source file.
File_server does not encode or zip files ever.
This program serves static files. Just zip them up now to save memory resources.
File_server supports single range requests.
Bash the following command:
curl -v -r 0-6 localhost:3000And the first 6 bytes of index.html will be delivered.
Multipart ranges are not currently supported.
They're a little more strenuous, tend to hog memory, and are difficult to deliver efficiently. Sorry.
Valid range sytanxes:
<unit>=<range-start>-
<unit>=<range-start>-<range-end>
<unit>=-<suffix-length>
Details for a particular file or directory can be requested with some url params:
http://127.0.0.1:3000/?serialize_as=json
The following json schema will be retured:
{
"details": "<details>",
"entries": [
"<details>",
"..."
]
}Which could produce a json object similar to the following:
{
"details": {
"is_file": false,
"is_dir": true,
"is_symlink": false,
"file_name": "demo",
"url_path": "/demo",
"size": 128,
"created_at": "1788035132686",
"accessed_at": "1792381141727",
"modified_at": "1792381141619"
},
"entries": [
{
"is_file": true,
"is_dir": false,
"is_symlink": false,
"file_name": "index.html.zst",
"url_path": "/demo/index.html.zst",
"size": "304",
"created_at": "1788035132686",
"accessed_at": "1788035156555",
"modified_at": "1788035132686"
},
{
"is_file": true,
"is_dir": false,
"is_symlink": false,
"file_name": "index.html",
"url_path": "/demo/index.html",
"size": "460",
"created_at": "1788035132686",
"accessed_at": "1788035156555",
"modified_at": "1788035132686"
}
]
}Timestamps are u128 integers in rust. File sizes are u64 integers. Since neither of those
types can actually parse in Javascript-land, numbers in the schema above are sent as strings.
Json structs structs can be swapped for a more rust-specific FileDetails struct:
use response::{EntryDetailsJson, FileDetailsJson, FileDetails};
let file_details_json: FileDetailsJson = ...
let file_details: Results<FileDetails, ParseIntError> = file_details_json::as_file_details();file_server is released under the BSD 3-Clause License.