Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/amandasaurus/rust-cgi

Create CGI programmes in Rust with hyper's http types
https://github.com/amandasaurus/rust-cgi

cgi http rust

Last synced: 21 days ago
JSON representation

Create CGI programmes in Rust with hyper's http types

Awesome Lists containing this project

README

        

= 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:https://github.com/hyperium/http[`http` types].

image::https://img.shields.io/crates/v/cgi.svg?style=flat[crates.io released version badge]
image::https://img.shields.io/crates/l/cgi.svg?style=flat[crates.io released licencegpl]

: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 {
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`, 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, "

Hello World!

")
})}
----

== 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:https://en.wikipedia.org/wiki/HTTP_404[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>`/`Request>`.

= 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:https://github.com/hyperium/http[hyper's http].
* link:https://docs.rs/http/0.1.5/http/[`http` API documentation]
* link:https://tools.ietf.org/html/rfc3875[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[]