<!-- review: finished -->

<a id="developer-guide"></a>

# Guia do desenvolvedor

<a id="coding-conventions"></a>

## Convenções de codificação

O código-fonte segue a seguinte estrutura e convenções.

<a id="code-layout"></a>

### Layout do código

* `auto` — Scripts de build
* `src`
  * `core` — Tipos e funções básicas — string, array, log,
    pool, etc.
  * `event` — Núcleo de eventos
    * `modules` — Módulos de notificação de eventos:
      `epoll`, `kqueue`, `select`
      etc.
  * `http` — Módulo HTTP principal e código comum
    * `modules` — Outros módulos HTTP
    * `v2` — HTTP/2
  * `mail` — Módulos de mail
  * `os` — Código específico da plataforma
    * `unix`
    * `win32`
  * `stream` — Módulos de stream

<a id="include-files"></a>

### Arquivos de inclusão

As duas declarações `#include` a seguir devem aparecer no
início de todo arquivo Angie:

```c
#include <ngx_config.h>
#include <ngx_core.h>
```

Além disso, código HTTP deve incluir

```c
#include <ngx_http.h>
```

Código de mail deve incluir

```c
#include <ngx_mail.h>
```

Código de stream deve incluir

```c
#include <ngx_stream.h>
```

<a id="integers"></a>

### Inteiros

Para propósitos gerais, o código Angie usa dois tipos de inteiros,
`ngx_int_t` e `ngx_uint_t`, que são
typedefs para `intptr_t` e `uintptr_t`
respectivamente.

<a id="common-return-codes"></a>

### Códigos de retorno comuns

A maioria das funções no Angie retorna os seguintes códigos:

* `NGX_OK` — Operação bem-sucedida.
* `NGX_ERROR` — Operação falhou.
* `NGX_AGAIN` — Operação incompleta; chame a função novamente.
* `NGX_DECLINED` — Operação rejeitada, por exemplo, porque está
  desabilitada na configuração. Isso nunca é um erro.
* `NGX_BUSY` — Recurso não está disponível.
* `NGX_DONE` — Operação completa ou continuada em outro lugar.
  Também usado como um código de sucesso alternativo.
* `NGX_ABORT` — Função foi abortada.
  Também usado como um código de erro alternativo.

<a id="error-handling"></a>

### Tratamento de erros

A macro `ngx_errno` retorna o último código de erro do sistema.
Ela é mapeada para `errno` em plataformas POSIX e para a
chamada `GetLastError()` no Windows.
A macro `ngx_socket_errno` retorna o último número de erro
de socket.
Como a macro `ngx_errno`, ela é mapeada para
`errno` em plataformas POSIX.
Ela é mapeada para a chamada `WSAGetLastError()` no Windows.
Acessar os valores de `ngx_errno` ou
`ngx_socket_errno` mais de uma vez seguida pode causar
problemas de desempenho.
Se o valor do erro pode ser usado múltiplas vezes, armazene-o em uma variável local
do tipo `ngx_err_t`.
Para definir erros, use as macros `ngx_set_errno(errno)` e
`ngx_set_socket_errno(errno)`.

Os valores de `ngx_errno` e
`ngx_socket_errno` podem ser passados para as funções de log
`ngx_log_error()` e `ngx_log_debugX()`, em
cujo caso o texto de erro do sistema é adicionado à mensagem de log.

Exemplo usando `ngx_errno`:

```c
ngx_int_t
ngx_my_kill(ngx_pid_t pid, ngx_log_t *log, int signo)
{
    ngx_err_t  err;

    if (kill(pid, signo) == -1) {
        err = ngx_errno;

        ngx_log_error(NGX_LOG_ALERT, log, err, "kill(%P, %d) failed", pid, signo);

        if (err == NGX_ESRCH) {
            return 2;
        }

        return 1;
    }

    return 0;
}
```

<a id="strings"></a>

### Strings

<a id="overview"></a>

#### Visão geral

Para strings C, o Angie usa o ponteiro de tipo de caractere não assinado
`u_char *`.

O tipo de string do Angie `ngx_str_t` é definido como segue:

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

O campo `len` contém o comprimento da string e
`data` contém os dados da string.
A string, mantida em `ngx_str_t`, pode ou não ser
terminada em null após os `len` bytes.
Na maioria dos casos não é.
No entanto, em certas partes do código (por exemplo, ao analisar configuração),
objetos `ngx_str_t` são conhecidos por serem terminados em null, o que
simplifica a comparação de strings e torna mais fácil passar as strings para
syscalls.

As operações de string no Angie são declaradas em
`src/core/ngx_string.h`.
Algumas delas são wrappers em torno de funções C padrão:

* `ngx_strcmp()`
* `ngx_strncmp()`
* `ngx_strstr()`
* `ngx_strlen()`
* `ngx_strchr()`
* `ngx_memcmp()`
* `ngx_memset()`
* `ngx_memcpy()`
* `ngx_memmove()`

Outras funções de string são específicas do Angie:

* `ngx_memzero()` — Preenche memória com zeros.
* `ngx_explicit_memzero()` — Faz o mesmo que
  `ngx_memzero()`, mas esta chamada nunca é removida pela
  otimização de eliminação de armazenamento morto do compilador.
  Esta função pode ser usada para limpar dados sensíveis como senhas e chaves.
* `ngx_cpymem()` — Faz o mesmo que
  `ngx_memcpy()`, mas retorna o endereço de destino final.
  Esta é útil para anexar múltiplas strings em sequência.
* `ngx_movemem()` — Faz o mesmo que
  `ngx_memmove()`, mas retorna o endereço de destino final.
* `ngx_strlchr()` — Procura por um caractere em uma string,
  delimitada por dois ponteiros.

As seguintes funções realizam conversão de caso e comparação:

* `ngx_tolower()`
* `ngx_toupper()`
* `ngx_strlow()`
* `ngx_strcasecmp()`
* `ngx_strncasecmp()`

As seguintes macros simplificam a inicialização de strings:

* `ngx_string(text)` — inicializador estático para o
  tipo `ngx_str_t` a partir do literal de string C
  `text`
* `ngx_null_string` — inicializador de string vazia estático para o
  tipo `ngx_str_t`
* `ngx_str_set(str, text)` — inicializa string
  `str` do tipo `ngx_str_t *` com o literal de string C
  `text`
* `ngx_str_null(str)` — inicializa string `str`
  do tipo `ngx_str_t *` com a string vazia

<a id="formatting"></a>

#### Formatação

As seguintes funções de formatação suportam tipos específicos do Angie:

* `ngx_sprintf(buf, fmt, ...)`
* `ngx_snprintf(buf, max, fmt, ...)`
* `ngx_slprintf(buf, last, fmt, ...)`
* `ngx_vslprintf(buf, last, fmt, args)`
* `ngx_vsnprintf(buf, max, fmt, args)`

A lista completa de opções de formatação suportadas por essas funções está
em `src/core/ngx_string.c`. Algumas delas são:

* `%O` — `off_t`
* `%T` — `time_t`
* `%z` — `ssize_t`
* `%i` — `ngx_int_t`
* `%p` — `void *`
* `%V` — `ngx_str_t *`
* `%s` — `u_char *` (terminado em null)
* `%*s` — `size_t + u_char *`

Você pode antepor `u` na maioria dos tipos para torná-los não assinados.
Para converter saída para hex, use `X` ou `x`.

<a id="numeric-conversion"></a>

### Conversão numérica

Várias funções para conversão numérica são implementadas no Angie.
As primeiras quatro convertem cada uma uma string de comprimento dado para um inteiro positivo do
tipo indicado.
Elas retornam `NGX_ERROR` em caso de erro.

* `ngx_atoi(line, n)` — `ngx_int_t`
* `ngx_atosz(line, n)` — `ssize_t`
* `ngx_atoof(line, n)` — `off_t`
* `ngx_atotm(line, n)` — `time_t`

Há duas funções adicionais de conversão numérica.
Como as primeiras quatro, elas retornam `NGX_ERROR` em caso de erro.

* `ngx_atofp(line, n, point)` — Converte um número de ponto fixo
  de comprimento dado para um inteiro positivo do tipo
  `ngx_int_t`.
  O resultado é deslocado para a esquerda por `point` posições
  decimais.
  A representação em string do número deve ter no máximo
  `point` dígitos fracionários.
  Por exemplo, `ngx_atofp("10.5", 4, 2)` retorna
  `1050`.
* `ngx_hextoi(line, n)` — Converte uma representação hexadecimal
  de um inteiro positivo para `ngx_int_t`.

<a id="regular-expressions"></a>

### Expressões regulares

