7 releases (breaking)
Uses old Rust 2015
0.6.1-rc1 | Nov 6, 2022 |
---|---|
0.6.0 | May 27, 2020 |
0.5.0 | Apr 11, 2020 |
0.4.0 | Apr 11, 2020 |
0.1.0 | Dec 8, 2018 |
#640 in HTTP server
395 downloads per month
21KB
263 lines
rust-cgi
Easily create CGIfootnote:[Retro!]footnote:[Common Gateway Interface 1.1, RFC
3875] programmesfootnote:[Yes, I'm spelling it programme, the correct way.] in
Rust based on link:http
types.
:toc:
Installation & Usage
Cargo.toml
:
[code,toml]
[dependencies]
cgi = "0.6"
Use the cgi_main!
macro, with a function that takes a cgi::Request
and returns a
cgi::Response
.
[code,rust]
extern crate cgi;
cgi::cgi_main! { |request: cgi::Request| -> cgi::Response {
cgi::text_response(200, "Hello World")
} }
If your function returns a Result
, you can use cgi_try_main!
:
[code,rust]
extern crate cgi;
cgi::cgi_try_main! { |request: cgi::Request| -> Result<cgi::Response, String> {
let greeting = std::fs::read_to_string("greeting.txt").map_err(|_| "Couldn't open file")?;
Ok(cgi::text_response(200, greeting))
} }
It will parse & extract the CGI environmental variables, and the HTTP request body to create
Request<u8>
, call your function to create a response, and convert your Response
into the
correct format and print to stdout. If this programme is not called as CGI (e.g. missing
required environmental variables), it will panic.
It is also possible to call the cgi::handle
function directly inside your main
function:
[code,rust]
extern crate cgi;
fn main() { cgi::handle(|request: cgi::Request| -> cgi::Response {
cgi::html_response(200, "<html><body><h1>Hello World!</h1></body></html>")
})}
Response Shortcuts
Several shortcuts create shortcuts easily:
cgi:empty_response(status_code)
:: A HTTP Reponse with no body and that HTTP
status code, e.g. return cgi::empty_response(404);
to return a
link:HTTP 404 Not Found.
cgi::html_response(status_code, text)
:: Converts text
to bytes (UTF8) and
sends that as the body with that status_code
and HTML Content-Type
header.
cgi::string_response(status_code, text)
:: Converts text
to bytes (UTF8),
and sends that as the body with that status_code
, e.g. return
cgi::string_response(200, "Hello World!"):: returns a simple plain text response.
cgi::binary_response(status_code, blob):: Sends
blob` with that status code.
Re-exports
http
is re-exported, (as cgi::http
).
cgi::Response
/Request
are http::Response<Vec<u8>>
/Request<Vec<u8>>
.
Running locally
Python provides a simple CGI webserver you can use to run your scripts. The
binaries must be in a cgi-bin
directory, so you'll need to create that
directory and copy your binary into it. Given a project named example
, run
this in your project root directory (i.e. where Cargo.toml
is):
mkdir cgi-bin
cargo build
cp target/debug/example cgi-bin/example
python3 -m http.server --cgi
and then open link:http://localhost:8000/cgi-bin/example[].
See also
Things using this
- 'Suggestions welcome!'
Resources
- link:hyper's http.
- link:
http
API documentation - link:RFC 3875 - The Common Gateway Interface (CGI) v1.1
Why?
CGI is old, and easy to deploy. Just drop a binary in the right place, and Apache (or whatever) will serve it up. Rust is fast, so for simple things, there should be less downsides to spinning up a custom HTTP server.
Copyright
Copyright link:https://www.gnu.org/licenses/agpl-3.0.en.html[GNU Affero GPL v3 (or later)]. See the file link:LICENCE[]
Dependencies
~590KB