3 Module N_HTTP_RESP
gullradriel edited this page 2026-11-01 16:37:14 +01:00

HTTP RESPONSE: validated headers, body, framing, writing

Structures

Name
struct N_HTTP_RESP
a response under construction (fields are private, use the functions)

Types

Name
typedef ssize_t(*)(void *ctx, const void *buf, size_t len) n_http_write_fn
a write function: write up to len bytes, return how many were written (at least 1) or -1 on a fatal error; partial writes are retried
typedef int(*)(void *user, N_HTTP_STREAM *out) n_http_stream_fn
a streamed body's producer: write the body with n_http_stream_write(), return TRUE when it is complete, FALSE to cut it short (the connection then closes)
enum N_HTTP_RANGE { N_HTTP_RANGE_UNSATISFIABLE = 2, N_HTTP_RANGE_OK = 1, N_HTTP_RANGE_NONE = 0}
result of n_http_parse_range()

Functions

Name
int n_http_stream_write(N_HTTP_STREAM * s, const void * data, size_t len)
write a piece of a streamed body (one chunk for HTTP/1.1)
const char * n_http_status_reason(int status)
reason phrase of a status code ("Not Found"); a generic class phrase for an unlisted code, "" outside 100..599
int n_http_response_write_ex(const N_HTTP_RESP * r, n_http_write_fn fn, void * ctx, void(*)(void *ctx) before_piece)
n_http_response_write() calling before_piece before each piece of a streamed body is written (a server restarts its write deadline there, so a long stream is timed per piece)
int n_http_response_write(const N_HTTP_RESP * r, n_http_write_fn fn, void * ctx)
write the whole response (head, then body unless HEAD or bodiless)
int n_http_response_stream(N_HTTP_RESP * r, n_http_stream_fn fn, void * user, void(*)(void *user) free_user)
produce the body while it is sent (drops a memory or file body): no Content-Length; chunked framing for HTTP/1.1, the connection closed after the body for HTTP/1.0.
int n_http_response_set_status(N_HTTP_RESP * r, int status)
change the status code
int n_http_response_set_header(N_HTTP_RESP * r, const char * name, const char * value)
set a header: remove every header of that name (ASCII case-insensitive), then add it; same refusals as add_header
int n_http_response_set_connection(N_HTTP_RESP * r, int keep_alive, int version_minor, int head_only)
connection handling for this response
size_t n_http_response_remove_header(N_HTTP_RESP * r, const char * name)
remove every header of that name (ASCII case-insensitive)
N_HTTP_RESP * n_http_response_new(int status)
new response with a status, keep-alive off, HTTP/1.1
int n_http_response_head(const N_HTTP_RESP * r, N_STR ** out)
append the status line and headers, through the blank line
const char * n_http_response_get_header(const N_HTTP_RESP * r, const char * name)
value of the first header of that name (ASCII case-insensitive)
void n_http_response_free(N_HTTP_RESP ** r)
free a response (closing its file body) and set *r to NULL
int n_http_response_file(N_HTTP_RESP * r, int fd, long long offset, long long length)
use a file range as the body; the response owns fd from now on (it is closed on free, also when this call fails) and drops any memory body
long long n_http_response_body_length(const N_HTTP_RESP * r)
body length the response declares (Content-Length), 0 for a bodiless status
int n_http_response_append(N_HTTP_RESP * r, const void * data, size_t len)
append bytes to the memory body (drops a file or streamed body)
int n_http_response_add_header(N_HTTP_RESP * r, const char * name, const char * value)
add a header line (repeats allowed, e.g.
N_HTTP_RANGE n_http_parse_range(const char * value, size_t len, long long total, long long * first, long long * last)
interpret a Range header for a body of total bytes

Defines

Name
N_HTTP_RESPONSE_VALUE_MAX
longest header value accepted, in bytes
N_HTTP_RESPONSE_HEADERS_MAX
most headers a response may carry

Types Documentation

typedef n_http_write_fn

typedef ssize_t(* n_http_write_fn) (void *ctx, const void *buf, size_t len);

a write function: write up to len bytes, return how many were written (at least 1) or -1 on a fatal error; partial writes are retried

typedef n_http_stream_fn

typedef int(* n_http_stream_fn) (void *user, N_HTTP_STREAM *out);

a streamed body's producer: write the body with n_http_stream_write(), return TRUE when it is complete, FALSE to cut it short (the connection then closes)

enum N_HTTP_RANGE

Enumerator Value Description
N_HTTP_RANGE_UNSATISFIABLE 2 send 416, with a Content-Range that gives only the total
N_HTTP_RANGE_OK 1 one satisfiable range: send 206
N_HTTP_RANGE_NONE 0 no usable Range: send the whole body (200)

result of n_http_parse_range()

Functions Documentation

function n_http_stream_write

int n_http_stream_write(
    N_HTTP_STREAM * s,
    const void * data,
    size_t len
)

write a piece of a streamed body (one chunk for HTTP/1.1)

Parameters:

  • s the stream the producer received
  • data bytes
  • len number of bytes (0 does nothing)
  • s the stream
  • data bytes
  • len number of bytes

Return:

  • TRUE, FALSE when the peer is gone or a write failed (and for every call after that): the producer should stop
  • TRUE, FALSE once a write failed

write a piece of a streamed body, see the header

write a piece of a streamed body (one chunk for HTTP/1.1)

function n_http_status_reason

const char * n_http_status_reason(
    int status
)

reason phrase of a status code ("Not Found"); a generic class phrase for an unlisted code, "" outside 100..599

Parameters:

  • status the status code
  • status the status code

Return:

  • a static string
  • a static string, "" outside 100..599

reason phrase of a status code, a class phrase for an unlisted one

reason phrase of a status code ("Not Found"); a generic class phrase for an unlisted code, "" outside 100..599

function n_http_response_write_ex

int n_http_response_write_ex(
    const N_HTTP_RESP * r,
    n_http_write_fn fn,
    void * ctx,
    void(*)(void *ctx) before_piece
)

n_http_response_write() calling before_piece before each piece of a streamed body is written (a server restarts its write deadline there, so a long stream is timed per piece)

Parameters:

  • r the response
  • fn the write function
  • ctx passed to fn and before_piece
  • before_piece called before each piece, or NULL
  • r the response
  • fn the write function
  • ctx passed to fn and before_piece
  • before_piece called before each piece, or NULL

Return:

  • TRUE when every byte was written and a producer completed
  • TRUE when every byte was written and a producer completed

write the whole response, calling before_piece before each piece of a streamed body

n_http_response_write() calling before_piece before each piece of a streamed body is written (a server restarts its write deadline there, so a long stream is timed per piece)

function n_http_response_write

int n_http_response_write(
    const N_HTTP_RESP * r,
    n_http_write_fn fn,
    void * ctx
)

write the whole response (head, then body unless HEAD or bodiless)

Parameters:

  • r the response
  • fn the write function
  • ctx passed to fn
  • r the response
  • fn the write function
  • ctx passed to fn

Return:

  • TRUE when every byte was written, FALSE otherwise
  • TRUE when every byte was written, FALSE otherwise

Partial writes are continued; a file body is read in chunks from its offset. Stops at the first write error or short file.

function n_http_response_stream

int n_http_response_stream(
    N_HTTP_RESP * r,
    n_http_stream_fn fn,
    void * user,
    void(*)(void *user) free_user
)

produce the body while it is sent (drops a memory or file body): no Content-Length; chunked framing for HTTP/1.1, the connection closed after the body for HTTP/1.0.

Parameters:

  • r the response
  • fn the producer
  • user passed to fn
  • free_user frees user with the response (also when this call fails), or NULL
  • r the response
  • fn the producer
  • user passed to fn
  • free_user frees user with the response, or NULL

Return:

  • TRUE, FALSE on a bad argument
  • TRUE, FALSE on a bad argument

use a producer as the body, see the header

The producer runs inside n_http_response_write(), after the head, in the writer's thread. produce the body while it is sent (drops a memory or file body): no Content-Length; chunked framing for HTTP/1.1, the connection closed after the body for HTTP/1.0.

function n_http_response_set_status

int n_http_response_set_status(
    N_HTTP_RESP * r,
    int status
)

change the status code

Parameters:

  • r the response
  • status 100..599

Return: TRUE, FALSE on a bad argument

function n_http_response_set_header

int n_http_response_set_header(
    N_HTTP_RESP * r,
    const char * name,
    const char * value
)

set a header: remove every header of that name (ASCII case-insensitive), then add it; same refusals as add_header

Parameters:

  • r the response
  • name header name
  • value header value
  • r the response
  • name header name
  • value header value

Return:

  • TRUE, FALSE when refused
  • TRUE, FALSE when refused (the old headers are kept then)

set a header: remove every header of that name, then add it

set a header: remove every header of that name (ASCII case-insensitive), then add it; same refusals as add_header

function n_http_response_set_connection

int n_http_response_set_connection(
    N_HTTP_RESP * r,
    int keep_alive,
    int version_minor,
    int head_only
)

connection handling for this response

Parameters:

  • r the response
  • keep_alive non-zero to keep the connection open
  • version_minor the request's HTTP/1.x minor version (0 or 1)
  • head_only non-zero for a HEAD request

Return: TRUE, FALSE on a bad argument

function n_http_response_remove_header

size_t n_http_response_remove_header(
    N_HTTP_RESP * r,
    const char * name
)

remove every header of that name (ASCII case-insensitive)

Parameters:

  • r the response
  • name header name

Return: the number removed

function n_http_response_new

N_HTTP_RESP * n_http_response_new(
    int status
)

new response with a status, keep-alive off, HTTP/1.1

Parameters:

  • status status code, 100..599

Return: the response, NULL on a bad status or allocation failure

function n_http_response_head

int n_http_response_head(
    const N_HTTP_RESP * r,
    N_STR ** out
)

append the status line and headers, through the blank line

Parameters:

  • r the response
  • out destination, appended to (created when *out is NULL)

Return: TRUE, FALSE on a bad argument or allocation failure

function n_http_response_get_header

const char * n_http_response_get_header(
    const N_HTTP_RESP * r,
    const char * name
)

value of the first header of that name (ASCII case-insensitive)

Parameters:

  • r the response
  • name header name

Return: the value, or NULL

function n_http_response_free

void n_http_response_free(
    N_HTTP_RESP ** r
)

free a response (closing its file body) and set *r to NULL

Parameters:

  • r address of the response pointer (may point to NULL)

function n_http_response_file

int n_http_response_file(
    N_HTTP_RESP * r,
    int fd,
    long long offset,
    long long length
)

use a file range as the body; the response owns fd from now on (it is closed on free, also when this call fails) and drops any memory body

Parameters:

  • r the response
  • fd an open, readable descriptor
  • offset first byte
  • length number of bytes from offset
  • r the response
  • fd an open, readable descriptor
  • offset first byte
  • length number of bytes from offset

Return:

  • TRUE, FALSE on a bad argument
  • TRUE, FALSE on a bad argument (fd is closed then too)

use a file range as the body; the response owns fd from now on

use a file range as the body; the response owns fd from now on (it is closed on free, also when this call fails) and drops any memory body

function n_http_response_body_length

long long n_http_response_body_length(
    const N_HTTP_RESP * r
)

body length the response declares (Content-Length), 0 for a bodiless status

Parameters:

  • r the response
  • r the response

Return:

  • the length, -1 on a NULL argument or a streamed body
  • the length, -1 on a NULL argument

body length the response declares, 0 for a bodiless status

body length the response declares (Content-Length), 0 for a bodiless status

function n_http_response_append

int n_http_response_append(
    N_HTTP_RESP * r,
    const void * data,
    size_t len
)

append bytes to the memory body (drops a file or streamed body)

Parameters:

  • r the response
  • data bytes (may be NULL only when len is 0)
  • len number of bytes
  • r the response
  • data bytes (may be NULL only when len is 0)
  • len number of bytes

Return:

  • TRUE, FALSE on a bad argument or allocation failure
  • TRUE, FALSE on a bad argument or allocation failure

append bytes to the memory body (drops a file body)

append bytes to the memory body (drops a file or streamed body)

function n_http_response_add_header

int n_http_response_add_header(
    N_HTTP_RESP * r,
    const char * name,
    const char * value
)

add a header line (repeats allowed, e.g.

Parameters:

  • r the response
  • name header name
  • value header value
  • r the response
  • name header name
  • value header value

Return:

  • TRUE, FALSE when refused
  • TRUE, FALSE when refused

add a header line after validating name and value

Set-Cookie)

Refused: a name that is not a token; Content-Length, Transfer-Encoding and Connection (the builder's own); a value holding a control byte other than a tab, or longer than N_HTTP_RESPONSE_VALUE_MAX; more than N_HTTP_RESPONSE_HEADERS_MAX headers. Surrounding spaces of the value are trimmed. add a header line (repeats allowed, e.g.

function n_http_parse_range

N_HTTP_RANGE n_http_parse_range(
    const char * value,
    size_t len,
    long long total,
    long long * first,
    long long * last
)

interpret a Range header for a body of total bytes

Parameters:

  • value the Range header value (may be NULL: NONE)
  • len its length
  • total the full body length
  • first receives the first byte (OK only)
  • last receives the last byte, inclusive (OK only)
  • value the Range header value (may be NULL: NONE)
  • len its length
  • total the full body length
  • first receives the first byte (OK only)
  • last receives the last byte, inclusive (OK only)

Return:

interpret a single-range Range header for a body of total bytes

Only a single "bytes=a-b", "bytes=a-" or "bytes=-n" range is served; anything else (other units, several ranges, malformed) answers NONE so the full body goes out, which is always correct. A range starting at or past the end is UNSATISFIABLE. interpret a Range header for a body of total bytes

Macros Documentation

define N_HTTP_RESPONSE_VALUE_MAX

#define N_HTTP_RESPONSE_VALUE_MAX 8192

longest header value accepted, in bytes

define N_HTTP_RESPONSE_HEADERS_MAX

#define N_HTTP_RESPONSE_HEADERS_MAX 64

most headers a response may carry