A interface de expressões regulares no Angie é um wrapper em torno
da biblioteca [PCRE](http://www.pcre.org).
O arquivo de cabeçalho correspondente é `src/core/ngx_regex.h`.

Para usar uma expressão regular para correspondência de strings, ela primeiro precisa ser
compilada, o que geralmente é feito na fase de configuração.
Note que como o suporte PCRE é opcional, todo código usando a interface deve
ser protegido pela macro `NGX_PCRE` circundante:

```c
#if (NGX_PCRE)
ngx_regex_t          *re;
ngx_regex_compile_t   rc;

u_char                errstr[NGX_MAX_CONF_ERRSTR];

ngx_str_t  value = ngx_string("message (\\d\\d\\d).*Codeword is '(?<cw>\\w+)'");

ngx_memzero(&rc, sizeof(ngx_regex_compile_t));

rc.pattern = value;
rc.pool = cf->pool;
rc.err.len = NGX_MAX_CONF_ERRSTR;
rc.err.data = errstr;
/* rc.options can be set to NGX_REGEX_CASELESS */

if (ngx_regex_compile(&rc) != NGX_OK) {
    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
    return NGX_CONF_ERROR;
}

re = rc.regex;
#endif
```

Após compilação bem-sucedida, os campos `captures` e
`named_captures` na estrutura
`ngx_regex_compile_t` contêm a contagem de todas as
capturas e capturas nomeadas, respectivamente, encontradas na expressão regular.

A expressão regular compilada pode então ser usada para correspondência contra strings:

```c
ngx_int_t  n;
int        captures[(1 + rc.captures) * 3];

ngx_str_t input = ngx_string("This is message 123. Codeword is 'foobar'.");

n = ngx_regex_exec(re, &input, captures, (1 + rc.captures) * 3);
if (n >= 0) {
    /* string matches expression */

} else if (n == NGX_REGEX_NO_MATCHED) {
    /* no match was found */

} else {
    /* some error */
    ngx_log_error(NGX_LOG_ALERT, log, 0, ngx_regex_exec_n " failed: %i", n);
}
```

Os argumentos para `ngx_regex_exec()` são a expressão regular
compilada `re`, a string a ser correspondida `input`,
um array opcional de inteiros para armazenar quaisquer `captures` que
sejam encontradas, e o `size` do array.
O tamanho do array `captures` deve ser um múltiplo de três,
conforme exigido pela
[API PCRE](http://www.pcre.org/original/doc/html/pcreapi.html).
No exemplo, o tamanho é calculado a partir do número total de capturas mais
um para a própria string correspondida.

Se houver correspondências, as capturas podem ser acessadas da seguinte forma:

```c
u_char     *p;
size_t      size;
ngx_str_t   name, value;

/* all captures */
for (i = 0; i < n * 2; i += 2) {
    value.data = input.data + captures[i];
    value.len = captures[i + 1] - captures[i];
}

/* accessing named captures */

size = rc.name_size;
p = rc.names;

for (i = 0; i < rc.named_captures; i++, p += size) {

    /* capture name */
    name.data = &p[2];
    name.len = ngx_strlen(name.data);

    n = 2 * ((p[0] << 8) + p[1]);

    /* captured value */
    value.data = &input.data[captures[n]];
    value.len = captures[n + 1] - captures[n];
}
```

A função `ngx_regex_exec_array()` aceita um array de
elementos `ngx_regex_elt_t` (que são apenas expressões regulares
compiladas com nomes associados), uma string para correspondência e um log.
A função aplica expressões do array à string até que
uma correspondência seja encontrada ou não restem mais expressões.
O valor de retorno é `NGX_OK` quando há uma correspondência e
`NGX_DECLINED` caso contrário, ou `NGX_ERROR`
em caso de erro.

<a id="time"></a>

### Tempo

A estrutura `ngx_time_t` representa tempo com três tipos
separados para segundos, milissegundos e o deslocamento GMT:

```c
typedef struct {
    time_t      sec;
    ngx_uint_t  msec;
    ngx_int_t   gmtoff;
} ngx_time_t;
```

A estrutura `ngx_tm_t` é um alias para
`struct tm` em plataformas UNIX e `SYSTEMTIME`
no Windows.

Para obter o tempo atual, geralmente é suficiente acessar uma das
variáveis globais disponíveis, representando o valor de tempo em cache no formato
desejado.

As representações de string disponíveis são:

* `ngx_cached_err_log_time` — Usado em entradas de log de erro:
  `"1970/09/28 12:00:00"`
* `ngx_cached_http_log_time` — Usado em entradas de log de acesso HTTP:
  `"28/Sep/1970:12:00:00 +0600"`
* `ngx_cached_syslog_time` — Usado em entradas de syslog:
  `"Sep 28 12:00:00"`
* `ngx_cached_http_time` — Usado em cabeçalhos HTTP:
  `"Mon, 28 Sep 1970 06:00:00 GMT"`
* `ngx_cached_http_log_iso8601` — O formato padrão ISO 8601:
  `"1970-09-28T12:00:00+06:00"`

As macros `ngx_time()` e `ngx_timeofday()`
retornam o valor de tempo atual em segundos e são a forma preferida de acessar
o valor de tempo em cache.

Para obter o tempo explicitamente, use `ngx_gettimeofday()`,
que atualiza seu argumento (ponteiro para
`struct timeval`).
O tempo é sempre atualizado quando o Angie retorna ao loop de eventos das chamadas
do sistema.
Para atualizar o tempo imediatamente, chame `ngx_time_update()`,
ou `ngx_time_sigsafe_update()` se estiver atualizando o tempo no
contexto do manipulador de sinal.

As seguintes funções convertem `time_t` na representação
de tempo decomposto indicada.
A primeira função em cada par converte `time_t` para
`ngx_tm_t` e a segunda (com o infixo `_libc_`)
para `struct tm`:

* `ngx_gmtime(), ngx_libc_gmtime()` — Tempo expresso como UTC
* `ngx_localtime(), ngx_libc_localtime()` — Tempo expresso
  relativo ao fuso horário local

A função `ngx_http_time(buf, time)` retorna uma representação
de string adequada para uso em cabeçalhos HTTP (por exemplo,
`"Mon, 28 Sep 1970 06:00:00 GMT"`).
A função `ngx_http_cookie_time(buf, time)` retorna uma representação
de string adequada para cookies HTTP (`"Thu, 31-Dec-37 23:55:55 GMT"`).

<a id="containers"></a>

## Contêineres

<a id="array"></a>

### Array

O tipo de array do Angie `ngx_array_t` é definido da seguinte forma

```c
typedef struct {
    void        *elts;
    ngx_uint_t   nelts;
    size_t       size;
    ngx_uint_t   nalloc;
    ngx_pool_t  *pool;
} ngx_array_t;
```

Os elementos do array estão disponíveis no campo `elts`.
O campo `nelts` contém o número de elementos.
O campo `size` contém o tamanho de um único elemento e é definido
quando o array é inicializado.

Use a chamada `ngx_array_create(pool, n, size)` para criar um
array em um pool, e a chamada `ngx_array_init(array, pool, n, size)`
para inicializar um objeto array que já foi alocado.

```c
ngx_array_t  *a, b;

/* create an array of strings with preallocated memory for 10 elements */
a = ngx_array_create(pool, 10, sizeof(ngx_str_t));

/* initialize string array for 10 elements */
ngx_array_init(&b, pool, 10, sizeof(ngx_str_t));
```

Use as seguintes funções para adicionar elementos a um array:

* `ngx_array_push(a)` adiciona um elemento no final e retorna um ponteiro
  para ele
* `ngx_array_push_n(a, n)` adiciona `n` elementos no final
  e retorna um ponteiro para o primeiro

Se a quantidade de memória atualmente alocada não for grande o suficiente para acomodar
os novos elementos, um novo bloco de memória é alocado e os elementos existentes
são copiados para ele.
O novo bloco de memória normalmente é duas vezes maior que o existente.

```c
s = ngx_array_push(a);
ss = ngx_array_push_n(&b, 3);
```

<a id="list"></a>

### Lista

No Angie uma lista é uma sequência de arrays, otimizada para inserir um número
potencialmente grande de itens.
O tipo de lista `ngx_list_t` é definido da seguinte forma:

```c
typedef struct {
    ngx_list_part_t  *last;
    ngx_list_part_t   part;
    size_t            size;
    ngx_uint_t        nalloc;
    ngx_pool_t       *pool;
} ngx_list_t;
```

Os itens reais são armazenados em partes da lista, que são definidas da seguinte forma:

```c
typedef struct ngx_list_part_s  ngx_list_part_t;

struct ngx_list_part_s {
    void             *elts;
    ngx_uint_t        nelts;
    ngx_list_part_t  *next;
};
```

Antes do uso, uma lista deve ser inicializada chamando
`ngx_list_init(list, pool, n, size)` ou criada chamando
`ngx_list_create(pool, n, size)`.
Ambas as funções recebem como argumentos o tamanho de um único item e um número de
itens por parte da lista.
Para adicionar um item a uma lista, use a função `ngx_list_push(list)`.
Para iterar sobre os itens, acesse diretamente os campos da lista conforme mostrado no
exemplo:

```c
ngx_str_t        *v;
ngx_uint_t        i;
ngx_list_t       *list;
ngx_list_part_t  *part;

list = ngx_list_create(pool, 100, sizeof(ngx_str_t));
if (list == NULL) { /* error */ }

/* add items to the list */

v = ngx_list_push(list);
if (v == NULL) { /* error */ }
ngx_str_set(v, "foo");

v = ngx_list_push(list);
if (v == NULL) { /* error */ }
ngx_str_set(v, "bar");

/* iterate over the list */

part = &list->part;
v = part->elts;

for (i = 0; /* void */; i++) {

    if (i >= part->nelts) {
        if (part->next == NULL) {
            break;
        }

        part = part->next;
        v = part->elts;
        i = 0;
    }

    ngx_do_smth(&v[i]);
}
```

As listas são usadas principalmente para cabeçalhos de entrada e saída HTTP.

As listas não suportam remoção de itens.
No entanto, quando necessário, os itens podem ser marcados internamente como ausentes sem
serem realmente removidos da lista.
Por exemplo, para marcar cabeçalhos de saída HTTP (que são armazenados como
objetos `ngx_table_elt_t`) como ausentes, defina o campo
`hash` em `ngx_table_elt_t` como
zero.
Itens marcados desta forma são explicitamente ignorados quando os cabeçalhos são iterados.

<a id="queue"></a>

### Fila

No Angie uma fila é uma lista duplamente ligada intrusiva, com cada nó definido da
seguinte forma:

```c
typedef struct ngx_queue_s  ngx_queue_t;

struct ngx_queue_s {
    ngx_queue_t  *prev;
    ngx_queue_t  *next;
};
```

O nó cabeça da fila não está ligado a nenhum dado.
Use a chamada `ngx_queue_init(q)` para inicializar o cabeça da lista
antes do uso.
As filas suportam as seguintes operações:

* `ngx_queue_insert_head(h, x)`,
  `ngx_queue_insert_tail(h, x)` — Inserir um novo nó
* `ngx_queue_remove(x)` — Remover um nó da fila
* `ngx_queue_split(h, q, n)` — Dividir uma fila em um nó,
  retornando a cauda da fila em uma fila separada
* `ngx_queue_add(h, n)` — Adicionar uma segunda fila à primeira fila
* `ngx_queue_head(h)`,
  `ngx_queue_last(h)` — Obter o primeiro ou último nó da fila
* `ngx_queue_sentinel(h)` — Obter um objeto sentinela da fila para terminar
  a iteração
* `ngx_queue_data(q, type, link)` — Obter uma referência ao
  início de uma estrutura de dados do nó da fila, considerando o deslocamento do campo da fila
  nela

Um exemplo:

```c
typedef struct {
    ngx_str_t    value;
    ngx_queue_t  queue;
} ngx_foo_t;

ngx_foo_t    *f;
ngx_queue_t   values, *q;

ngx_queue_init(&values);

f = ngx_palloc(pool, sizeof(ngx_foo_t));
if (f == NULL) { /* error */ }
ngx_str_set(&f->value, "foo");

ngx_queue_insert_tail(&values, &f->queue);

/* insert more nodes here */

for (q = ngx_queue_head(&values);
     q != ngx_queue_sentinel(&values);
     q = ngx_queue_next(q))
{
    f = ngx_queue_data(q, ngx_foo_t, queue);

    ngx_do_smth(&f->value);
}
```

<a id="red-black-tree"></a>

### Árvore Rubro-Negra

O arquivo de cabeçalho `src/core/ngx_rbtree.h` fornece acesso à
implementação eficiente de árvores rubro-negras.

```c
typedef struct {
    ngx_rbtree_t       rbtree;
    ngx_rbtree_node_t  sentinel;

    /* dados personalizados por árvore aqui */
} my_tree_t;

typedef struct {
    ngx_rbtree_node_t  rbnode;

    /* dados personalizados por nó */
    foo_t              val;
} my_node_t;
```

Para lidar com uma árvore como um todo, você precisa de dois nós: raiz e sentinela.
Tipicamente, eles são adicionados a uma estrutura personalizada, permitindo que você
organize seus dados em uma árvore na qual as folhas contêm um link para ou incorporam
seus dados.

Para inicializar uma árvore:

```c
my_tree_t  root;

ngx_rbtree_init(&root.rbtree, &root.sentinel, insert_value_function);
```

Para percorrer uma árvore e inserir novos valores, use as
funções "`insert_value`".
Por exemplo, a função `ngx_str_rbtree_insert_value` lida
com o tipo `ngx_str_t`.
Seus argumentos são ponteiros para um nó raiz de uma inserção, o nó recém-criado
a ser adicionado e uma sentinela da árvore.

```c
void ngx_str_rbtree_insert_value(ngx_rbtree_node_t *temp,
                                 ngx_rbtree_node_t *node,
                                 ngx_rbtree_node_t *sentinel)
```

O percurso é bastante direto e pode ser demonstrado com o
seguinte padrão de função de busca:

```c
my_node_t *
my_rbtree_lookup(ngx_rbtree_t *rbtree, foo_t *val, uint32_t hash)
{
    ngx_int_t           rc;
    my_node_t          *n;
    ngx_rbtree_node_t  *node, *sentinel;

    node = rbtree->root;
    sentinel = rbtree->sentinel;

    while (node != sentinel) {

        n = (my_node_t *) node;

        if (hash != node->key) {
            node = (hash < node->key) ? node->left : node->right;
            continue;
        }

        rc = compare(val, node->val);

        if (rc < 0) {
            node = node->left;
            continue;
        }

        if (rc > 0) {
            node = node->right;
            continue;
        }

        return n;
    }

    return NULL;
}
```

A função `compare()` é uma função comparadora clássica que
retorna um valor menor que, igual a ou maior que zero.
Para acelerar as buscas e evitar comparar objetos de usuário que podem ser grandes, um campo
hash inteiro é usado.

Para adicionar um nó a uma árvore, aloque um novo nó, inicialize-o e chame
`ngx_rbtree_insert()`:

```c
my_node_t          *my_node;
ngx_rbtree_node_t  *node;

my_node = ngx_palloc(...);
init_custom_data(&my_node->val);

node = &my_node->rbnode;
node->key = create_key(my_node->val);

ngx_rbtree_insert(&root->rbtree, node);
```

Para remover um nó, chame a função `ngx_rbtree_delete()`:

```c
ngx_rbtree_delete(&root->rbtree, node);
```

<a id="hash-1"></a>

### Hash

As funções de tabela hash são declaradas em `src/core/ngx_hash.h`.
Tanto correspondência exata quanto com curingas são suportadas.
A última requer configuração extra e é descrita em uma seção separada abaixo.

Antes de inicializar um hash, você precisa saber o número de elementos que ele irá
conter para que o Angie possa construí-lo de forma otimizada.
Dois parâmetros que precisam ser configurados são `max_size`
e `bucket_size`, conforme detalhado em um
[documento](https://pt.angie.software//angie/docs/configuration/configfile.md#configure-hashes) separado.
Eles geralmente são configuráveis pelo usuário.
As configurações de inicialização do hash são armazenadas com o
tipo `ngx_hash_init_t`, e o hash em si é
`ngx_hash_t`:

```c
ngx_hash_t       foo_hash;
ngx_hash_init_t  hash;

hash.hash = &foo_hash;
hash.key = ngx_hash_key;
hash.max_size = 512;
hash.bucket_size = ngx_align(64, ngx_cacheline_size);
hash.name = "foo_hash";
hash.pool = cf->pool;
hash.temp_pool = cf->temp_pool;
```

O `key` é um ponteiro para uma função que cria a chave
inteira do hash a partir de uma string.
Existem duas funções genéricas de criação de chave:
`ngx_hash_key(data, len)` e
`ngx_hash_key_lc(data, len)`.
A última converte uma string para todos os caracteres minúsculos, então a string passada
deve ser gravável.
Se isso não for verdade, passe a flag `NGX_HASH_READONLY_KEY`
para a função, inicializando o array de chaves (veja abaixo).

As chaves hash são armazenadas em `ngx_hash_keys_arrays_t` e
são inicializadas com `ngx_hash_keys_array_init(arr, type)`:
O segundo parâmetro (`type`) controla a quantidade de recursos
pré-alocados para o hash e pode ser `NGX_HASH_SMALL` ou
`NGX_HASH_LARGE`.
O último é apropriado se você espera que o hash contenha milhares de
elementos.

```c
ngx_hash_keys_arrays_t  foo_keys;

foo_keys.pool = cf->pool;
foo_keys.temp_pool = cf->temp_pool;

ngx_hash_keys_array_init(&foo_keys, NGX_HASH_SMALL);
```

Para inserir chaves em um array de chaves hash, use a
função `ngx_hash_add_key(keys_array, key, value, flags)`:

```c
ngx_str_t k1 = ngx_string("key1");
ngx_str_t k2 = ngx_string("key2");

ngx_hash_add_key(&foo_keys, &k1, &my_data_ptr_1, NGX_HASH_READONLY_KEY);
ngx_hash_add_key(&foo_keys, &k2, &my_data_ptr_2, NGX_HASH_READONLY_KEY);
```

Para construir a tabela hash, chame a
função `ngx_hash_init(hinit, key_names, nelts)`:

```c
ngx_hash_init(&hash, foo_keys.keys.elts, foo_keys.keys.nelts);
```

A função falha se os parâmetros `max_size` ou
`bucket_size` não forem grandes o suficiente.

Quando o hash é construído, use a
função `ngx_hash_find(hash, key, name, len)` para buscar
elementos:

```c
my_data_t   *data;
ngx_uint_t   key;

key = ngx_hash_key(k1.data, k1.len);

data = ngx_hash_find(&foo_hash, key, k1.data, k1.len);
if (data == NULL) {
    /* key not found */
}
```

<a id="wildcard-matching"></a>

#### Correspondência com curingas

Para criar um hash que funciona com curingas, use o
tipo `ngx_hash_combined_t`.
Ele inclui o tipo hash descrito acima e tem dois arrays de chaves adicionais:
`dns_wc_head` e `dns_wc_tail`.
A inicialização das propriedades básicas é similar a um hash regular:

```c
ngx_hash_init_t      hash
ngx_hash_combined_t  foo_hash;

hash.hash = &foo_hash.hash;
hash.key = ...;
```

É possível adicionar chaves curinga usando a
flag `NGX_HASH_WILDCARD_KEY`:

```c
/* k1 = ".example.org"; */
/* k2 = "foo.*";        */
ngx_hash_add_key(&foo_keys, &k1, &data1, NGX_HASH_WILDCARD_KEY);
ngx_hash_add_key(&foo_keys, &k2, &data2, NGX_HASH_WILDCARD_KEY);
```

A função reconhece curingas e adiciona chaves nos arrays correspondentes.
Por favor, consulte a
documentação do módulo [Map](https://pt.angie.software//angie/docs/configuration/modules/http/http_map.md#http-map)
para a descrição da sintaxe de curingas e do
algoritmo de correspondência.

Dependendo do conteúdo das chaves adicionadas, você pode precisar inicializar até três
arrays de chaves: um para correspondência exata (descrito acima) e dois mais para habilitar
correspondência começando do início ou fim de uma string:

```c
if (foo_keys.dns_wc_head.nelts) {

    ngx_qsort(foo_keys.dns_wc_head.elts,
              (size_t) foo_keys.dns_wc_head.nelts,
              sizeof(ngx_hash_key_t),
              cmp_dns_wildcards);

    hash.hash = NULL;
    hash.temp_pool = pool;

    if (ngx_hash_wildcard_init(&hash, foo_keys.dns_wc_head.elts,
                               foo_keys.dns_wc_head.nelts)
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    foo_hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
}
```

O array de chaves precisa ser ordenado, e os resultados da inicialização devem ser adicionados
ao hash combinado.
A inicialização do array `dns_wc_tail` é feita de forma similar.

A busca em um hash combinado é tratada pela
função `ngx_hash_find_combined(chash, key, name, len)`:

```c
/* key = "bar.example.org"; - irá corresponder a ".example.org" */
/* key = "foo.example.com"; - irá corresponder a "foo.*"        */

hkey = ngx_hash_key(key.data, key.len);
res = ngx_hash_find_combined(&foo_hash, hkey, key.data, key.len);
```

<a id="memory-management"></a>

## Gerenciamento de memória

<a id="heap"></a>

### Heap

Para alocar memória do heap do sistema, use as seguintes funções:

* `ngx_alloc(size, log)` — Aloca memória do heap do sistema.
  Este é um wrapper em torno de `malloc()` com suporte a logging.
  Erros de alocação e informações de depuração são registrados em `log`.
* `ngx_calloc(size, log)` — Aloca memória do heap do sistema
  como `ngx_alloc()`, mas preenche a memória com zeros após
  a alocação.
* `ngx_memalign(alignment, size, log)` — Aloca memória alinhada
  do heap do sistema.
  Este é um wrapper em torno de `posix_memalign()`
  nas plataformas que fornecem essa função.
  Caso contrário, a implementação recorre a `ngx_alloc()` que
  fornece alinhamento máximo.
* `ngx_free(p)` — Libera memória alocada.
  Este é um wrapper em torno de `free()`.

<a id="pooling"></a>

### Pooling

A maioria das alocações do Angie são feitas em pools.
A memória alocada em um pool do Angie é liberada automaticamente quando o pool é
destruído.
Isso fornece boa performance de alocação e torna o controle de memória fácil.

Um pool aloca internamente objetos em blocos contínuos de memória.
Uma vez que um bloco está cheio, um novo é alocado e adicionado à lista de
blocos de memória do pool.
Quando a alocação solicitada é muito grande para caber em um bloco, a solicitação
é encaminhada para o alocador do sistema e o
ponteiro retornado é armazenado no pool para posterior desalocação.

O tipo para pools do Angie é `ngx_pool_t`.
As seguintes operações são suportadas:

* `ngx_create_pool(size, log)` — Cria um pool com tamanho de
  bloco especificado.
  O objeto pool retornado também é alocado no pool.
  O `size`
  deve ser pelo menos `NGX_MIN_POOL_SIZE`
  e um múltiplo de `NGX_POOL_ALIGNMENT`.
* `ngx_destroy_pool(pool)` — Libera toda a memória do pool, incluindo
  o próprio objeto pool.
* `ngx_palloc(pool, size)` — Aloca memória alinhada do
  pool especificado.
* `ngx_pcalloc(pool, size)` — Aloca memória alinhada
  do pool especificado e a preenche com zeros.
* `ngx_pnalloc(pool, size)` — Aloca memória não alinhada do
  pool especificado.
  Usado principalmente para alocar strings.
* `ngx_pfree(pool, p)` — Libera memória que foi previamente
  alocada no pool especificado.
  Apenas alocações que resultam de solicitações encaminhadas para o alocador do sistema
  podem ser liberadas.

```c
u_char      *p;
ngx_str_t   *s;
ngx_pool_t  *pool;

pool = ngx_create_pool(1024, log);
if (pool == NULL) { /* error */ }

s = ngx_palloc(pool, sizeof(ngx_str_t));
if (s == NULL) { /* error */ }
ngx_str_set(s, "foo");

p = ngx_pnalloc(pool, 3);
if (p == NULL) { /* error */ }
ngx_memcpy(p, "foo", 3);
```

Links de cadeia (`ngx_chain_t`) são ativamente usados no Angie,
então a implementação de pool do Angie fornece uma maneira de reutilizá-los.
O campo `chain` de `ngx_pool_t` mantém uma
lista de links previamente alocados prontos para reutilização.
Para alocação eficiente de um link de cadeia em um pool, use a
função `ngx_alloc_chain_link(pool)`.
Esta função procura por um link de cadeia livre na lista do pool e aloca um novo
link de cadeia se a lista do pool estiver vazia.
Para liberar um link, chame a função `ngx_free_chain(pool, cl)`.

Manipuladores de limpeza podem ser registrados em um pool.
Um manipulador de limpeza é um callback com um argumento que é chamado quando o pool é
destruído.
Um pool geralmente está vinculado a um objeto específico do Angie (como uma requisição HTTP) e é
destruído quando o objeto atinge o fim de seu tempo de vida.
Registrar uma limpeza de pool é uma maneira conveniente de liberar recursos, fechar
descritores de arquivo ou fazer ajustes finais nos dados compartilhados associados ao
objeto principal.

Para registrar uma limpeza de pool, chame
`ngx_pool_cleanup_add(pool, size)`, que retorna um
ponteiro `ngx_pool_cleanup_t` para
ser preenchido pelo chamador.
Use o argumento `size` para alocar contexto para o manipulador
de limpeza.

```c
ngx_pool_cleanup_t  *cln;

cln = ngx_pool_cleanup_add(pool, 0);
if (cln == NULL) { /* error */ }

cln->handler = ngx_my_cleanup;
cln->data = "foo";

...

static void
ngx_my_cleanup(void *data)
{
    u_char  *msg = data;

    ngx_do_smth(msg);
}
```

<a id="shared-memory"></a>

### Memória compartilhada

A memória compartilhada é usada pelo Angie para compartilhar dados comuns entre processos.
A função `ngx_shared_memory_add(cf, name, size, tag)` adiciona
uma nova entrada de memória compartilhada `ngx_shm_zone_t` a um ciclo.
A função recebe o `name` e `size`
da zona.
Cada zona compartilhada deve ter um nome único.
Se uma entrada de zona compartilhada com o `name` e
`tag` fornecidos já existe, a entrada de zona existente é reutilizada.
A função falha com um erro se uma entrada existente com o mesmo nome tem uma
tag diferente.
Geralmente, o endereço da estrutura do módulo é passado como
`tag`, tornando possível reutilizar zonas compartilhadas por nome dentro
de um módulo do Angie.

A estrutura de entrada de memória compartilhada `ngx_shm_zone_t` tem os
seguintes campos:

* `init` — Callback de inicialização, chamado após a zona compartilhada
  ser mapeada para memória real
* `data` — Contexto de dados, usado para passar dados arbitrários para o
  callback `init`
* `noreuse` — Flag que desabilita a reutilização de uma zona compartilhada do
  ciclo antigo
* `tag` — Tag da zona compartilhada
* `shm` — Objeto específico da plataforma do tipo
  `ngx_shm_t`, tendo pelo menos os seguintes campos:
  * `addr` — Endereço de memória compartilhada mapeada, inicialmente NULL
  * `size` — Tamanho da memória compartilhada
  * `name` — Nome da memória compartilhada
  * `log` — Log da memória compartilhada
  * `exists` — Flag que indica que a memória compartilhada foi herdada
    do processo mestre (específico do Windows)

As entradas de zona compartilhada são mapeadas para memória real em
`ngx_init_cycle()` após a configuração ser analisada.
Em sistemas POSIX, a syscall `mmap()` é usada para criar o
mapeamento anônimo compartilhado.
No Windows, o par `CreateFileMapping()`/
`MapViewOfFileEx()` é usado.

Para alocar em memória compartilhada, o Angie fornece o slab pool
do tipo `ngx_slab_pool_t`.
Um slab pool para alocar memória é automaticamente criado em cada zona compartilhada
do Angie.
O pool está localizado no início da zona compartilhada e pode ser acessado pela
expressão `(ngx_slab_pool_t *) shm_zone->shm.addr`.
Para alocar memória em uma zona compartilhada, chame
`ngx_slab_alloc(pool, size)` ou
`ngx_slab_calloc(pool, size)`.
Para liberar memória, chame `ngx_slab_free(pool, p)`.

O slab pool divide toda a zona compartilhada em páginas.
Cada página é usada para alocar objetos do mesmo tamanho.
O tamanho especificado deve ser uma potência de 2, e maior que o tamanho mínimo de
8 bytes.
Valores não conformes são arredondados para cima.
Uma máscara de bits para cada página rastreia quais blocos estão em uso e quais estão livres para
alocação.
Para tamanhos maiores que meia página (que geralmente é 2048 bytes), a alocação é
feita uma página inteira por vez.

Para proteger dados na memória compartilhada de acesso concorrente, use o mutex
disponível no campo `mutex` de
`ngx_slab_pool_t`.
Um mutex é mais comumente usado pelo slab pool ao alocar e liberar
memória, mas pode ser usado para proteger quaisquer outras estruturas de dados do usuário alocadas
na zona compartilhada.
Para bloquear ou desbloquear um mutex, chame
`ngx_shmtx_lock(&shpool->mutex)` ou
`ngx_shmtx_unlock(&shpool->mutex)` respectivamente.

```c
ngx_str_t        name;
ngx_foo_ctx_t   *ctx;
ngx_shm_zone_t  *shm_zone;

ngx_str_set(&name, "foo");

/* allocate shared zone context */
ctx = ngx_pcalloc(cf->pool, sizeof(ngx_foo_ctx_t));
if (ctx == NULL) {
    /* error */
}

/* add an entry for 64k shared zone */
shm_zone = ngx_shared_memory_add(cf, &name, 65536, &ngx_foo_module);
if (shm_zone == NULL) {
    /* error */
}

/* register init callback and context */
shm_zone->init = ngx_foo_init_zone;
shm_zone->data = ctx;


...


static ngx_int_t
ngx_foo_init_zone(ngx_shm_zone_t *shm_zone, void *data)
{
    ngx_foo_ctx_t  *octx = data;

    size_t            len;
    ngx_foo_ctx_t    *ctx;
    ngx_slab_pool_t  *shpool;

    value = shm_zone->data;

    if (octx) {
        /* reusing a shared zone from old cycle */
        ctx->value = octx->value;
        return NGX_OK;
    }

    shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;

    if (shm_zone->shm.exists) {
        /* initialize shared zone context in Windows Angie worker */
        ctx->value = shpool->data;
        return NGX_OK;
    }

    /* initialize shared zone */

    ctx->value = ngx_slab_alloc(shpool, sizeof(ngx_uint_t));
    if (ctx->value == NULL) {
        return NGX_ERROR;
    }

    shpool->data = ctx->value;

    return NGX_OK;
}
```

<a id="logging-1"></a>

### Registro de logs

Para registro de logs, o Angie usa objetos `ngx_log_t`.
O logger do Angie suporta vários tipos de saída:

* stderr — registro para erro padrão (stderr)
* file — registro para um arquivo
* syslog — registro para syslog
* memory — registro para armazenamento de memória interna para fins de desenvolvimento; a memória
  pode ser acessada posteriormente com um debugger

Uma instância de logger pode ser uma cadeia de loggers, vinculados uns aos outros com
o campo `next`.
Neste caso, cada mensagem é escrita para todos os loggers na cadeia.

Para cada logger, um nível de severidade controla quais mensagens são escritas no
log (apenas eventos atribuídos a esse nível ou superior são registrados).
Os seguintes níveis de severidade são suportados:

* `NGX_LOG_EMERG`
* `NGX_LOG_ALERT`
* `NGX_LOG_CRIT`
* `NGX_LOG_ERR`
* `NGX_LOG_WARN`
* `NGX_LOG_NOTICE`
* `NGX_LOG_INFO`
* `NGX_LOG_DEBUG`

Para registro de debug, a máscara de debug também é verificada.
As máscaras de debug são:

* `NGX_LOG_DEBUG_CORE`
* `NGX_LOG_DEBUG_ALLOC`
* `NGX_LOG_DEBUG_MUTEX`
* `NGX_LOG_DEBUG_EVENT`
* `NGX_LOG_DEBUG_HTTP`
* `NGX_LOG_DEBUG_MAIL`
* `NGX_LOG_DEBUG_STREAM`

Normalmente, os loggers são criados pelo código existente do Angie a partir de
diretivas `error_log` e estão disponíveis em quase todas as etapas
de processamento em ciclo, configuração, conexão do cliente e outros objetos.

O Angie fornece as seguintes macros de registro:

* `ngx_log_error(level, log, err, fmt, ...)` — registro de erro
* `ngx_log_debug0(level, log, err, fmt)`,
  `ngx_log_debug1(level, log, err, fmt, arg1)` etc. — registro de
  debug com até oito argumentos de formatação suportados

Uma mensagem de log é formatada em um buffer de tamanho
`NGX_MAX_ERROR_STR` (atualmente, 2048 bytes) na pilha.
A mensagem é precedida pelo nível de severidade, ID do processo (PID), ID da conexão
(armazenado em `log->connection`), e o texto de erro do sistema.
Para mensagens não-debug, `log->handler` também é chamado para
preceder informações mais específicas à mensagem de log.
O módulo HTTP define a função `ngx_http_log_error()` como manipulador de log
para registrar endereços do cliente e servidor, ação atual (armazenada em
`log->action`), linha de requisição do cliente, nome do servidor, etc.

```c
/* specify what is currently done */
log->action = "sending mp4 to client";

/* error and debug log */
ngx_log_error(NGX_LOG_INFO, c->log, 0, "client prematurely
              closed connection");

ngx_log_debug2(NGX_LOG_DEBUG_HTTP, mp4->file.log, 0,
               "mp4 start:%ui, length:%ui", mp4->start, mp4->length);
```

O exemplo acima resulta em entradas de log como estas:

```text
2016/09/16 22:08:52 [info] 17445#0: *1 client prematurely closed connection while
sending mp4 to client, client: 127.0.0.1, server: , request: "GET /file.mp4 HTTP/1.1"
2016/09/16 23:28:33 [debug] 22140#0: *1 mp4 start:0, length:10000
```

<a id="cycles"></a>

### Ciclos

Um objeto de ciclo armazena o contexto de execução do Angie criado a partir de uma
configuração específica.
Seu tipo é `ngx_cycle_t`.
O ciclo atual é referenciado pela variável global `ngx_cycle`
e herdado pelos workers do Angie quando eles iniciam.
Cada vez que a configuração do Angie é recarregada, um novo ciclo é criado a partir da
nova configuração do Angie; o ciclo antigo é normalmente excluído após o novo ser
criado com sucesso.

Um ciclo é criado pela função `ngx_init_cycle()`, que
recebe o ciclo anterior como argumento.
A função localiza o arquivo de configuração do ciclo anterior e herda o máximo
de recursos possível do ciclo anterior.
Um ciclo placeholder chamado "init cycle" é criado na inicialização do Angie, e então é
substituído por um ciclo real construído a partir da configuração.

Os membros do ciclo incluem:

* `pool` — Pool do ciclo.
  Criado para cada novo ciclo.
* `log` — Log do ciclo.
  Inicialmente herdado do ciclo antigo, é definido para apontar para
  `new_log` após a configuração ser lida.
* `new_log` — Log do ciclo, criado pela configuração.
  É afetado pela diretiva `error_log` de escopo raiz.
* `connections`, `connection_n` —
  Array de conexões do tipo `ngx_connection_t`, criado pelo
  módulo de eventos durante a inicialização de cada worker do Angie.
  A diretiva `worker_connections` na configuração do Angie
  define o número de conexões `connection_n`.
* `free_connections`,
  `free_connection_n` — Lista e número de conexões atualmente disponíveis.
  Se não há conexões disponíveis, um worker do Angie recusa aceitar novos clientes
  ou conectar a servidores upstream.
* `files`, `files_n` — Array para mapear descritores
  de arquivo para conexões do Angie.
  Este mapeamento é usado pelos módulos de eventos que têm a
  flag `NGX_USE_FD_EVENT` (atualmente, são
  `poll` e `devpoll`).
* `conf_ctx` — Array de configurações de módulos principais.
  As configurações são criadas e preenchidas durante a leitura dos arquivos de configuração
  do Angie.
* `modules`, `modules_n` — Array de módulos
  do tipo `ngx_module_t`, tanto estáticos quanto dinâmicos, carregados pela
  configuração atual.
* `listening` — Array de objetos de escuta do tipo
  `ngx_listening_t`.
  Objetos de escuta são normalmente adicionados pela diretiva `listen`
  de diferentes módulos que chamam a função
  `ngx_create_listening()`.
  Sockets de escuta são criados com base nos objetos de escuta.
* `paths` — Array de caminhos do tipo `ngx_path_t`.
  Caminhos são adicionados chamando a função `ngx_add_path()` de
  módulos que vão operar em determinados diretórios.
  Estes diretórios são criados pelo Angie após ler a configuração, se estiverem ausentes.
  Além disso, dois manipuladores podem ser adicionados para cada caminho:
  * path loader — Executa apenas uma vez em 60 segundos após iniciar ou recarregar
    o Angie.
    Normalmente, o loader lê o diretório e armazena dados na memória compartilhada
    do Angie.
    O manipulador é chamado do processo dedicado do Angie "cache loader".
  * path manager — Executa periodicamente.
    Normalmente, o manager remove arquivos antigos do diretório e atualiza a
    memória do Angie para refletir as mudanças.
    O manipulador é chamado do processo dedicado "cache manager".
* `open_files` — Lista de objetos de arquivo aberto do tipo
  `ngx_open_file_t`, que são criados chamando a função
  `ngx_conf_open_file()`.
  Atualmente, o Angie usa este tipo de arquivos abertos para logging.
  Após ler a configuração, o Angie abre todos os arquivos na
  lista `open_files` e armazena cada descritor de arquivo no
  campo `fd` do objeto.
  Os arquivos são abertos em modo de anexação e são criados se estiverem ausentes.
  Os arquivos na lista são reabertos pelos workers do Angie ao receber o
  sinal de reabertura (mais frequentemente `USR1`).
  Neste caso o descritor no campo `fd` é alterado para um
  novo valor.
* `shared_memory` — Lista de zonas de memória compartilhada, cada uma adicionada
  chamando a função `ngx_shared_memory_add()`.
  Zonas compartilhadas são mapeadas para a mesma faixa de endereços em todos os processos do Angie e
  são usadas para compartilhar dados comuns, por exemplo a árvore em memória do cache HTTP.

<a id="buffer"></a>

### Buffer

Para operações de entrada/saída, o Angie fornece o tipo de buffer
`ngx_buf_t`.
Normalmente, é usado para armazenar dados a serem escritos em um destino ou lidos de uma
fonte.
Um buffer pode referenciar dados na memória ou em um arquivo e é tecnicamente
possível para um buffer referenciar ambos ao mesmo tempo.
A memória para o buffer é alocada separadamente e não está relacionada à estrutura
do buffer `ngx_buf_t`.

A estrutura `ngx_buf_t` tem os seguintes campos:

* `start`, `end` — Os limites do bloco de memória
  alocado para o buffer.
* `pos`, `last` — Os limites do buffer de memória;
  normalmente um subintervalo de `start` ..
  `end`.
* `file_pos`, `file_last` — Os limites de um
  buffer de arquivo, expressos como deslocamentos do início do arquivo.
* `tag` — Valor único usado para distinguir buffers; criado por
  diferentes módulos do Angie, normalmente para fins de reutilização de buffer.
* `file` — Objeto de arquivo.
* `temporary` — Flag indicando que o buffer referencia
  memória gravável.
* `memory` — Flag indicando que o buffer referencia memória
  somente leitura.
* `in_file` — Flag indicando que o buffer referencia dados
  em um arquivo.
* `flush` — Flag indicando que todos os dados anteriores ao buffer
  precisam ser liberados.
* `recycled` — Flag indicando que o buffer pode ser reutilizado e
  precisa ser consumido o mais rápido possível.
* `sync` — Flag indicando que o buffer não carrega dados ou
  sinal especial como `flush` ou `last_buf`.
  Por padrão o Angie considera tais buffers uma condição de erro, mas esta flag diz
  ao Angie para pular a verificação de erro.
* `last_buf` — Flag indicando que o buffer é o último na
  saída.
* `last_in_chain` — Flag indicando que não há mais buffers de dados
  em uma requisição ou sub-requisição.
* `shadow` — Referência a outro buffer ("sombra") relacionado ao
  buffer atual, normalmente no sentido de que o buffer usa dados da
  sombra.
  Quando o buffer é consumido, o buffer sombra é normalmente também marcado como
  consumido.
* `last_shadow` — Flag indicando que o buffer é o último
  que referencia um buffer sombra específico.
* `temp_file` — Flag indicando que o buffer está em um arquivo
  temporário.

Para operações de entrada e saída os buffers são ligados em cadeias.
Uma cadeia é uma sequência de links de cadeia do tipo `ngx_chain_t`,
definida como segue:

```c
typedef struct ngx_chain_s  ngx_chain_t;

struct ngx_chain_s {
    ngx_buf_t    *buf;
    ngx_chain_t  *next;
};
```

Cada link de cadeia mantém uma referência ao seu buffer e uma referência ao próximo
link de cadeia.

Um exemplo de uso de buffers e cadeias:

```c
ngx_chain_t *
ngx_get_my_chain(ngx_pool_t *pool)
{
    ngx_buf_t    *b;
    ngx_chain_t  *out, *cl, **ll;

    /* first buf */
    cl = ngx_alloc_chain_link(pool);
    if (cl == NULL) { /* error */ }

    b = ngx_calloc_buf(pool);
    if (b == NULL) { /* error */ }

    b->start = (u_char *) "foo";
    b->pos = b->start;
    b->end = b->start + 3;
    b->last = b->end;
    b->memory = 1; /* read-only memory */

    cl->buf = b;
    out = cl;
    ll = &cl->next;

    /* second buf */
    cl = ngx_alloc_chain_link(pool);
    if (cl == NULL) { /* error */ }

    b = ngx_create_temp_buf(pool, 3);
    if (b == NULL) { /* error */ }

    b->last = ngx_cpymem(b->last, "foo", 3);

    cl->buf = b;
    cl->next = NULL;
    *ll = cl;

    return out;
}
```

<a id="networking"></a>

## Rede

<a id="connections"></a>

### Conexões

O tipo de conexão `ngx_connection_t` é um wrapper em torno de um
descritor de socket.
Ele inclui os seguintes campos:

* `fd` — Descritor de socket
* `data` — Contexto de conexão arbitrário.
  Normalmente, é um ponteiro para um objeto de nível superior construído sobre a
  conexão, como uma requisição HTTP ou uma sessão Stream.
* `read`, `write` — Eventos de leitura e escrita para
  a conexão.
* `recv`, `send`,
  `recv_chain`, `send_chain` — Operações de I/O
  para a conexão.
* `pool` — Pool da conexão.
* `log` — Log da conexão.
* `sockaddr`, `socklen`,
  `addr_text` — Endereço do socket remoto em formas binária e texto.
* `local_sockaddr`, `local_socklen` — Endereço
  do socket local em forma binária.
  Inicialmente, esses campos estão vazios.
  Use a função `ngx_connection_local_sockaddr()` para obter o
  endereço do socket local.
* `proxy_protocol_addr`, `proxy_protocol_port`
  — Endereço e porta do cliente do protocolo PROXY, se o protocolo PROXY estiver habilitado para
  a conexão.
* `ssl` — Contexto SSL para a conexão.
* `reusable` — Flag indicando que a conexão está em um estado que
  a torna elegível para reutilização.
* `close` — Flag indicando que a conexão está sendo reutilizada
  e precisa ser fechada.

Uma conexão Angie pode encapsular transparentemente a camada SSL.
Neste caso, o campo `ssl` da conexão mantém um ponteiro para uma
estrutura `ngx_ssl_connection_t`, mantendo todos os dados
relacionados ao SSL para a conexão, incluindo `SSL_CTX` e
`SSL`.
Os manipuladores `recv`, `send`,
`recv_chain` e `send_chain` também são
definidos para funções habilitadas para SSL.

A diretiva `worker_connections` na configuração do Angie
limita o número de conexões por worker do Angie.
Todas as estruturas de conexão são pré-criadas quando um worker inicia e armazenadas no
campo `connections` do objeto cycle.
Para recuperar uma estrutura de conexão, use a
função `ngx_get_connection(s, log)`.
Ela recebe como argumento `s` um descritor de socket, que precisa
ser envolvido em uma estrutura de conexão.

Como o número de conexões por worker é limitado, o Angie fornece uma
maneira de capturar conexões que estão atualmente em uso.
Para habilitar ou desabilitar a reutilização de uma conexão, chame a
função `ngx_reusable_connection(c, reusable)`.
Chamar `ngx_reusable_connection(c, 1)` define a
flag `reuse` na estrutura de conexão e insere a
conexão na `reusable_connections_queue` do cycle.
Sempre que `ngx_get_connection()` descobre que não há
conexões disponíveis na lista `free_connections` do cycle,
ela chama `ngx_drain_connections()` para liberar um
número específico de conexões reutilizáveis.
Para cada conexão desse tipo, a flag `close` é definida e seu manipulador de leitura
é chamado, que deve liberar a conexão chamando
`ngx_close_connection(c)` e torná-la disponível para reutilização.
Para sair do estado quando uma conexão pode ser reutilizada,
`ngx_reusable_connection(c, 0)` é chamada.
Conexões de cliente HTTP são um exemplo de conexões reutilizáveis no Angie; elas
são marcadas como reutilizáveis até que o primeiro byte de requisição seja recebido do cliente.

<a id="events-1"></a>

## Eventos

<a id="event"></a>

### Evento

O objeto de evento `ngx_event_t` no Angie fornece um mecanismo
para notificação de que um evento específico ocorreu.

Os campos em `ngx_event_t` incluem:

* `data` — Contexto de evento arbitrário usado em manipuladores de eventos,
  geralmente como ponteiro para uma conexão relacionada ao evento.
* `handler` — Função de callback a ser invocada quando o evento
  acontece.
* `write` — Flag indicando um evento de escrita.
  A ausência da flag indica um evento de leitura.
* `active` — Flag indicando que o evento está registrado para
  receber notificações de I/O, normalmente de mecanismos de notificação como
  `epoll`, `kqueue`, `poll`.
* `ready` — Flag indicando que o evento recebeu uma
  notificação de I/O.
* `delayed` — Flag indicando que o I/O está atrasado devido à limitação de taxa.
* `timer` — Nó da árvore rubro-negra para inserir o evento na
  árvore de timer.
* `timer_set` — Flag indicando que o timer do evento está definido e
  ainda não expirou.
* `timedout` — Flag indicando que o timer do evento expirou.
* `eof` — Flag indicando que EOF ocorreu durante a leitura de dados.
* `pending_eof` — Flag indicando que EOF está pendente no
  socket, mesmo que possa haver alguns dados disponíveis antes dele.
  A flag é entregue via o evento `EPOLLRDHUP`
  `epoll` ou
  flag `EV_EOF` `kqueue`.
* `error` — Flag indicando que um erro ocorreu durante
  a leitura (para um evento de leitura) ou escrita (para um evento de escrita).
* `cancelable` — Flag de evento de timer indicando que o evento
  deve ser ignorado durante o desligamento do worker.
  O desligamento gracioso do worker é atrasado até que não haja eventos de timer não canceláveis
  agendados.
* `posted` — Flag indicando que o evento está postado em uma fila.
* `queue` — Nó da fila para postar o evento em uma fila.

<a id="i-o-events"></a>

### Eventos de I/O

Cada conexão obtida chamando a função `ngx_get_connection()`
tem dois eventos anexados, `c->read` e
`c->write`, que são usados para receber notificação de que o
socket está pronto para leitura ou escrita.
Todos esses eventos operam no modo Edge-Triggered, significando que eles apenas disparam
notificações quando o estado do socket muda.
Por exemplo, fazer uma leitura parcial em um socket não faz o Angie entregar uma
notificação de leitura repetida até que mais dados cheguem no socket.
Mesmo quando o mecanismo de notificação de I/O subjacente é essencialmente
Level-Triggered (`poll`, `select` etc), o Angie
converte as notificações para Edge-Triggered.
Para tornar as notificações de eventos do Angie consistentes em todos os sistemas de notificação
em diferentes plataformas, as funções
`ngx_handle_read_event(rev, flags)` e
`ngx_handle_write_event(wev, lowat)` devem ser chamadas após
manipular uma notificação de socket de I/O ou chamar qualquer função de I/O nesse socket.
Normalmente, as funções são chamadas uma vez no final de cada manipulador de evento de leitura ou escrita.

<a id="timer-events"></a>

### Eventos de timer

Um evento pode ser definido para enviar uma notificação quando um timeout expira.
O timer usado pelos eventos conta milissegundos desde algum ponto não especificado
no passado truncado para o tipo `ngx_msec_t`.
Seu valor atual pode ser obtido da variável `ngx_current_msec`.

A função `ngx_add_timer(ev, timer)` define um timeout para um
evento, `ngx_del_timer(ev)` exclui um timeout previamente definido.
A árvore rubro-negra global de timeout `ngx_event_timer_rbtree`
armazena todos os timeouts atualmente definidos.
A chave na árvore é do tipo `ngx_msec_t` e é o tempo
quando o evento ocorre.
A estrutura da árvore permite operações rápidas de inserção e exclusão, bem como
acesso aos timeouts mais próximos, que o Angie usa para descobrir quanto tempo esperar
por eventos de I/O e para expirar eventos de timeout.

<a id="posted-events"></a>

### Eventos postados

Um evento pode ser postado, o que significa que seu manipulador será chamado em algum
ponto posterior dentro da iteração atual do loop de eventos.
Postar eventos é uma boa prática para simplificar código e escapar de estouros de pilha.
Eventos postados são mantidos em uma fila de postagem.
A macro `ngx_post_event(ev, q)` posta o evento
`ev` na fila de postagem `q`.
A macro `ngx_delete_posted_event(ev)` exclui o evento
`ev` da fila em que está atualmente postado.
Normalmente, eventos são postados na fila `ngx_posted_events`,
que é processada tarde no loop de eventos — após todos os eventos de I/O e timer
já terem sido manipulados.
A função `ngx_event_process_posted()` é chamada para processar
uma fila de eventos.
Ela chama manipuladores de eventos até que a fila esteja vazia.
Isso significa que um manipulador de evento postado pode postar mais eventos para serem processados
dentro da iteração atual do loop de eventos.

Um exemplo:

```c
void
ngx_my_connection_read(ngx_connection_t *c)
{
    ngx_event_t  *rev;

    rev = c->read;

    ngx_add_timer(rev, 1000);

    rev->handler = ngx_my_read_handler;

    ngx_my_read(rev);
}


void
ngx_my_read_handler(ngx_event_t *rev)
{
    ssize_t            n;
    ngx_connection_t  *c;
    u_char             buf[256];

    if (rev->timedout) { /* timeout expired */ }

    c = rev->data;

    while (rev->ready) {
        n = c->recv(c, buf, sizeof(buf));

        if (n == NGX_AGAIN) {
            break;
        }

        if (n == NGX_ERROR) { /* error */ }

        /* process buf */
    }

    if (ngx_handle_read_event(rev, 0) != NGX_OK) { /* error */ }
}
```

<a id="event-loop"></a>

### Loop de eventos

Exceto pelo processo master do Angie, todos os processos do Angie fazem I/O e, portanto, têm um
loop de eventos.
(O processo master do Angie, em vez disso, passa a maior parte do tempo na
chamada `sigsuspend()` aguardando a chegada de sinais.)
O loop de eventos do Angie é implementado na
função `ngx_process_events_and_timers()`, que é chamada
repetidamente até que o processo termine.

O loop de eventos tem os seguintes estágios:

* Encontrar o timeout que está mais próximo de expirar, chamando
  `ngx_event_find_timer()`.
  Esta função encontra o nó mais à esquerda na árvore de timers e retorna o
  número de milissegundos até que o nó expire.
* Processar eventos de I/O chamando um manipulador, específico para o mecanismo de notificação
  de eventos, escolhido pela configuração do Angie.
  Este manipulador aguarda que pelo menos um evento de I/O aconteça, mas apenas até que o próximo
  timeout expire.
  Quando um evento de leitura ou escrita ocorre, a flag `ready`
  é definida e o manipulador do evento é chamado.
  Para Linux, o manipulador `ngx_epoll_process_events()`
  é normalmente usado, que chama `epoll_wait()` para aguardar eventos de I/O.
* Expirar timers chamando `ngx_event_expire_timers()`.
  A árvore de timers é iterada do elemento mais à esquerda para a direita até que um
  timeout não expirado seja encontrado.
  Para cada nó expirado, a flag de evento `timedout` é definida,
  a flag `timer_set` é resetada, e o manipulador de evento é chamado.
* Processar eventos postados chamando `ngx_event_process_posted()`.
  A função remove repetidamente o primeiro elemento da fila de eventos
  postados e chama o manipulador do elemento, até que a fila esteja vazia.

Todos os processos do Angie também manipulam sinais.
Os manipuladores de sinais apenas definem variáveis globais que são verificadas após a
chamada `ngx_process_events_and_timers()`.

<a id="processes"></a>

### Processos

Existem vários tipos de processos no Angie.
O tipo de um processo é mantido na variável global `ngx_process`
e é um dos seguintes:

* `NGX_PROCESS_MASTER` — O processo master, que lê a
  configuração do Angie, cria ciclos e inicia e controla processos filhos.
  Ele não executa nenhum I/O e responde apenas a sinais.
  Sua função de ciclo é `ngx_master_process_cycle()`.
* `NGX_PROCESS_WORKER` — O processo worker, que manipula conexões
  de clientes.
  Ele é iniciado pelo processo master e responde aos seus sinais e comandos
  de canal também.
  Sua função de ciclo é `ngx_worker_process_cycle()`.
  Pode haver múltiplos processos worker, conforme configurado pela
  diretiva `worker_processes`.
* `NGX_PROCESS_SINGLE` — O processo único, que existe apenas no
  modo `master_process off` e é o único processo executando
  nesse modo.
  Ele cria ciclos (como o processo master faz) e manipula conexões de clientes
  (como o processo worker faz).
  Sua função de ciclo é `ngx_single_process_cycle()`.
* `NGX_PROCESS_HELPER` — O processo auxiliar, do qual atualmente
  existem dois tipos: gerenciador de cache e carregador de cache.
  A função de ciclo para ambos é
  `ngx_cache_manager_process_cycle()`.

Os processos do Angie manipulam os seguintes sinais:

* `NGX_SHUTDOWN_SIGNAL` (`SIGQUIT` na maioria dos
  sistemas) — Desligamento gracioso.
  Ao receber este sinal, o processo master envia um sinal de desligamento para todos
  os processos filhos.
  Quando não restam processos filhos, o master destrói o pool de ciclo e sai.
  Quando um processo worker recebe este sinal, ele fecha todos os sockets de escuta e
  aguarda até que não haja eventos não canceláveis agendados, então destrói o
  pool de ciclo e sai.
  Quando o gerenciador de cache ou o processo carregador de cache recebe este sinal, ele
  sai imediatamente.
  A variável `ngx_quit` é definida como `1` quando um
  processo recebe este sinal e é imediatamente resetada após ser processada.
  A variável `ngx_exiting` é definida como `1` enquanto
  um processo worker está no estado de desligamento.
* `NGX_TERMINATE_SIGNAL` (`SIGTERM` na maioria dos
  sistemas) — Terminar.
  Ao receber este sinal, o processo master envia um sinal de terminação para todos
  os processos filhos.
  Se um processo filho não sair dentro de 1 segundo, o processo master envia o
  sinal `SIGKILL` para matá-lo.
  Quando não restam processos filhos, o processo master destrói o pool de ciclo e
  sai.
  Quando um processo worker, o processo gerenciador de cache ou o processo carregador de cache
  recebe este sinal, ele destrói o pool de ciclo e sai.
  A variável `ngx_terminate` é definida como `1`
  quando este sinal é recebido.
* `NGX_NOACCEPT_SIGNAL` (`SIGWINCH` na maioria dos
  sistemas) — Desligar todos os processos worker e auxiliares.
  Ao receber este sinal, o processo master desliga seus processos filhos.
  Se um binário do Angie novo iniciado anteriormente sair, os processos filhos do
  master antigo são iniciados novamente.
  Quando um processo worker recebe este sinal, ele desliga no modo de debug
  definido pela diretiva `debug_points`.
* `NGX_RECONFIGURE_SIGNAL` (`SIGHUP` na maioria dos
  sistemas) — Reconfigurar.
  Ao receber este sinal, o processo master relê a configuração e
  cria um novo ciclo baseado nela.
  Se o novo ciclo for criado com sucesso, o ciclo antigo é deletado e novos
  processos filhos são iniciados.
  Enquanto isso, os processos filhos antigos recebem o
  sinal `NGX_SHUTDOWN_SIGNAL`.
  No modo de processo único, o Angie cria um novo ciclo, mas mantém o antigo até
  que não haja mais clientes com conexões ativas vinculadas a ele.
  Os processos worker e auxiliares ignoram este sinal.
* `NGX_REOPEN_SIGNAL` (`SIGUSR1` na maioria dos
  sistemas) — Reabrir arquivos.
  O processo master envia este sinal para os workers, que reabrem todos os
  `open_files` relacionados ao ciclo.
* `NGX_CHANGEBIN_SIGNAL` (`SIGUSR2` na maioria dos
  sistemas) — Alterar o binário do Angie.
  O processo master inicia um novo binário do Angie e passa uma lista de todos os sockets
  de escuta.
  A lista em formato texto, passada na variável de ambiente `"NGINX"`,
  consiste em números de descritores separados por ponto e vírgula.
  O novo binário do Angie lê a variável `"NGINX"` e adiciona os
  sockets ao seu ciclo de inicialização.
  Outros processos ignoram este sinal.

Embora todos os processos worker do Angie sejam capazes de receber e manipular adequadamente sinais
POSIX, o processo master não usa a chamada de sistema `kill()`
padrão para passar sinais para workers e auxiliares.
Em vez disso, o Angie usa pares de sockets entre processos que permitem enviar mensagens
entre todos os processos do Angie.
Atualmente, no entanto, as mensagens são enviadas apenas do master para seus filhos.
As mensagens carregam os sinais padrão.

<a id="threading"></a>

### Threading

É possível descarregar para uma thread separada tarefas que de outra forma
bloqueariam o processo worker do Angie.
Por exemplo, o Angie pode ser configurado para usar threads para executar
[I/O de arquivo](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#aio).
Outro caso de uso é uma biblioteca que não tem interface assíncrona
e, portanto, não pode ser normalmente usada com o Angie.
Tenha em mente que a interface de threads é um auxiliar para a abordagem
assíncrona existente para processar conexões de clientes e de forma alguma
pretende ser um substituto.

Para lidar com sincronização, os seguintes wrappers sobre
primitivos `pthreads` estão disponíveis:

* `typedef pthread_mutex_t  ngx_thread_mutex_t;`
  * `ngx_int_t
    ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log);`
* `typedef pthread_cond_t  ngx_thread_cond_t;`
  * `ngx_int_t
    ngx_thread_cond_create(ngx_thread_cond_t *cond, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_cond_destroy(ngx_thread_cond_t *cond, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_cond_signal(ngx_thread_cond_t *cond, ngx_log_t *log);`
  * `ngx_int_t
    ngx_thread_cond_wait(ngx_thread_cond_t *cond, ngx_thread_mutex_t *mtx,
    ngx_log_t *log);`

Em vez de criar uma nova thread para cada tarefa, o Angie implementa
uma estratégia de [thread_pool](https://pt.angie.software//angie/docs/configuration/modules/core.md#thread-pool).
Múltiplos pools de threads podem ser configurados para diferentes propósitos
(por exemplo, executar I/O em diferentes conjuntos de discos).
Cada pool de threads é criado na inicialização e contém um número limitado de threads
que processam uma fila de tarefas.
Quando uma tarefa é concluída, um manipulador de conclusão predefinido é chamado.

O arquivo de cabeçalho `src/core/ngx_thread_pool.h` contém
definições relevantes:

```c
struct ngx_thread_task_s {
    ngx_thread_task_t   *next;
    ngx_uint_t           id;
    void                *ctx;
    void               (*handler)(void *data, ngx_log_t *log);
    ngx_event_t          event;
};

typedef struct ngx_thread_pool_s  ngx_thread_pool_t;

ngx_thread_pool_t *ngx_thread_pool_add(ngx_conf_t *cf, ngx_str_t *name);
ngx_thread_pool_t *ngx_thread_pool_get(ngx_cycle_t *cycle, ngx_str_t *name);

ngx_thread_task_t *ngx_thread_task_alloc(ngx_pool_t *pool, size_t size);
ngx_int_t ngx_thread_task_post(ngx_thread_pool_t *tp, ngx_thread_task_t *task);
```

No momento da configuração, um módulo que deseja usar threads deve obter uma
referência para um pool de threads chamando
`ngx_thread_pool_add(cf, name)`, que ou cria um
novo pool de threads com o `name` fornecido ou retorna uma referência
para o pool com esse nome se ele já existir.

Para adicionar uma `task` em uma fila de um pool de threads especificado
`tp` em tempo de execução, use a
função `ngx_thread_task_post(tp, task)`.

Para executar uma função em uma thread, passe parâmetros e configure um
manipulador de conclusão usando a estrutura `ngx_thread_task_t`:

```c
typedef struct {
    int    foo;
} my_thread_ctx_t;


static void
my_thread_func(void *data, ngx_log_t *log)
{
    my_thread_ctx_t *ctx = data;

    /* esta função é executada em uma thread separada */
}


static void
my_thread_completion(ngx_event_t *ev)
{
    my_thread_ctx_t *ctx = ev->data;

    /* executada no loop de eventos do Angie */
}


ngx_int_t
my_task_offload(my_conf_t *conf)
{
    my_thread_ctx_t    *ctx;
    ngx_thread_task_t  *task;

    task = ngx_thread_task_alloc(conf->pool, sizeof(my_thread_ctx_t));
    if (task == NULL) {
        return NGX_ERROR;
    }

    ctx = task->ctx;

    ctx->foo = 42;

    task->handler = my_thread_func;
    task->event.handler = my_thread_completion;
    task->event.data = ctx;

    if (ngx_thread_task_post(conf->thread_pool, task) != NGX_OK) {
        return NGX_ERROR;
    }

    return NGX_OK;
}
```

<a id="modules-1"></a>

## Módulos

<a id="adding-new-modules"></a>

### Adicionando novos módulos

Cada módulo Angie independente reside em um diretório separado que contém
pelo menos dois arquivos:
`config` e um arquivo com o código-fonte do módulo.
O arquivo `config` contém todas as informações necessárias para o Angie
integrar o módulo, por exemplo:

```bash
ngx_module_type=CORE
ngx_module_name=ngx_foo_module
ngx_module_srcs="$ngx_addon_dir/ngx_foo_module.c"

. auto/module

ngx_addon_name=$ngx_module_name
```

O arquivo `config` é um script shell POSIX que pode definir
e acessar as seguintes variáveis:

* `ngx_module_type` — Tipo de módulo a ser construído.
  Os valores possíveis são `CORE`, `HTTP`,
  `HTTP_FILTER`, `HTTP_INIT_FILTER`,
  `HTTP_AUX_FILTER`, `MAIL`,
  `STREAM` ou `MISC`.
* `ngx_module_name` — Nomes dos módulos.
  Para construir múltiplos módulos a partir de um conjunto de arquivos-fonte, especifique uma
  lista de nomes separados por espaços em branco.
  O primeiro nome indica o nome do binário de saída para o módulo dinâmico.
  Os nomes na lista devem corresponder aos nomes usados no código-fonte.
* `ngx_addon_name` — Nome do módulo como aparece na saída
  no console do script de configuração.
* `ngx_module_srcs` — Lista separada por espaços em branco de arquivos-fonte
  usados para compilar o módulo.
  A variável `$ngx_addon_dir` pode ser usada para representar o caminho
  para o diretório do módulo.
* `ngx_module_incs` — Caminhos de inclusão necessários para construir o módulo
* `ngx_module_deps` — Lista separada por espaços em branco das
  dependências do módulo.
  Geralmente, é a lista de arquivos de cabeçalho.
* `ngx_module_libs` — Lista separada por espaços em branco de bibliotecas para
  vincular com o módulo.
  Por exemplo, use `ngx_module_libs=-lpthread` para vincular
  a biblioteca `libpthread`.
  As seguintes macros podem ser usadas para vincular às mesmas bibliotecas que o
  Angie:
  `LIBXSLT`, `LIBGD`, `GEOIP`,
  `PCRE`, `OPENSSL`, `MD5`,
  `SHA1`, `ZLIB` e `PERL`.
* `ngx_module_link` — Variável definida pelo sistema de construção para
  `DYNAMIC` para um módulo dinâmico ou `ADDON`
  para um módulo estático e usada para determinar diferentes ações a serem executadas
  dependendo do tipo de vinculação.
* `ngx_module_order` — Ordem de carregamento para o módulo;
  útil para os tipos de módulo `HTTP_FILTER` e
  `HTTP_AUX_FILTER`.
  O formato para esta opção é uma lista separada por espaços em branco de módulos.
  Todos os módulos na lista seguindo o nome do módulo atual ficam depois dele na
  lista global de módulos, que define a ordem para inicialização dos módulos.
  Para módulos de filtro, inicialização posterior significa execução anterior.

  Os seguintes módulos são tipicamente usados como referências.
  O `ngx_http_copy_filter_module` lê os dados para outros
  módulos de filtro e é colocado próximo ao final da lista para que seja um dos
  primeiros a ser executado.
  O `ngx_http_write_filter_module` escreve os dados para o
  socket do cliente e é colocado próximo ao topo da lista, sendo o último a ser
  executado.

  Por padrão, módulos de filtro são colocados antes do
  `ngx_http_copy_filter` na lista de módulos para que o
  manipulador de filtro seja executado após o manipulador do filtro de cópia.
  Para outros tipos de módulo, o padrão é a string vazia.

Para compilar um módulo no Angie estaticamente, use o
argumento `--add-module=/path/to/module` para o script
de configuração.
Para compilar um módulo para carregamento dinâmico posterior no Angie, use o
argumento `--add-dynamic-module=/path/to/module`.

<a id="core-modules"></a>

### Módulos principais

Módulos são os blocos de construção do Angie, e a maior parte de sua funcionalidade é
implementada como módulos.
O arquivo-fonte do módulo deve conter uma variável global do tipo
`ngx_module_t`, que é definida da seguinte forma:

```c
struct ngx_module_s {

    /* parte privada é omitida */

    void                 *ctx;
    ngx_command_t        *commands;
    ngx_uint_t            type;

    ngx_int_t           (*init_master)(ngx_log_t *log);

    ngx_int_t           (*init_module)(ngx_cycle_t *cycle);

    ngx_int_t           (*init_process)(ngx_cycle_t *cycle);
    ngx_int_t           (*init_thread)(ngx_cycle_t *cycle);
    void                (*exit_thread)(ngx_cycle_t *cycle);
    void                (*exit_process)(ngx_cycle_t *cycle);

    void                (*exit_master)(ngx_cycle_t *cycle);

    /* stubs para extensões futuras são omitidos */
};
```

A parte privada omitida inclui a versão do módulo e uma assinatura e é
preenchida usando a macro predefinida `NGX_MODULE_V1`.

Cada módulo mantém seus dados privados no campo `ctx`,
reconhece as diretivas de configuração, especificadas no
array `commands`, e pode ser invocado em certas etapas do
ciclo de vida do Angie.
O ciclo de vida do módulo consiste nos seguintes eventos:

* Manipuladores de diretivas de configuração são chamados conforme aparecem
  nos arquivos de configuração no contexto do processo mestre.
* Após a configuração ser analisada com sucesso, o manipulador `init_module`
  é chamado no contexto do processo mestre.
  O manipulador `init_module` é chamado no processo mestre cada
  vez que uma configuração é carregada.
* O processo mestre cria um ou mais processos worker e o
  manipulador `init_process` é chamado em cada um deles.
* Quando um processo worker recebe o comando de desligamento ou término do
  mestre, ele invoca o manipulador `exit_process`.
* O processo mestre chama o manipulador `exit_master` antes
  de sair.

Como threads são usadas no Angie apenas como uma facilidade de E/S suplementar com sua
própria API, os manipuladores `init_thread` e `exit_thread`
não são chamados atualmente.
Também não há manipulador `init_master`, porque seria
sobrecarga desnecessária.

O `type` do módulo define exatamente o que é armazenado no
campo `ctx`.
Seu valor é um dos seguintes tipos:

* `NGX_CORE_MODULE`
* `NGX_EVENT_MODULE`
* `NGX_HTTP_MODULE`
* `NGX_MAIL_MODULE`
* `NGX_STREAM_MODULE`

O `NGX_CORE_MODULE` é o tipo de módulo mais básico e, portanto, o mais
genérico e de mais baixo nível.
Os outros tipos de módulo são implementados sobre ele e fornecem uma
maneira mais conveniente de lidar com domínios correspondentes, como manipular eventos ou
requisições HTTP.

O conjunto de módulos principais inclui os módulos `ngx_core_module`,
`ngx_errlog_module`, `ngx_regex_module`,
`ngx_thread_pool_module` e
`ngx_openssl_module`.
O módulo HTTP, o módulo stream, o módulo mail e módulos de evento também são módulos
principais.
O contexto de um módulo principal é definido como:

```c
typedef struct {
    ngx_str_t             name;
    void               *(*create_conf)(ngx_cycle_t *cycle);
    char               *(*init_conf)(ngx_cycle_t *cycle, void *conf);
} ngx_core_module_t;
```

onde o `name` é uma string com o nome do módulo,
`create_conf` e `init_conf`
são ponteiros para funções que criam e inicializam a configuração do módulo
respectivamente.
Para módulos principais, o Angie chama `create_conf` antes de analisar
uma nova configuração e `init_conf` depois que toda a configuração
é analisada com sucesso.
A função típica `create_conf` aloca memória para a
configuração e define valores padrão.

Por exemplo, um módulo simplista chamado `ngx_foo_module` poderia
se parecer com isto:

```c
/*
 * Copyright (C) Author.
 */


#include <ngx_config.h>
#include <ngx_core.h>


typedef struct {
    ngx_flag_t  enable;
} ngx_foo_conf_t;


static void *ngx_foo_create_conf(ngx_cycle_t *cycle);
static char *ngx_foo_init_conf(ngx_cycle_t *cycle, void *conf);

static char *ngx_foo_enable(ngx_conf_t *cf, void *post, void *data);
static ngx_conf_post_t  ngx_foo_enable_post = { ngx_foo_enable };


static ngx_command_t  ngx_foo_commands[] = {

    { ngx_string("foo_enabled"),
      NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
      ngx_conf_set_flag_slot,
      0,
      offsetof(ngx_foo_conf_t, enable),
      &ngx_foo_enable_post },

      ngx_null_command
};


static ngx_core_module_t  ngx_foo_module_ctx = {
    ngx_string("foo"),
    ngx_foo_create_conf,
    ngx_foo_init_conf
};


ngx_module_t  ngx_foo_module = {
    NGX_MODULE_V1,
    &ngx_foo_module_ctx,                   /* module context */
    ngx_foo_commands,                      /* module directives */
    NGX_CORE_MODULE,                       /* module type */
    NULL,                                  /* init master */
    NULL,                                  /* init module */
    NULL,                                  /* init process */
    NULL,                                  /* init thread */
    NULL,                                  /* exit thread */
    NULL,                                  /* exit process */
    NULL,                                  /* exit master */
    NGX_MODULE_V1_PADDING
};


static void *
ngx_foo_create_conf(ngx_cycle_t *cycle)
{
    ngx_foo_conf_t  *fcf;

    fcf = ngx_pcalloc(cycle->pool, sizeof(ngx_foo_conf_t));
    if (fcf == NULL) {
        return NULL;
    }

    fcf->enable = NGX_CONF_UNSET;

    return fcf;
}


static char *
ngx_foo_init_conf(ngx_cycle_t *cycle, void *conf)
{
    ngx_foo_conf_t *fcf = conf;

    ngx_conf_init_value(fcf->enable, 0);

    return NGX_CONF_OK;
}


static char *
ngx_foo_enable(ngx_conf_t *cf, void *post, void *data)
{
    ngx_flag_t  *fp = data;

    if (*fp == 0) {
        return NGX_CONF_OK;
    }

    ngx_log_error(NGX_LOG_NOTICE, cf->log, 0, "Foo Module is enabled");

    return NGX_CONF_OK;
}
```

<a id="configuration-directives"></a>

### Diretivas de Configuração

O tipo `ngx_command_t` define uma única diretiva de configuração.
Cada módulo que oferece suporte à configuração fornece um array de tais estruturas
que descrevem como processar argumentos e quais manipuladores chamar:

```c
typedef struct ngx_command_s  ngx_command_t;

struct ngx_command_s {
    ngx_str_t             name;
    ngx_uint_t            type;
    char               *(*set)(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
    ngx_uint_t            conf;
    ngx_uint_t            offset;
    void                 *post;
};
```

Termine o array com o valor especial `ngx_null_command`.
O `name` é o nome da diretiva como ela aparece
no arquivo de configuração, por exemplo, "worker_processes" ou "listen".
O `type` é um campo de bits de flags que especifica o número de
argumentos que a diretiva aceita, seu tipo e o contexto no qual ela aparece.
As flags são:

* `NGX_CONF_NOARGS` — A diretiva não aceita argumentos.
* `NGX_CONF_1MORE` — A diretiva aceita um ou mais argumentos.
* `NGX_CONF_2MORE` — A diretiva aceita dois ou mais argumentos.
* `NGX_CONF_TAKE1` .. `NGX_CONF_TAKE7` —
  A diretiva aceita exatamente o número indicado de argumentos.
* `NGX_CONF_TAKE12`, `NGX_CONF_TAKE13`,
  `NGX_CONF_TAKE23`, `NGX_CONF_TAKE123`,
  `NGX_CONF_TAKE1234` — A diretiva pode aceitar diferentes números de
  argumentos.
  As opções são limitadas aos números especificados.
  Por exemplo, `NGX_CONF_TAKE12` significa que aceita um ou dois
  argumentos.

Flags para tipos de diretiva:

* `NGX_CONF_BLOCK` — A diretiva é um bloco, ou seja, pode
  conter outras diretivas dentro de suas chaves de abertura e fechamento, ou até mesmo
  implementar seu próprio parser para lidar com conteúdo interno.
* `NGX_CONF_FLAG` — A diretiva aceita um valor booleano, seja
  `on` ou `off`.

O contexto da diretiva define onde ela pode aparecer na configuração:

* `NGX_MAIN_CONF` — No contexto de nível superior.
* `NGX_HTTP_MAIN_CONF` — No bloco `http`.
* `NGX_HTTP_SRV_CONF` — Em um bloco `server`
  dentro do bloco `http`.
* `NGX_HTTP_LOC_CONF` — Em um bloco `location`
  dentro do bloco `http`.
* `NGX_HTTP_UPS_CONF` — Em um bloco `upstream`
  dentro do bloco `http`.
* `NGX_HTTP_SIF_CONF` — Em um bloco `if` dentro
  de um bloco `server` no bloco `http`.
* `NGX_HTTP_LIF_CONF` — Em um bloco `if` dentro
  de um bloco `location` no bloco `http`.
* `NGX_HTTP_LMT_CONF` — Em um bloco `limit_except`
  dentro do bloco `http`.
* `NGX_STREAM_MAIN_CONF` — No bloco `stream`.
* `NGX_STREAM_SRV_CONF` — Em um bloco `server`
  dentro do bloco `stream`.
* `NGX_STREAM_UPS_CONF` — Em um bloco `upstream`
  dentro do bloco `stream`.
* `NGX_MAIL_MAIN_CONF` — No bloco `mail`.
* `NGX_MAIL_SRV_CONF` — Em um bloco `server`
  dentro do bloco `mail`.
* `NGX_EVENT_CONF` — No bloco `events`.
* `NGX_DIRECT_CONF` — Usado por módulos que não
  criam uma hierarquia de contextos e têm apenas uma única configuração global.
  Esta configuração é passada para o manipulador como o argumento `conf`.

O parser de configuração usa essas flags para gerar um erro para uma
diretiva mal posicionada e chama manipuladores de diretiva fornecidos com o
ponteiro de configuração apropriado, para que as mesmas diretivas em locais diferentes possam
armazenar seus valores em locais distintos.

O campo `set` define um manipulador que processa a diretiva
e armazena valores analisados na configuração correspondente.
Há várias funções que realizam conversões comuns:

* `ngx_conf_set_flag_slot` — Converte as strings literais
  `on` e `off` em um
  valor `ngx_flag_t` com valores 1 ou 0, respectivamente.
* `ngx_conf_set_str_slot` — Armazena uma string como um valor do
  tipo `ngx_str_t`.
* `ngx_conf_set_str_array_slot` — Adiciona um valor a um array
  `ngx_array_t` de strings `ngx_str_t`.
  O array é criado se ainda não existir.
* `ngx_conf_set_keyval_slot` — Adiciona um par chave-valor a um
  array `ngx_array_t` de pares chave-valor
  `ngx_keyval_t`.
  A primeira string torna-se a chave e a segunda o valor.
  O array é criado se ainda não existir.
* `ngx_conf_set_num_slot` — Converte um argumento da diretiva
  para um valor `ngx_int_t`.
* `ngx_conf_set_size_slot` — Converte um
  [tamanho](https://pt.angie.software//angie/docs/configuration/configfile.md#syntax) para um valor `size_t`
  expresso em bytes.
* `ngx_conf_set_off_slot` — Converte um
  [offset](https://pt.angie.software//angie/docs/configuration/configfile.md#syntax) para um valor `off_t`
  expresso em bytes.
* `ngx_conf_set_msec_slot` — Converte um
  [tempo](https://pt.angie.software//angie/docs/configuration/configfile.md#syntax) para um valor `ngx_msec_t`
  expresso em milissegundos.
* `ngx_conf_set_sec_slot` — Converte um
  [tempo](https://pt.angie.software//angie/docs/configuration/configfile.md#syntax) para um valor `time_t`
  expresso em segundos.
* `ngx_conf_set_bufs_slot` — Converte os dois argumentos fornecidos
  em um objeto `ngx_bufs_t` que contém o número e
  [tamanho](https://pt.angie.software//angie/docs/configuration/configfile.md#syntax) dos buffers.
* `ngx_conf_set_enum_slot` — Converte o argumento fornecido
  em um valor `ngx_uint_t`.
  O array terminado em null de `ngx_conf_enum_t` passado no
  campo `post` define as strings aceitáveis e os valores
  inteiros correspondentes.
* `ngx_conf_set_bitmask_slot` — Converte os argumentos fornecidos
  em um valor `ngx_uint_t`.
  Os valores de máscara para cada argumento são combinados com OR produzindo o resultado.
  O array terminado em null de `ngx_conf_bitmask_t` passado no
  campo `post` define as strings aceitáveis e os valores
  de máscara correspondentes.
* `ngx_conf_set_path_slot` — Converte os argumentos fornecidos para um
  valor `ngx_path_t` e realiza todas as inicializações necessárias.
  Para detalhes, veja a documentação da diretiva
  [proxy_temp_path](https://pt.angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-temp-path).
* `ngx_conf_set_access_slot` — Converte os argumentos fornecidos para uma máscara
  de permissões de arquivo.
  Para detalhes, veja a documentação da diretiva
  [proxy_store_access](https://pt.angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-store-access).

O campo `conf` define qual estrutura de configuração
é passada para o manipulador de diretiva.
Módulos principais têm apenas a configuração global e definem
a flag `NGX_DIRECT_CONF` para acessá-la.
Módulos como HTTP, Stream ou Mail criam hierarquias de configurações.
Por exemplo, a configuração de um módulo é criada para os escopos `server`,
`location` e `if`.

* `NGX_HTTP_MAIN_CONF_OFFSET` — Configuração para o
  bloco `http`.
* `NGX_HTTP_SRV_CONF_OFFSET` — Configuração para um
  bloco `server` dentro do bloco `http`.
* `NGX_HTTP_LOC_CONF_OFFSET` — Configuração para um
  bloco `location` dentro do bloco `http`.
* `NGX_STREAM_MAIN_CONF_OFFSET` — Configuração para o
  bloco `stream`.
* `NGX_STREAM_SRV_CONF_OFFSET` — Configuração para um
  bloco `server` dentro do bloco `stream`.
* `NGX_MAIL_MAIN_CONF_OFFSET` — Configuração para o
  bloco `mail`.
* `NGX_MAIL_SRV_CONF_OFFSET` — Configuração para um
  bloco `server` dentro do bloco `mail`.

O campo `offset` define o deslocamento de um campo na estrutura
de configuração do módulo que contém valores para esta diretiva específica.
O uso típico é empregar a macro `offsetof()`.

O campo `post` tem dois propósitos: pode ser usado para definir
um manipulador a ser chamado após o manipulador principal ter completado, ou para passar
dados adicionais para o manipulador principal.
No primeiro caso, a estrutura `ngx_conf_post_t` precisa ser
inicializada com um ponteiro para o manipulador, por exemplo:

```c
static char *ngx_do_foo(ngx_conf_t *cf, void *post, void *data);
static ngx_conf_post_t  ngx_foo_post = { ngx_do_foo };
```

O argumento `post` é o próprio objeto `ngx_conf_post_t`,
e o `data` é um ponteiro para o valor,
convertido dos argumentos pelo manipulador principal com o tipo apropriado.

<a id="http"></a>

## HTTP

<a id="http-connection"></a>

### Conexão

Cada conexão de cliente HTTP passa pelas seguintes etapas:

* `ngx_event_accept()` aceita uma conexão TCP do cliente.
  Este manipulador é chamado em resposta a uma notificação de leitura em um socket de escuta.
  Um novo objeto `ngx_connection_t` é criado nesta etapa
  para encapsular o socket do cliente recém-aceito.
  Cada ouvinte do Angie fornece um manipulador para passar o novo objeto de conexão.
  Para conexões HTTP é `ngx_http_init_connection(c)`.
* `ngx_http_init_connection()` executa a inicialização inicial da
  conexão HTTP.
  Nesta etapa um objeto `ngx_http_connection_t` é criado para
  a conexão e sua referência é armazenada no campo
  `data` da conexão.
  Posteriormente será substituído por um objeto de requisição HTTP.
  Um analisador de protocolo PROXY e o handshake SSL são iniciados
  nesta etapa também.
* O manipulador de evento de leitura `ngx_http_wait_request_handler()`
  é chamado quando dados estão disponíveis no socket do cliente.
  Nesta etapa um objeto de requisição HTTP `ngx_http_request_t` é
  criado e definido no campo `data` da conexão.
* O manipulador de evento de leitura `ngx_http_process_request_line()`
  lê a linha de requisição do cliente.
  O manipulador é definido por `ngx_http_wait_request_handler()`.
  Os dados são lidos no `buffer` da conexão.
  O tamanho do buffer é inicialmente definido pela diretiva
  [client_header_buffer_size](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#client-header-buffer-size).
  Todo o cabeçalho do cliente deve caber no buffer.
  Se o tamanho inicial não for suficiente, um buffer maior é alocado,
  com a capacidade definida pela diretiva [large_client_header_buffers](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#large-client-header-buffers).
* O manipulador de evento de leitura `ngx_http_process_request_headers()`,
  é definido após `ngx_http_process_request_line()` para ler
  o cabeçalho da requisição do cliente.
* `ngx_http_core_run_phases()` é chamado quando o cabeçalho da requisição
  é completamente lido e analisado.
  Esta função executa as fases da requisição de
  `NGX_HTTP_POST_READ_PHASE` até
  `NGX_HTTP_CONTENT_PHASE`.
  A última fase destina-se a gerar uma resposta e passá-la pela cadeia de filtros.
  A resposta não é necessariamente enviada ao cliente nesta fase.
  Pode permanecer em buffer e ser enviada na etapa de finalização.
* `ngx_http_finalize_request()` é geralmente chamado quando a
  requisição gerou toda a saída ou produziu um erro.
  No último caso, uma página de erro apropriada é procurada e usada como
  resposta.
  Se a resposta não foi completamente enviada ao cliente neste ponto, um
  escritor HTTP `ngx_http_writer()` é ativado para terminar
  de enviar os dados pendentes.
* `ngx_http_finalize_connection()` é chamado quando a resposta
  completa foi enviada ao cliente e a requisição pode ser destruída.
  Se o recurso keepalive da conexão do cliente estiver habilitado,
  `ngx_http_set_keepalive()` é chamado, que destrói a
  requisição atual e aguarda a próxima requisição na conexão.
  Caso contrário, `ngx_http_close_request()` destrói tanto a
  requisição quanto a conexão.

<a id="request"></a>

### Requisição

Para cada requisição HTTP do cliente o objeto `ngx_http_request_t` é
criado. Alguns dos campos deste objeto são:

* `connection` — Ponteiro para um objeto de conexão do cliente
  `ngx_connection_t`.
  Várias requisições podem referenciar o mesmo objeto de conexão ao mesmo tempo -
  uma requisição principal e suas sub-requisições.
  Após uma requisição ser excluída, uma nova requisição pode ser criada na mesma conexão.

  Note que para conexões HTTP o campo `data` de
  `ngx_connection_t` aponta de volta para a requisição.
  Tais requisições são chamadas ativas, em oposição às outras requisições vinculadas à
  conexão.
  Uma requisição ativa é usada para manipular eventos de conexão do cliente e tem permissão para
  enviar sua resposta ao cliente.
  Normalmente, cada requisição torna-se ativa em algum ponto para que possa enviar sua
  saída.
* `ctx` — Array de contextos de módulos HTTP.
  Cada módulo do tipo `NGX_HTTP_MODULE` pode armazenar qualquer valor
  (normalmente, um ponteiro para uma estrutura) na requisição.
  O valor é armazenado no array `ctx` na posição
  `ctx_index` do módulo.
  As seguintes macros fornecem uma maneira conveniente de obter e definir contextos de requisição:
  * `ngx_http_get_module_ctx(r, module)` — Retorna
    o contexto do `module`
  * `ngx_http_set_ctx(r, c, module)` — Define `c`
    como o contexto do `module`
* `main_conf`, `srv_conf`,
  `loc_conf` — Arrays das configurações da requisição
  atual.
  As configurações são armazenadas nas posições `ctx_index`
  do módulo.
* `read_event_handler`, `write_event_handler` -
  Manipuladores de eventos de leitura e escrita para a requisição.
  Normalmente, tanto os manipuladores de eventos de leitura quanto de escrita para uma conexão HTTP
  são definidos como `ngx_http_request_handler()`.
  Esta função chama os manipuladores `read_event_handler` e
  `write_event_handler` para a requisição
  atualmente ativa.
* `cache` — Objeto de cache da requisição para armazenar em cache a
  resposta upstream.
* `upstream` — Objeto upstream da requisição para proxy.
* `pool` — Pool da requisição.
  O próprio objeto de requisição é alocado neste pool, que é destruído quando
  a requisição é excluída.
  Para alocações que precisam estar disponíveis durante toda a vida útil da conexão do cliente,
  use o pool de `ngx_connection_t` em vez disso.
* `header_in` — Buffer no qual o cabeçalho da requisição HTTP
  do cliente é lido.
* `headers_in`, `headers_out` — Objetos de cabeçalhos
  HTTP de entrada e saída.
  Ambos os objetos contêm o campo `headers` do tipo
  `ngx_list_t` para manter a lista bruta de cabeçalhos.
  Além disso, cabeçalhos específicos estão disponíveis para obtenção e definição como
  campos separados, por exemplo `content_length_n`,
  `status` etc.
* `request_body` — Objeto do corpo da requisição do cliente.
* `start_sec`, `start_msec` — Ponto no tempo quando
  a requisição foi criada, usado para rastrear a duração da requisição.
* `method`, `method_name` — Representação numérica e textual
  do método de requisição HTTP do cliente.
  Valores numéricos para métodos são definidos em
  `src/http/ngx_http_request.h` com as macros
  `NGX_HTTP_GET`, `NGX_HTTP_HEAD`,
  `NGX_HTTP_POST`, etc.
* `http_protocol` — Versão do protocolo HTTP do cliente em sua
  forma textual original ("HTTP/1.0", "HTTP/1.1" etc).
* `http_version` — Versão do protocolo HTTP do cliente em
  forma numérica (`NGX_HTTP_VERSION_10`,
  `NGX_HTTP_VERSION_11`, etc.).
* `http_major`, `http_minor` — Versão do protocolo HTTP
  do cliente em forma numérica dividida em partes maior e menor.
* `request_line`, `unparsed_uri` — Linha de requisição
  e URI na requisição original do cliente.
* `uri`, `args`, `exten` —
  URI, argumentos e extensão de arquivo para a requisição atual.
  O valor do URI aqui pode diferir do URI original enviado pelo cliente devido à
  normalização.
  Durante o processamento da requisição, esses valores podem mudar conforme redirecionamentos internos
  são executados.
* `main` — Ponteiro para um objeto de requisição principal.
  Este objeto é criado para processar uma requisição HTTP do cliente, em oposição a
  sub-requisições, que são criadas para executar uma subtarefa específica dentro da requisição principal.
* `parent` — Ponteiro para a requisição pai de uma sub-requisição.
* `postponed` — Lista de buffers de saída e sub-requisições, na
  ordem em que são enviados e criados.
  A lista é usada pelo filtro postpone para fornecer saída consistente da requisição
  quando partes dela são criadas por sub-requisições.
* `post_subrequest` — Ponteiro para um manipulador com o contexto
  a ser chamado quando uma sub-requisição é finalizada.
  Não usado para requisições principais.
* `posted_requests` — Lista de requisições a serem iniciadas ou
  retomadas, o que é feito chamando o
  `write_event_handler` da requisição.
  Normalmente, este manipulador contém a função principal da requisição, que primeiro executa
  as fases da requisição e depois produz a saída.

  Uma requisição é geralmente postada pela chamada
  `ngx_http_post_request(r, NULL)`.
  É sempre postada na lista `posted_requests` da requisição principal.
  A função `ngx_http_run_posted_requests(c)` executa todas
  as requisições que são postadas na requisição principal da
  requisição ativa da conexão passada.
  Todos os manipuladores de eventos chamam `ngx_http_run_posted_requests`,
  o que pode levar a novas requisições postadas.
  Normalmente, é chamado após invocar um manipulador de leitura ou escrita de uma requisição.
* `phase_handler` — Índice da fase atual da requisição.
* `ncaptures`, `captures`,
  `captures_data` — Capturas de regex produzidas
  pela última correspondência de regex da requisição.
  Uma correspondência de regex pode ocorrer em vários lugares durante o processamento da requisição:
  busca em map, busca de servidor por SNI ou Host HTTP, rewrite, proxy_redirect, etc.
  As capturas produzidas por uma busca são armazenadas nos campos mencionados acima.
  O campo `ncaptures` contém o número de capturas,
  `captures` contém os limites das capturas e
  `captures_data` contém a string contra a qual o regex foi
  correspondido e que é usada para extrair capturas.
  Após cada nova correspondência de regex, as capturas da requisição são redefinidas para conter novos valores.
* `count` — Contador de referência da requisição.
  O campo só faz sentido para a requisição principal.
  Aumentar o contador é feito por simples `r->main->count++`.
  Para diminuir o contador, chame
  `ngx_http_finalize_request(r, rc)`.
  A criação de uma sub-requisição e a execução do processo de leitura do corpo da requisição ambos
  incrementam o contador.
* `subrequests` — Nível atual de aninhamento de sub-requisições.
  Cada sub-requisição herda o nível de aninhamento de seu pai, diminuído em um.
  Um erro é gerado se o valor chegar a zero.
  O valor para a requisição principal é definido pela
  constante `NGX_HTTP_MAX_SUBREQUESTS`.
* `uri_changes` — Número de mudanças de URI restantes para
  a requisição.
  O número total de vezes que uma requisição pode alterar seu URI é limitado pela
  constante `NGX_HTTP_MAX_URI_CHANGES`.
  A cada mudança o valor é decrementado até chegar a zero, momento em que
  um erro é gerado.
  Reescritas e redirecionamentos internos para localizações normais ou nomeadas são considerados mudanças de URI.
* `blocked` — Contador de bloqueios mantidos na requisição.
  Enquanto este valor for diferente de zero, a requisição não pode ser finalizada.
  Atualmente, este valor é aumentado por operações AIO pendentes (POSIX AIO e
  operações de thread) e bloqueios de cache ativos.
* `buffered` — Máscara de bits mostrando quais módulos fizeram buffer da
  saída produzida pela requisição.
  Vários filtros podem fazer buffer da saída; por exemplo, sub_filter pode fazer buffer de dados
  devido a uma correspondência parcial de string, copy filter pode fazer buffer de dados devido à
  falta de buffers de saída livres, etc.
  Enquanto este valor for diferente de zero, a requisição não é finalizada,
  aguardando um flush.
* `header_only` — Flag indicando que a saída não requer
  um corpo.
  Por exemplo, esta flag é usada por requisições HTTP HEAD.
* `keepalive` — Flag indicando se o keepalive da conexão
  do cliente é suportado.
  O valor é inferido da versão HTTP e do valor do
  cabeçalho "Connection".
* `header_sent` — Flag indicando que o cabeçalho de saída
  já foi enviado pela requisição.
* `internal` — Flag indicando que a requisição atual
  é interna.
  Para entrar no estado interno, uma requisição deve passar por um
  redirecionamento interno ou ser uma sub-requisição.
  Requisições internas têm permissão para entrar em localizações internas.
* `allow_ranges` — Flag indicando que uma resposta parcial
  pode ser enviada ao cliente, conforme solicitado pelo cabeçalho HTTP Range.
* `subrequest_ranges` — Flag indicando que uma resposta parcial
  pode ser enviada durante o processamento de uma sub-requisição.
* `single_range` — Flag indicando que apenas um único intervalo contínuo
  de dados de saída pode ser enviado ao cliente.
  Esta flag é geralmente definida ao enviar um fluxo de dados, por exemplo, de um
  servidor proxy, e a resposta inteira não está disponível em um único buffer.
* `main_filter_need_in_memory`,
  `filter_need_in_memory` — Flags
  solicitando que a saída seja produzida em buffers de memória em vez de arquivos.
  Este é um sinal para o copy filter ler dados de buffers de arquivo mesmo se
  sendfile estiver habilitado.
  A diferença entre as duas flags é a localização dos módulos de filtro que
  as definem.
  Filtros chamados antes do postpone filter na cadeia de filtros definem
  `filter_need_in_memory`, solicitando que apenas a saída da
  requisição atual venha em buffers de memória.
  Filtros chamados posteriormente na cadeia de filtros definem
  `main_filter_need_in_memory`, solicitando que
  tanto a requisição principal quanto todas as sub-requisições leiam arquivos em memória
  ao enviar a saída.
* `filter_need_temporary` — Flag solicitando que a saída da requisição
  seja produzida em buffers temporários, mas não em buffers de memória somente leitura ou
  buffers de arquivo.
  Isto é usado por filtros que podem alterar a saída diretamente nos buffers onde
  ela é enviada.

<a id="http-module-configuration"></a>

### Configuração de Módulo HTTP

Cada módulo HTTP pode ter três tipos de configuração:

* Configuração principal — Aplica-se a todo o bloco `http`.
  Funciona como configurações globais para o módulo.
* Configuração de servidor — Aplica-se a um único bloco `server`.
  Funciona como configurações específicas do servidor para o módulo.
* Configuração de localização — Aplica-se a um único bloco `location`,
  `if` ou `limit_except`.
  Funciona como configurações específicas da localização para o módulo.

As estruturas de configuração são criadas na etapa de configuração do Angie chamando
funções que alocam as estruturas, as inicializam
e as mesclam.
O exemplo a seguir mostra como criar uma configuração de localização simples
para um módulo.
A configuração tem uma configuração, `foo`, do tipo
unsigned integer.

```c
typedef struct {
    ngx_uint_t  foo;
} ngx_http_foo_loc_conf_t;


static ngx_http_module_t  ngx_http_foo_module_ctx = {
    NULL,                                  /* preconfiguration */
    NULL,                                  /* postconfiguration */

    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */

    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */

    ngx_http_foo_create_loc_conf,          /* create location configuration */
    ngx_http_foo_merge_loc_conf            /* merge location configuration */
};


static void *
ngx_http_foo_create_loc_conf(ngx_conf_t *cf)
{
    ngx_http_foo_loc_conf_t  *conf;

    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_foo_loc_conf_t));
    if (conf == NULL) {
        return NULL;
    }

    conf->foo = NGX_CONF_UNSET_UINT;

    return conf;
}


static char *
ngx_http_foo_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_foo_loc_conf_t *prev = parent;
    ngx_http_foo_loc_conf_t *conf = child;

    ngx_conf_merge_uint_value(conf->foo, prev->foo, 1);
}
```

Como visto no exemplo, a função `ngx_http_foo_create_loc_conf()`
cria uma nova estrutura de configuração, e
`ngx_http_foo_merge_loc_conf()` mescla uma configuração com
a configuração de um nível superior.
Na verdade, as configurações de servidor e localização não existem apenas nos níveis de servidor e
localização, mas também são criadas para todos os níveis acima deles.
Especificamente, uma configuração de servidor também é criada no nível principal e
configurações de localização são criadas nos níveis principal, servidor e localização.
Essas configurações tornam possível especificar configurações específicas de servidor e localização
em qualquer nível de um arquivo de configuração do Angie.
Eventualmente as configurações são mescladas para baixo.
Várias macros como `NGX_CONF_UNSET` e
`NGX_CONF_UNSET_UINT` são fornecidas
para indicar uma configuração ausente e ignorá-la durante a mesclagem.
Macros de mesclagem padrão do Angie como `ngx_conf_merge_value()` e
`ngx_conf_merge_uint_value()` fornecem uma maneira conveniente de
mesclar uma configuração e definir o valor padrão se nenhuma das configurações
forneceu um valor explícito.
Para uma lista completa de macros para diferentes tipos, veja
`src/core/ngx_conf_file.h`.

As seguintes macros estão disponíveis
para acessar a configuração de módulos HTTP no momento da configuração.
Todas elas recebem uma referência `ngx_conf_t` como primeiro argumento.

* `ngx_http_conf_get_module_main_conf(cf, module)`
* `ngx_http_conf_get_module_srv_conf(cf, module)`
* `ngx_http_conf_get_module_loc_conf(cf, module)`

O exemplo a seguir obtém um ponteiro para uma configuração de localização
do [módulo HTTP core](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#http-core) padrão
e substitui o manipulador de conteúdo de localização armazenado
no campo `handler` da estrutura.

```c
static ngx_int_t ngx_http_foo_handler(ngx_http_request_t *r);


static ngx_command_t  ngx_http_foo_commands[] = {

    { ngx_string("foo"),
      NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
      ngx_http_foo,
      0,
      0,
      NULL },

      ngx_null_command
};


static char *
ngx_http_foo(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_core_loc_conf_t  *clcf;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
    clcf->handler = ngx_http_bar_handler;

    return NGX_CONF_OK;
}
```

As seguintes macros estão disponíveis para acessar a configuração de módulos
HTTP em tempo de execução.

* `ngx_http_get_module_main_conf(r, module)`
* `ngx_http_get_module_srv_conf(r, module)`
* `ngx_http_get_module_loc_conf(r, module)`

Essas macros recebem uma referência para uma requisição HTTP
`ngx_http_request_t`.
A configuração principal de uma requisição nunca muda.
A configuração do servidor pode mudar do padrão após
a escolha de um servidor virtual para a requisição.
A configuração de localização selecionada para processar uma requisição pode mudar múltiplas
vezes como resultado de uma operação de reescrita ou redirecionamento interno.
O exemplo a seguir mostra como acessar a configuração HTTP de um módulo em
tempo de execução.

```c
static ngx_int_t
ngx_http_foo_handler(ngx_http_request_t *r)
{
    ngx_http_foo_loc_conf_t  *flcf;

    flcf = ngx_http_get_module_loc_conf(r, ngx_http_foo_module);

    ...
}
```

<a id="phases"></a>

### Fases

Cada requisição HTTP passa por uma sequência de fases.
Em cada fase um tipo distinto de processamento é executado na requisição.
Manipuladores específicos de módulo podem ser registrados na maioria das fases,
e muitos módulos padrão do Angie registram seus manipuladores de fase como uma forma
de serem invocados em um estágio específico do processamento da requisição.
As fases são processadas sucessivamente e os manipuladores de fase são chamados
uma vez que a requisição atinge a fase.
A seguir está a lista das fases HTTP do Angie.

* `NGX_HTTP_POST_READ_PHASE` — Primeira fase.
  O módulo [RealIP](https://pt.angie.software//angie/docs/configuration/modules/http/http_realip.md#http-realip)
  registra seu manipulador nesta fase para habilitar
  substituição de endereços de cliente antes que qualquer outro módulo seja invocado.
* `NGX_HTTP_SERVER_REWRITE_PHASE` — Fase onde
  diretivas de reescrita definidas em um bloco `server`
  (mas fora de um bloco `location`) são processadas.
  O módulo [Rewrite](https://pt.angie.software//angie/docs/configuration/modules/http/http_rewrite.md#http-rewrite)
  instala seu manipulador nesta fase.
* `NGX_HTTP_FIND_CONFIG_PHASE` — Fase especial onde
  uma localização é escolhida baseada na URI da requisição.
  Antes desta fase, a localização padrão para o servidor virtual relevante é atribuída à
  requisição, e qualquer módulo solicitando uma configuração de localização
  recebe a configuração para a localização padrão do servidor.
  Esta fase atribui uma nova localização à requisição.
  Nenhum manipulador adicional pode ser registrado nesta fase.
* `NGX_HTTP_REWRITE_PHASE` — Igual a
  `NGX_HTTP_SERVER_REWRITE_PHASE`, mas para
  regras de reescrita definidas na localização escolhida na fase anterior.
* `NGX_HTTP_POST_REWRITE_PHASE` — Fase especial onde
  a requisição é redirecionada para uma nova localização se sua URI mudou
  durante uma reescrita.
  Isso é implementado pela requisição passando pela
  `NGX_HTTP_FIND_CONFIG_PHASE` novamente.
  Nenhum manipulador adicional pode ser registrado nesta fase.
* `NGX_HTTP_PREACCESS_PHASE` — Uma fase comum para diferentes
  tipos de manipuladores, não associados com controle de acesso.
  Os módulos padrão do Angie
  [Limit Conn](https://pt.angie.software//angie/docs/configuration/modules/http/http_limit_conn.md#http-limit-conn) e
  [Limit Req](https://pt.angie.software//angie/docs/configuration/modules/http/http_limit_req.md#http-limit-req) registram seus manipuladores nesta fase.
* `NGX_HTTP_ACCESS_PHASE` — Fase onde é verificado
  se o cliente está autorizado a fazer a requisição.
  Módulos padrão do Angie como
  [Access](https://pt.angie.software//angie/docs/configuration/modules/http/http_access.md#http-access) e
  [Auth Basic](https://pt.angie.software//angie/docs/configuration/modules/http/http_auth_basic.md#http-auth-basic) registram seus manipuladores nesta fase.
  Por padrão o cliente deve passar na verificação de autorização de todos os manipuladores
  registrados nesta fase para que a requisição continue para a próxima fase.
  A diretiva [satisfy](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#satisfy) pode
  ser usada para permitir que o processamento continue se qualquer um dos manipuladores de fase
  autorizar o cliente.
* `NGX_HTTP_POST_ACCESS_PHASE` — Fase especial onde a
  diretiva [satisfy](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#satisfy) é processada.
  Se alguns manipuladores de fase de acesso negaram acesso e nenhum explicitamente permitiu,
  a requisição é finalizada.
  Nenhum manipulador adicional pode ser registrado nesta fase.
* `NGX_HTTP_PRECONTENT_PHASE` — Fase para manipuladores serem chamados
  antes de gerar conteúdo.
  Módulos padrão como
  [try_files](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#try-files) e
  [Mirror](https://pt.angie.software//angie/docs/configuration/modules/http/http_mirror.md#http-mirror)
  registram seus manipuladores nesta fase.
* `NGX_HTTP_CONTENT_PHASE` — Fase onde a resposta
  é normalmente gerada.
  Múltiplos módulos padrão do Angie registram seus manipuladores nesta fase,
  incluindo
  [Index](https://pt.angie.software//angie/docs/configuration/modules/http/http_index.md#http-index).
  Eles são chamados sequencialmente até que um deles produza
  a saída.
  Também é possível definir manipuladores de conteúdo por localização.
  Se a configuração de localização do módulo [Módulo HTTP](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#http-core) tem
  `handler` definido, ele é chamado como o manipulador de conteúdo
  e os manipuladores instalados nesta fase são ignorados.
* `NGX_HTTP_LOG_PHASE` — Fase onde o registro de requisições
  é executado.
  Atualmente, apenas o módulo
  [Log](https://pt.angie.software//angie/docs/configuration/modules/http/http_log.md#http-log) registra seu manipulador
  neste estágio para registro de acesso.
  Manipuladores de fase de log são chamados no final do processamento da requisição, logo
  antes de liberar a requisição.

A seguir está um exemplo de um manipulador de fase de pré-acesso.

```c
static ngx_http_module_t  ngx_http_foo_module_ctx = {
    NULL,                                  /* preconfiguration */
    ngx_http_foo_init,                     /* postconfiguration */

    NULL,                                  /* create main configuration */
    NULL,                                  /* init main configuration */

    NULL,                                  /* create server configuration */
    NULL,                                  /* merge server configuration */

    NULL,                                  /* create location configuration */
    NULL                                   /* merge location configuration */
};


static ngx_int_t
ngx_http_foo_handler(ngx_http_request_t *r)
{
    ngx_table_elt_t  *ua;

    ua = r->headers_in.user_agent;

    if (ua == NULL) {
        return NGX_DECLINED;
    }

    /* reject requests with "User-Agent: foo" */
    if (ua->value.len == 3 && ngx_strncmp(ua->value.data, "foo", 3) == 0) {
        return NGX_HTTP_FORBIDDEN;
    }

    return NGX_DECLINED;
}


static ngx_int_t
ngx_http_foo_init(ngx_conf_t *cf)
{
    ngx_http_handler_pt        *h;
    ngx_http_core_main_conf_t  *cmcf;

    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

    h = ngx_array_push(&cmcf->phases[NGX_HTTP_PREACCESS_PHASE].handlers);
    if (h == NULL) {
        return NGX_ERROR;
    }

    *h = ngx_http_foo_handler;

    return NGX_OK;
}
```

Espera-se que os manipuladores de fase retornem códigos específicos:

* `NGX_OK` — prosseguir para a próxima fase.
* `NGX_DECLINED` — prosseguir para o próximo manipulador da fase
  atual.
  Se o manipulador atual for o último na fase atual,
  mover para a próxima fase.
* `NGX_AGAIN`, `NGX_DONE` — suspender
  o processamento da fase até algum evento futuro, que pode ser
  uma operação de E/S assíncrona ou apenas um atraso, por exemplo.
  Assume-se que o processamento da fase será retomado posteriormente chamando
  `ngx_http_core_run_phases()`.
* Qualquer outro valor retornado pelo manipulador de fase é tratado como um código
  de finalização da requisição, em particular, um código de resposta HTTP.
  A requisição é finalizada com o código fornecido.

Para algumas fases, os códigos de retorno são tratados de forma ligeiramente diferente.
Na fase de conteúdo, qualquer código de retorno diferente de
`NGX_DECLINED` é considerado um código de finalização.
Qualquer código de retorno dos manipuladores de conteúdo de localização é considerado
um código de finalização.
Na fase de acesso, no
modo [satisfy any](https://pt.angie.software//angie/docs/configuration/modules/http/index.md#satisfy),
retornar um código diferente de `NGX_OK`,
`NGX_DECLINED`, `NGX_AGAIN`,
`NGX_DONE` é considerado uma negação.
Se nenhum manipulador de acesso subsequente permitir ou negar acesso com um
código diferente, o código de negação se tornará o código de finalização.

<a id="examples"></a>

### Exemplos

O repositório
[nginx-dev-examples](https://github.com/nginx/nginx-dev-examples)
fornece exemplos de módulos nginx adequados para o Angie também.

<a id="code-style"></a>

## Estilo de código

<a id="general-rules"></a>

### Regras gerais

* largura máxima do texto é 80 caracteres
* indentação é 4 espaços
* sem tabs, sem espaços no final
* elementos de lista na mesma linha são separados com espaços
* literais hexadecimais são minúsculos
* nomes de arquivos, funções e tipos, e variáveis globais têm
  o prefixo `ngx_` ou um prefixo mais específico como
  `ngx_http_` e `ngx_mail_`

```c
size_t
ngx_utf8_length(u_char *p, size_t n)
{
    u_char  c, *last;
    size_t  len;

    last = p + n;

    for (len = 0; p < last; len++) {

        c = *p;

        if (c < 0x80) {
            p++;
            continue;
        }

        if (ngx_utf8_decode(&p, last - p) > 0x10ffff) {
            /* invalid UTF-8 */
            return n;
        }
    }

    return len;
}
```

<a id="files"></a>

### Arquivos

Um arquivo fonte típico pode conter as seguintes seções, separadas por
duas linhas vazias:

* declarações de copyright
* includes
* definições do pré-processador
* definições de tipos
* protótipos de funções
* definições de variáveis
* definições de funções

As declarações de copyright ficam assim:

```c
/*
 * Copyright (C) Author Name
 * Copyright (C) Organization, Inc.
 */
```

Se o arquivo for modificado significativamente, a lista de autores deve ser atualizada,
o novo autor é adicionado ao topo.

Os arquivos `ngx_config.h` e `ngx_core.h`
são sempre incluídos primeiro, seguidos por um de
`ngx_http.h`, `ngx_stream.h`,
ou `ngx_mail.h`.
Então seguem arquivos de cabeçalho externos opcionais:

```c
#include <ngx_config.h>
#include <ngx_core.h>
#include <ngx_http.h>

#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxslt/xslt.h>

#if (NGX_HAVE_EXSLT)
#include <libexslt/exslt.h>
#endif
```

Arquivos de cabeçalho devem incluir a chamada "proteção de cabeçalho":

```c
#ifndef _NGX_PROCESS_CYCLE_H_INCLUDED_
#define _NGX_PROCESS_CYCLE_H_INCLUDED_
...
#endif /* _NGX_PROCESS_CYCLE_H_INCLUDED_ */
```

<a id="comments"></a>

### Comentários

* comentários `//` não são usados
* texto é em inglês, ortografia americana é preferida
* comentários multi-linha são formatados assim:
  ```c
  /*
   * The red-black tree code is based on the algorithm described in
   * the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
   */
  ```

  ```c
  /* find the server configuration for the address:port */
  ```

<a id="preprocessor"></a>

### Pré-processador

Nomes de macro começam com o prefixo `ngx_` ou `NGX_`
(ou mais específico).
Nomes de macro para constantes são maiúsculos.
Macros parametrizadas e macros para inicializadores são minúsculas.
O nome da macro e o valor são separados por pelo menos dois espaços:

```c
#define NGX_CONF_BUFFER  4096

#define ngx_buf_in_memory(b)  (b->temporary || b->memory || b->mmap)

#define ngx_buf_size(b)                                                      \
    (ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos):                      \
                            (b->file_last - b->file_pos))

#define ngx_null_string  { 0, NULL }
```

Condições ficam dentro de parênteses, negação fica fora:

```c
#if (NGX_HAVE_KQUEUE)
...
#elif ((NGX_HAVE_DEVPOLL && !(NGX_TEST_BUILD_DEVPOLL)) \
       || (NGX_HAVE_EVENTPORT && !(NGX_TEST_BUILD_EVENTPORT)))
...
#elif (NGX_HAVE_EPOLL && !(NGX_TEST_BUILD_EPOLL))
...
#elif (NGX_HAVE_POLL)
...
#else /* select */
...
#endif /* NGX_HAVE_KQUEUE */
```

<a id="types-1"></a>

### Tipos

Nomes de tipos terminam com o sufixo `_t`.
Um nome de tipo definido é separado por pelo menos dois espaços:

```c
typedef ngx_uint_t  ngx_rbtree_key_t;
```

Tipos de estrutura são definidos usando `typedef`.
Dentro de estruturas, tipos de membros e nomes são alinhados:

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

Mantenha o mesmo alinhamento entre diferentes estruturas no arquivo.
Uma estrutura que aponta para si mesma tem um nome terminando com
`_s`.
Definições de estruturas adjacentes são separadas por duas linhas vazias:

```c
typedef struct ngx_list_part_s  ngx_list_part_t;

struct ngx_list_part_s {
    void             *elts;
    ngx_uint_t        nelts;
    ngx_list_part_t  *next;
};


typedef struct {
    ngx_list_part_t  *last;
    ngx_list_part_t   part;
    size_t            size;
    ngx_uint_t        nalloc;
    ngx_pool_t       *pool;
} ngx_list_t;
```

Cada membro da estrutura é declarado em sua própria linha:

```c
typedef struct {
    ngx_uint_t        hash;
    ngx_str_t         key;
    ngx_str_t         value;
    u_char           *lowcase_key;
} ngx_table_elt_t;
```

Ponteiros de função dentro de estruturas têm tipos definidos terminando com
`_pt`:

```c
typedef ssize_t (*ngx_recv_pt)(ngx_connection_t *c, u_char *buf, size_t size);
typedef ssize_t (*ngx_recv_chain_pt)(ngx_connection_t *c, ngx_chain_t *in,
    off_t limit);
typedef ssize_t (*ngx_send_pt)(ngx_connection_t *c, u_char *buf, size_t size);
typedef ngx_chain_t *(*ngx_send_chain_pt)(ngx_connection_t *c, ngx_chain_t *in,
    off_t limit);

typedef struct {
    ngx_recv_pt        recv;
    ngx_recv_chain_pt  recv_chain;
    ngx_recv_pt        udp_recv;
    ngx_send_pt        send;
    ngx_send_pt        udp_send;
    ngx_send_chain_pt  udp_send_chain;
    ngx_send_chain_pt  send_chain;
    ngx_uint_t         flags;
} ngx_os_io_t;
```

Enumerações têm tipos terminando com `_e`:

```c
typedef enum {
    ngx_http_fastcgi_st_version = 0,
    ngx_http_fastcgi_st_type,
    ...
    ngx_http_fastcgi_st_padding
} ngx_http_fastcgi_state_e;
```

<a id="variables-2"></a>

### Variáveis

Variáveis são declaradas ordenadas por comprimento do tipo base, depois alfabeticamente.
Nomes de tipos e nomes de variáveis são alinhados.
As "colunas" de tipo e nome são separadas por dois espaços.
Arrays grandes são colocados no final de um bloco de declaração:

```c
u_char                      *rv, *p;
ngx_conf_t                  *cf;
ngx_uint_t                   i, j, k;
unsigned int                 len;
struct sockaddr             *sa;
const unsigned char         *data;
ngx_peer_connection_t       *pc;
ngx_http_core_srv_conf_t   **cscfp;
ngx_http_upstream_srv_conf_t *us, *uscf;
u_char                       text[NGX_SOCKADDR_STRLEN];
```

Variáveis estáticas e globais podem ser inicializadas na declaração:

```c
static ngx_str_t  ngx_http_memcached_key = ngx_string("memcached_key");
```

```c
static ngx_uint_t  mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
```

```c
static uint32_t  ngx_crc32_table16[] = {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    ...
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
```

Existe um conjunto de combinações tipo/nome comumente usadas:

```c
u_char                        *rv;
ngx_int_t                      rc;
ngx_conf_t                    *cf;
ngx_connection_t              *c;
ngx_http_request_t            *r;
ngx_peer_connection_t         *pc;
ngx_http_upstream_srv_conf_t  *us, *uscf;
```

<a id="functions"></a>

### Funções

Todas as funções (mesmo as estáticas) devem ter protótipos.
Os protótipos incluem nomes de argumentos.
Protótipos longos são quebrados com uma única indentação nas linhas de continuação:

```c
static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
static ngx_int_t ngx_http_init_phases(ngx_conf_t *cf,
    ngx_http_core_main_conf_t *cmcf);

static char *ngx_http_merge_servers(ngx_conf_t *cf,
    ngx_http_core_main_conf_t *cmcf, ngx_http_module_t *module,
    ngx_uint_t ctx_index);
```

O nome da função em uma definição começa em uma nova linha.
As chaves de abertura e fechamento do corpo da função ficam em linhas separadas.
O corpo da função é indentado.
Há duas linhas vazias entre as funções:

```c
static ngx_int_t
ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len)
{
    ...
}


static ngx_int_t
ngx_http_add_addresses(ngx_conf_t *cf, ngx_http_core_srv_conf_t *cscf,
    ngx_http_conf_port_t *port, ngx_http_listen_opt_t *lsopt)
{
    ...
}
```

Não há espaço após o nome da função e o parêntese de abertura.
Chamadas de função longas são quebradas de forma que as linhas de continuação comecem
na posição do primeiro argumento da função.
Se isso for impossível, formate a primeira linha de continuação de forma que ela
termine na posição 79:

```c
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
               "http header: \"%V: %V\"",
               &h->key, &h->value);

hc->busy = ngx_palloc(r->connection->pool,
                  cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *));
```

A macro `ngx_inline` deve ser usada em vez de
`inline`:

```c
static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf);
```

<a id="expressions"></a>

### Expressões

Operadores binários exceto `.` e `->`
devem ser separados de seus operandos por um espaço.
Operadores unários e subscritos não são separados de seus operandos por espaços:

```c
width = width * 10 + (*fmt++ - '0');
```

```c
ch = (u_char) ((decoded << 4) + (ch - '0'));
```

```c
r->exten.data = &r->uri.data[i + 1];
```

Conversões de tipo são separadas por um espaço das expressões convertidas.
Um asterisco dentro de uma conversão de tipo é separado por um espaço do nome do tipo:

```c
len = ngx_sock_ntop((struct sockaddr *) sin6, p, len, 1);
```

Se uma expressão não cabe em uma única linha, ela é quebrada.
O ponto preferido para quebrar uma linha é um operador binário.
A linha de continuação é alinhada com o início da expressão:

```c
if (status == NGX_HTTP_MOVED_PERMANENTLY
    || status == NGX_HTTP_MOVED_TEMPORARILY
    || status == NGX_HTTP_SEE_OTHER
    || status == NGX_HTTP_TEMPORARY_REDIRECT
    || status == NGX_HTTP_PERMANENT_REDIRECT)
{
    ...
}
```

```c
p->temp_file->warn = "an upstream response is buffered "
                     "to a temporary file";
```

Como último recurso, é possível quebrar uma expressão de forma que a
linha de continuação termine na posição 79:

```c
hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)
                                     + size * sizeof(ngx_hash_elt_t *));
```

As regras acima também se aplicam a sub-expressões,
onde cada sub-expressão tem seu próprio nível de indentação:

```c
if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
     || c->stale_updating) && !r->background
    && u->conf->cache_background_update)
{
    ...
}
```

Às vezes, é conveniente quebrar uma expressão após uma conversão de tipo.
Neste caso, a linha de continuação é indentada:

```c
node = (ngx_rbtree_node_t *)
           ((u_char *) lr - offsetof(ngx_rbtree_node_t, color));
```

Ponteiros são explicitamente comparados com
`NULL` (não `0`):

```c
if (ptr != NULL) {
    ...
}
```

<a id="conditionals-and-loops"></a>

### Condicionais e Loops

A palavra-chave `if` é separada da condição
por um espaço.
A chave de abertura fica na mesma linha, ou em uma
linha dedicada se a condição ocupar várias linhas.
A chave de fechamento fica em uma linha dedicada, opcionalmente seguida por
`else if` / `else`.
Geralmente, há uma linha vazia antes da
parte `else if` / `else`:

```c
if (node->left == sentinel) {
    temp = node->right;
    subst = node;

} else if (node->right == sentinel) {
    temp = node->left;
    subst = node;

} else {
    subst = ngx_rbtree_min(node->right, sentinel);

    if (subst->left != sentinel) {
        temp = subst->left;

    } else {
        temp = subst->right;
    }
}
```

Regras de formatação similares se aplicam aos loops `do` e
`while`:

```c
while (p < last && *p == ' ') {
    p++;
}
```

```c
do {
    ctx->node = rn;
    ctx = ctx->next;
} while (ctx);
```

A palavra-chave `switch` é separada da condição
por um espaço.
A chave de abertura fica na mesma linha.
A chave de fechamento fica em uma linha dedicada.
As palavras-chave `case` são alinhadas com
`switch`:

```c
switch (ch) {
case '!':
    looked = 2;
    state = ssi_comment0_state;
    break;

case '<':
    copy_end = p;
    break;

default:
    copy_end = p;
    looked = 0;
    state = ssi_start_state;
    break;
}
```

A maioria dos loops `for` são formatados da seguinte forma:

```c
for (i = 0; i < ccf->env.nelts; i++) {
    ...
}
```

```c
for (q = ngx_queue_head(locations);
     q != ngx_queue_sentinel(locations);
     q = ngx_queue_next(q))
{
    ...
}
```

Se alguma parte da instrução `for` for omitida,
isso é indicado pelo comentário `/* void */`:

```c
for (i = 0; /* void */ ; i++) {
    ...
}
```

Um loop com corpo vazio também é indicado pelo
comentário `/* void */` que pode ser colocado na mesma linha:

```c
for (cl = *busy; cl->next; cl = cl->next) { /* void */ }
```

Um loop infinito fica assim:

```c
for ( ;; ) {
    ...
}
```

<a id="labels"></a>

### Rótulos

Rótulos são cercados por linhas vazias e são indentados no nível anterior:

```c
    if (i == 0) {
        u->err = "host not found";
        goto failed;
    }

    u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_addr_t));
    if (u->addrs == NULL) {
        goto failed;
    }

    u->naddrs = i;

    ...

    return NGX_OK;

failed:

    freeaddrinfo(res);
    return NGX_ERROR;
```

<a id="debugging-memory-issues"></a>

## Depurando Problemas de Memória

Para depurar problemas de memória como estouro de buffer ou erros de uso após liberação, você
pode usar o [AddressSanitizer](https://en.wikipedia.org/wiki/AddressSanitizer)
(ASan), suportado por alguns compiladores modernos.
Para habilitar o ASan com `gcc` e `clang`,
use a opção de compilador e linker `-fsanitize=address`.
Ao compilar o Angie, isso pode ser feito adicionando a opção aos
parâmetros `--with-cc-opt` e `--with-ld-opt`
do script `configure`.

Como a maioria das alocações no Angie são feitas a partir do
[pool](#pool) interno do Angie, habilitar o ASan pode nem sempre ser suficiente para depurar
problemas de memória.
O pool interno aloca um grande bloco de memória do sistema e corta
alocações menores dele.
No entanto, esse mecanismo pode ser desabilitado definindo a
macro `NGX_DEBUG_PALLOC` como `1`.
Neste caso, as alocações são passadas diretamente para o alocador do sistema, dando a ele
controle total sobre os limites dos buffers.

A seguinte linha de configuração resume as informações fornecidas acima.
É recomendada durante o desenvolvimento de módulos de terceiros e teste do Angie em
diferentes plataformas.

```bash
auto/configure --with-cc-opt='-fsanitize=address -DNGX_DEBUG_PALLOC=1'
               --with-ld-opt=-fsanitize=address
```

<a id="common-pitfalls"></a>

## Armadilhas Comuns

<a id="writing-a-c-module"></a>

### Escrevendo um módulo C

A armadilha mais comum é uma tentativa de escrever um módulo C completo
quando isso pode ser evitado.
Na maioria dos casos sua tarefa pode ser realizada criando uma configuração adequada.
Se escrever um módulo for inevitável, tente torná-lo
o mais pequeno e simples possível.
Por exemplo, um módulo pode apenas exportar algumas
[variáveis](#http_variables).

Antes de começar um módulo, considere as seguintes questões:

* É possível implementar uma funcionalidade desejada usando
  [módulos já disponíveis](https://pt.angie.software//angie/docs/configuration/modules/index.md#modules)?
* É possível resolver um problema usando linguagens de script integradas,
  como [Perl](https://pt.angie.software//angie/docs/configuration/modules/http/http_perl.md#http-perl) ou [NJS](https://pt.angie.software//angie/docs/installation/external-modules/njs.md#external-njs)?

<a id="c-strings"></a>

### Strings C

O tipo de string mais usado no Angie,
[ngx_str_t](#string_overview) não é uma string
terminada em zero no estilo C.
Você não pode passar os dados para funções padrão da biblioteca C
como `strlen()` ou `strstr()`.
Em vez disso, devem ser usadas as [contrapartes](#string_overview)
do Angie que aceitam `ngx_str_t` ou
ponteiro para dados e um comprimento.
No entanto, há um caso em que `ngx_str_t` contém
um ponteiro para uma string terminada em zero: strings que vêm como resultado da
análise do arquivo de configuração são terminadas em zero.

<a id="global-variables"></a>

### Variáveis Globais

Evite usar variáveis globais em seus módulos.
Muito provavelmente é um erro ter uma variável global.
Qualquer dado global deve estar vinculado a um [ciclo de configuração](#cycle)
e ser alocado do [pool de memória](#pool) correspondente.
Isso permite ao Angie realizar recarregamentos de configuração suaves.
Uma tentativa de usar variáveis globais provavelmente quebrará essa funcionalidade,
porque será impossível ter duas configurações ao
mesmo tempo e se livrar delas.
Às vezes variáveis globais são necessárias.
Neste caso, atenção especial é necessária para gerenciar a reconfiguração
adequadamente.
Além disso, verifique se as bibliotecas usadas pelo seu código têm estado
global implícito que pode ser quebrado no recarregamento.

<a id="manual-memory-management"></a>

### Gerenciamento Manual de Memória

Em vez de lidar com a abordagem malloc/free que é propensa a erros,
aprenda como usar os [pools](#pool) do Angie.
Um pool é criado e vinculado a um objeto -
[configuração](#http_conf),
[ciclo](#cycle),
[conexão](#http_connection),
ou [requisição HTTP](#http_request).
Quando o objeto é destruído, o pool associado também é destruído.
Então ao trabalhar com um objeto, é possível alocar a quantidade
necessária do pool correspondente e não se preocupar em liberar memória
mesmo em caso de erros.

<a id="dev-threads"></a>

### Threads

É recomendado evitar usar threads no Angie porque isso definitivamente
quebrará as coisas: a maioria das funções do Angie não são thread-safe.
É esperado que uma thread execute apenas chamadas de sistema e
funções de biblioteca thread-safe.
Se você precisar executar algum código que não está relacionado ao processamento de requisições de cliente,
a maneira adequada é agendar um timer no manipulador de módulo `init_process`
e executar as ações necessárias no manipulador do timer.
Internamente o Angie faz uso de [threads](#dev_threads) para
acelerar operações relacionadas a IO, mas este é um caso especial com muitas
limitações.

<a id="blocking-libraries"></a>

### Bibliotecas Bloqueantes

Um erro comum é usar bibliotecas que são bloqueantes internamente.
A maioria das bibliotecas por aí são síncronas e bloqueantes por natureza.
Em outras palavras, elas executam uma operação por vez e desperdiçam
tempo esperando resposta de outro peer.
Como resultado, quando uma requisição é processada com tal biblioteca, todo o
worker do Angie é bloqueado, destruindo assim a performance.
Use apenas bibliotecas que fornecem interface assíncrona e não
bloqueiam todo o processo.

<a id="http-requests-to-external-services"></a>

### Requisições HTTP para Serviços Externos

Frequentemente módulos precisam executar uma chamada HTTP para algum serviço externo.
Um erro comum é usar alguma biblioteca externa, como libcurl,
para executar a requisição HTTP.
É absolutamente desnecessário trazer uma quantidade enorme de código
externo (provavelmente [bloqueante](#blocking-libraries)!)
para a tarefa que pode ser realizada pelo próprio Angie.

Há dois cenários básicos de uso quando uma requisição externa é necessária:

* no contexto de processamento de uma requisição de cliente (por exemplo, em manipulador de conteúdo)
* no contexto de um processo worker (por exemplo, manipulador de timer)

No primeiro caso, o melhor é usar a
[API de subrequests](#http_subrequests).
Em vez de acessar diretamente o serviço externo, você declara uma localização
na configuração do Angie e direciona sua subrequest para esta localização.
Esta localização não está limitada a
[fazer proxy](https://pt.angie.software//angie/docs/configuration/modules/http/http_proxy.md#proxy-pass)
de requisições, mas pode conter outras diretivas do Angie.
Um exemplo de tal abordagem é a
diretiva [auth_request](https://pt.angie.software//angie/docs/configuration/modules/http/http_auth_request.md#id1) implementada em
[Auth Request](https://pt.angie.software//angie/docs/configuration/modules/http/http_auth_request.md#http-auth-request).

Para o segundo caso, é possível usar a funcionalidade básica de cliente HTTP
disponível no Angie.
Por exemplo, o
[módulo OCSP](https://github.com/nginx/nginx/blob/master/src/event/ngx_event_openssl_stapling.c)
implementa um cliente HTTP simples.
