Crate dumb_cgi

source ·
Expand description

dumb_cgi is a library for collecting all the information made available by the web server to a CGI program into a single, easy-to-use struct.

use std::io::Write;
use dumb_cgi::{Request, Query, Body, EmptyResponse};

// This example is wrapped in a main function that returns a
// `std::io::Result<()>` in order to leverage the `?` to cut down
// on some visual noise.

fn main() -> std::io::Result<()> {
    // Gather all request data from the environment and stdin.
    let req = Request::new().unwrap();

    // Instantiate a new response object, and give it a `Content-type` so that
    // the body can be written to.
    let mut response = EmptyResponse::new(200)
        .with_content_type("text/plain");

    // Write info about the environment to the response body.
    write!(&mut response, "Environment Variables:\n")?;
    for (var, value) in req.vars() {
        write!(&mut response, "    {}={}\n", var, value)?;
    }

    // Write info about the request headers to the response body.
    write!(&mut response, "\nExposed HTTP Headers:\n");
    for (header, value) in req.headers() {
        write!(&mut response, "    {}: {}\n", header, value);
    }

    // Write info about the parsed query string to the response body.
    match req.query() {
        Query::None => { write!(&mut response, "\nNo query string.")?; },
        Query::Some(map) => {
            write!(&mut response, "\nQuery String Form Data:\n")?;
            for (name, value) in map.iter() {
                write!(&mut response, "    {}={}\n", name, value)?;
            }
        },
        Query::Err(e) => {
            write!(&mut response, "\nError reading query string: {:?}\n", &e.details)?;
        },
    }

    // Write info about the request body to the response body.
    match req.body() {
        Body::None => { write!(&mut response, "\nNo body.\n")?; },
        Body::Some(bytes) => {
            write!(&mut response, "\n{} bytes of body.\n", bytes.len())?;
        },
        Body::Multipart(parts) => {
            write!(&mut response, "\nMultipart body with {} parts:\n", parts.len())?;
            for (n, part) in parts.iter().enumerate() {
                write!(&mut response, "    Part {}:\n", &n)?;
                for (header, value) in part.headers.iter() {
                    write!(&mut response, "        {}: {}\n", header, value)?;
                }
                write!(&mut response, "        {} bytes of body.\n", part.body.len())?;
            }
        },
        Body::Err(e) => {
            write!(&mut response, "\nError reading body: {:?}\n", &e.details)?;
        },
    }

    // Finally, send the response.
    response.respond()
}

The emphases are lack of dependencies and simplicity (both in use and in maintenance). In pursuit of these, some trade-offs have been made.

  • Some CGI libraries use high-performance or fault-tolerant parsing techniques (like regular expressions). dumb_cgi is pretty straight-forward and doesn’t go out of its way to deal with non- or almost-compliant requests, or even certain strictly-compliant cases that are unlikely and awkward to support.

  • Some libraries are fast and memory-efficient by avoiding allocation; they keep the body of the request around and only hand out references to parts of it. dumb_cgi copies and owns the parts of the request (and the environment) that it needs. This is simpler to both use and maintain.

  • dumb_cgi lossily converts everything except request bodies (and the “body” portions of multipart/form-data body parts) into UTF-8. This means not supporting certain strictly-compliant requests and possibly not correctly receiving environment variables on some systems, but is easier to both use and maintain. (If you do need to deal with non-UTF-8 environment variables or header values, dumb_cgi is too dumb for your use case.)

  • dumb_cgi’s target is server-side CGI programs; it supports reading requests (not writing them), and writing responses (not reading them).

Features

dumb_cgi is dependency-free by default. Enabling the log feature pulls in the log and simplelog crates, which are really only for debugging dumb_cgi during its development. Consumers of this crate shouldn’t need this feature.

Structs

  • A response with no body.
  • Errors returned by this libraray.
  • A response with a body, instantiated by calling .with_content_type() on an EmptyResponse.
  • Struct holding a single part of a multipart/formdata body.
  • Struct holding details about your CGI environment and the request that has been made to your program.
  • An iterator over a HashMap<String, String> that yields (&'str, &'str) tuples.

Enums

  • Type of body detected in the request.
  • Type of query string detected in the request.