git repos / sago_web_git

src/cgi.h

browsing at commit = 55fa1ac0b398c748c7e2421b855a1606790cafc9

raw · blame · history

#pragma once

#include <functional>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

// Parsed CGI header block (the body is streamed separately).
struct CgiResult {
    int status = 200; // from a "Status:" header, or 200 if absent
    std::vector<std::pair<std::string, std::string>> headers;
};

// Forks and execs `argv` with exactly the environment in `env` (each entry
// "KEY=value"). The child's stdin is connected to `input_fd` (or /dev/null when
// input_fd < 0). Its stdout is parsed as a CGI response: once the header block
// up to the first blank line is parsed, `on_headers` is called with it and must
// return the stream to receive the body; the remaining bytes are then streamed
// there. Splitting it this way lets the caller set HTTP status/headers before
// any body is written. Throws std::runtime_error if the child cannot be spawned
// or exits non-zero.
void run_cgi(const std::vector<std::string> &argv,
             const std::vector<std::string> &env, int input_fd,
             const std::function<std::ostream &(const CgiResult &)> &on_headers);