Open-Source Wikis

/

nginx

/

Primitives

/

String (`ngx_str_t`)

nginx/nginx

String (ngx_str_t)

Active contributors: Maxim Dounin, Sergey Kandaurov

What it is

ngx_str_t is nginx's string type. It carries a length and a pointer; it is not null-terminated. Almost every place a function would take a const char * in normal C code, nginx takes a ngx_str_t * instead.

Definition

src/core/ngx_string.h:

typedef struct {
    size_t      len;
    u_char     *data;
} ngx_str_t;

That's it. Two fields, ~16 bytes on amd64.

Why not C strings?

Two reasons:

  • Most strings come from the network. A request line is a span inside a recv() buffer. A header value is a span inside the same buffer. nginx wants to point into those spans without copying — and there's no NUL terminator to terminate against.
  • NUL-injection is a class of bugs. Headers and URIs from untrusted input can contain \0. NUL-terminated strings silently truncate at the first \0; length-prefixed strings carry the bytes faithfully and let the caller decide.

The result is faster, safer string handling at the cost of being unable to pass strings directly to most stdlib functions.

Construction

Helper Use
ngx_string("hello") Compile-time literal: { 5, (u_char *) "hello" }
ngx_str_set(&s, "hello") Set both fields from a literal
ngx_str_null(&s) { 0, NULL }
ngx_null_string The empty ngx_str_t constant
(ngx_str_t) { len, data } C99 designated initializer (less common; the macros are preferred)

For dynamically-built strings:

ngx_str_t  s;

s.data = ngx_pnalloc(pool, len);
if (s.data == NULL) return NGX_ERROR;
ngx_memcpy(s.data, src, len);
s.len = len;

Comparison

Helper Behavior
ngx_strncmp(a, b, n) Like strncmp. Caller must guard against length mismatches.
ngx_strncasecmp(a, b, n) Case-insensitive variant.
ngx_strcasecmp(a, b) NUL-aware case-insensitive (operates on C strings, rare in practice).
ngx_strcmp(a, b) NUL-aware (operates on C strings).
ngx_memcmp(a, b, n) Byte-equality.

To compare two ngx_str_ts for equality, idiomatic nginx is:

if (s1->len == s2->len && ngx_strncmp(s1->data, s2->data, s1->len) == 0) {
    /* equal */
}

Mutation

Helper Behavior
ngx_strlow(dst, src, n) Lowercase copy (ASCII only)
ngx_strchr(s, c) NUL-aware (rare; usually you'd ngx_strlchr)
ngx_strlchr(p, last, c) Length-bounded strchr
ngx_cpymem(dst, src, n) Like memcpy but returns dst + n so you can chain copies
ngx_copy(dst, src, n) Specialized fast memcpy for small fixed sizes

Idiomatic chained copy:

u_char  *p = buf;
p = ngx_copy(p, "GET ", 4);
p = ngx_copy(p, uri.data, uri.len);
p = ngx_copy(p, " HTTP/1.1\r\n", 11);

Formatting

ngx_sprintf(buf, fmt, ...) and ngx_snprintf(buf, max, fmt, ...) are nginx's printf. They support a custom format-specifier set:

Specifier Type
%V ngx_str_t *
%v ngx_variable_value_t *
%s NUL-terminated char *
%*s Length + pointer (alternative to %V)
%i, %I, %uI, %uA, %uD, %uL Integer types of various widths
%f double
%T time_t
%M ngx_msec_t (milliseconds)
%xz hex size_t
%P ngx_pid_t
%O off_t

Stdlib printf("%s", str.data) is wrong in nginx code (might not be NUL-terminated). Always use %V with an ngx_str_t *.

ngx_sprintf returns a pointer to the byte after the last written byte — chaining-friendly.

Parsing

Helper Use
ngx_atoi(p, n) Decimal ngx_int_t
ngx_atosz(p, n) Decimal ssize_t
ngx_atotm(p, n) Decimal time_t
ngx_atofp(p, n, point) Fixed-point decimal (3 fractional digits → ms)
ngx_hextoi(p, n) Hex ngx_int_t
ngx_atoof(p, n) Decimal off_t

Each returns NGX_ERROR (-1) on parse failure. Inputs are length-prefixed; no NUL needed.

Charset

u_char rather than char is the official byte type. nginx is signedness-pedantic — char is signed on most platforms and that creates surprises with the high-bit characters in HTTP headers. The convention is u_char * for raw byte spans, with explicit casts at the boundary to functions that take char *.

Hashing

Helper Use
ngx_hash(key, c) Update a 32-bit FNV-1a-style hash with one byte
ngx_hash_key(p, n) Hash a buffer
ngx_hash_key_lc(p, n) Hash a buffer, lowercased (used for header lookup)
ngx_hash_strlow(dst, src, n) Lowercase a string and return its lowercased hash

Used by ngx_hash_t for read-only hash table lookups.

Pitfalls

  • %s vs %V. Mixing them up is a footgun. %V consumes a ngx_str_t *; %s consumes a NUL-terminated char *. The former works on most nginx data; the latter rarely does.
  • data is u_char *, not char *. Cast at the boundary or use the n* helpers.
  • Length matters. Don't assume any byte after data[len] is valid memory.
  • Comparisons must include length. ngx_strncmp(a, b, n) doesn't check that a and b are both at least n long — that's on you.

Cross-references

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

String (`ngx_str_t`) – nginx wiki | Factory