---
title: "req.headers.append em Zig: Como Corrigir no std.http.Client"
url: "https://ziglang.com.br/troubleshooting/req-headers-append-zig/"
markdown_url: "https://ziglang.com.br/troubleshooting/req-headers-append-zig.MD"
description: "Seu código com req.headers.append parou de compilar? Entenda a mudança da API HTTP do Zig e use extra_headers, fetch e Bearer token corretamente."
date: "2026-07-27"
author: "Zig Brasil"
---

# req.headers.append em Zig: Como Corrigir no std.http.Client

Seu código com req.headers.append parou de compilar? Entenda a mudança da API HTTP do Zig e use extra_headers, fetch e Bearer token corretamente.


Se um exemplo com `try req.headers.append("Nome", "valor")` parou de compilar, a correção mais comum nas versões recentes do Zig é **não alterar os headers depois de criar a requisição**. Passe os cabeçalhos como uma lista de `std.http.Header` em `extra_headers`, normalmente usando `std.http.Client.fetch`. A API HTTP da biblioteca padrão mudou várias vezes antes do Zig 1.0, por isso muitos snippets antigos encontrados em fóruns e repositórios já não correspondem ao release instalado.

A substituição direta costuma ser esta:

```zig
// Exemplo antigo encontrado na internet:
try req.headers.append("User-Agent", "minha-app/1.0");
try req.headers.append("Accept", "application/json");
```

```zig
// Padrão atual com fetch:
const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/dados" },
    .extra_headers = &.{
        .{ .name = "User-Agent", .value = "minha-app/1.0" },
        .{ .name = "Accept", .value = "application/json" },
    },
    .response_storage = .{ .dynamic = &body },
});
```

Este guia explica por que o erro acontece, como migrar GET, POST, Bearer token e API key, e quais detalhes verificar quando o código ainda falha.

## Resposta rápida

| Código ou objetivo | Caminho recomendado |
|---|---|
| `req.headers.append(...)` não existe | Passe `extra_headers = &.{ ... }` nas opções da operação HTTP |
| GET simples | Use `client.fetch` com `location`, `extra_headers` e `response_storage` |
| POST JSON | Use `method = .POST`, `payload` e o header tipado de `content_type` |
| Bearer token dinâmico | Monte o valor em um buffer que continue válido durante a chamada |
| Header conhecido da stdlib | Prefira o campo tipado em `headers` quando ele existir |
| Header customizado | Use `extra_headers` com pares `.name` e `.value` |
| Exemplo de outra versão | Confirme a versão com `zig version` e consulte a documentação correspondente |

Para uma visão completa do cliente, veja o tutorial de [`std.http.Client`](/tutoriais/zig-http-client/). Se você precisa apenas copiar uma requisição pronta, consulte as receitas de [HTTP GET em Zig](/receitas/zig-http-get-request/) e [HTTP POST em Zig](/receitas/zig-http-post-request/).

## Por que `req.headers.append` deixou de funcionar?

Zig ainda está antes da versão 1.0, então APIs da biblioteca padrão podem mudar entre releases. O módulo `std.http` passou por redesigns que alteraram a criação da requisição, os tipos de headers, a sequência de envio e as abstrações de I/O.

Um exemplo antigo pode falhar com mensagens parecidas com estas:

```text
error: no field named 'headers' in struct 'http.Client.Request'
```

```text
error: no field or member function named 'append'
```

```text
error: expected type '[]const http.Header', found ...
```

Esses erros não significam necessariamente que headers customizados foram removidos. Em geral, significa que eles agora são fornecidos como **configuração da operação**, em vez de serem anexados por mutação depois que o objeto foi criado.

A primeira etapa do diagnóstico é sempre registrar o release real:

```bash
zig version
```

Depois, compare o código com a documentação desse release. Não misture um exemplo de Zig 0.12, outro de 0.14 e tipos de 0.16 no mesmo arquivo. Essa combinação é uma das causas mais frequentes de erros em `std.http`.

## GET com headers usando `extra_headers`

O exemplo abaixo faz um GET, envia `User-Agent` e `Accept`, limita a memória disponível para a resposta e verifica o status HTTP.

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var client = std.http.Client{ .allocator = allocator };
    defer client.deinit();

    var body = std.ArrayList(u8).init(allocator);
    defer body.deinit();

    const result = try client.fetch(.{
        .location = .{
            .url = "https://api.github.com/repos/ziglang/zig",
        },
        .extra_headers = &.{
            .{ .name = "User-Agent", .value = "zig-exemplo/1.0" },
            .{ .name = "Accept", .value = "application/vnd.github+json" },
        },
        .response_storage = .{ .dynamic = &body },
    });

    if (result.status != .ok) {
        std.log.err("API respondeu com status {d}", .{
            @intFromEnum(result.status),
        });
        return error.HttpStatusInesperado;
    }

    std.debug.print("{s}\n", .{body.items});
}
```

`extra_headers` recebe uma slice de `std.http.Header`. A sintaxe `&.{ ... }` cria uma lista literal adequada para valores fixos. Para integrações reais, mantenha um limite operacional para a resposta; a forma exata desse limite depende da API de `response_storage` disponível no seu release e da estratégia usada pelo programa.

## Header tipado ou `extra_headers`?

As opções de `fetch` normalmente separam headers conhecidos de headers arbitrários. Um `Content-Type` pode ter um campo tipado, enquanto `X-API-Key`, `Idempotency-Key` ou um header específico do fornecedor entra em `extra_headers`.

Exemplo de POST JSON:

```zig
const payload =
    \\{"nome":"Ana","ativo":true}
;

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/usuarios" },
    .method = .POST,
    .headers = .{
        .content_type = .{ .override = "application/json" },
    },
    .extra_headers = &.{
        .{ .name = "Accept", .value = "application/json" },
        .{ .name = "User-Agent", .value = "minha-api-client/1.0" },
    },
    .payload = payload,
    .response_storage = .{ .dynamic = &body },
});
```

A regra prática é:

1. use o campo tipado quando a versão instalada o oferecer;
2. use `extra_headers` para extensões e valores sem campo próprio;
3. não envie duas versões conflitantes do mesmo header;
4. confira se o nome e o valor continuam vivos durante a operação.

## Authorization Bearer com valor dinâmico

Tokens normalmente chegam por variável de ambiente, arquivo seguro ou serviço de credenciais. Como o valor completo precisa incluir o prefixo `Bearer `, você pode montá-lo em um buffer local.

```zig
var authorization_buffer: [2048]u8 = undefined;
const authorization = try std.fmt.bufPrint(
    &authorization_buffer,
    "Bearer {s}",
    .{token},
);

const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/conta" },
    .extra_headers = &.{
        .{ .name = "Authorization", .value = authorization },
        .{ .name = "Accept", .value = "application/json" },
    },
    .response_storage = .{ .dynamic = &body },
});
```

O buffer precisa permanecer válido até `fetch` terminar. Não devolva uma slice apontando para uma variável local que já saiu de escopo e não reutilize o mesmo buffer em operações concorrentes.

Também evite imprimir o header em logs. Em produção, registre que a autenticação foi configurada, mas nunca o token. O guia de [configuração segura e segredos em Zig](/artigos/zig-configuracao-segura-segredos-env/) detalha esse cuidado.

## API key e headers específicos

Para uma chave enviada em `X-API-Key`, a configuração é direta:

```zig
const result = try client.fetch(.{
    .location = .{ .url = "https://api.example.com/relatorio" },
    .extra_headers = &.{
        .{ .name = "X-API-Key", .value = api_key },
        .{ .name = "Accept", .value = "application/json" },
    },
    .response_storage = .{ .dynamic = &body },
});
```

Antes de implementar, confirme como o fornecedor espera receber a credencial. Algumas APIs usam `Authorization: Bearer`, outras `X-API-Key`, e sistemas legados podem exigir nomes próprios. Não mova uma chave para a query string apenas para contornar um problema de header: URLs aparecem com mais facilidade em logs, histórico, métricas e traces.

## Migração de um exemplo antigo passo a passo

Considere este padrão antigo:

```zig
var req = try client.request(.GET, uri, .{
    .allocator = allocator,
}, .{});
defer req.deinit();

try req.headers.append("User-Agent", "app/1.0");
try req.headers.append("Accept", "application/json");

try req.start();
try req.finish();
try req.wait();
```

Para migrá-lo sem carregar partes incompatíveis da API antiga:

1. mantenha a criação e o `deinit` do `std.http.Client`;
2. substitua a sequência manual por `client.fetch` quando ela atender ao caso;
3. mova URL e método para as opções de `fetch`;
4. converta cada `append(nome, valor)` em um `std.http.Header`;
5. defina onde o corpo da resposta será armazenado;
6. valide `result.status` antes de fazer parse do body;
7. rode `zig fmt` e os testes do projeto.

O equivalente fica conceitualmente assim:

```zig
const result = try client.fetch(.{
    .location = .{ .url = url },
    .method = .GET,
    .extra_headers = &.{
        .{ .name = "User-Agent", .value = "app/1.0" },
        .{ .name = "Accept", .value = "application/json" },
    },
    .response_storage = .{ .dynamic = &body },
});
```

Essa migração é melhor do que tentar encontrar um novo lugar para chamar `append`, pois evita misturar o ciclo de vida antigo da requisição com as opções atuais.

## O que verificar se `extra_headers` também der erro

### 1. A versão do exemplo não é a sua

Confirme:

```bash
zig version
```

Se o projeto fixa uma versão em CI, container, `mise`, `asdf` ou `zigup`, use a mesma localmente. “Funciona na minha máquina” costuma significar apenas que duas versões diferentes estão compilando APIs diferentes.

### 2. O tipo esperado mudou

Leia a assinatura de `FetchOptions` na documentação ou no código da stdlib instalada. O compilador do Zig normalmente mostra o tipo esperado e a origem da declaração. Siga essa trilha em vez de aplicar casts aleatórios.

### 3. O valor do header não vive tempo suficiente

Um header guarda slices; ele não necessariamente copia todos os valores. Strings literais vivem pelo programa inteiro, mas valores formatados precisam permanecer válidos durante a chamada.

### 4. Existem headers duplicados

Evite definir `Content-Type` tanto em `.headers.content_type` quanto em `.extra_headers`. Duplicidade pode causar rejeição pelo servidor ou comportamento ambíguo em proxies.

### 5. Você precisa da API de baixo nível

`fetch` resolve GET, POST e boa parte das integrações REST. Streaming de upload, controle fino da conexão ou protocolos long-lived podem exigir APIs de nível mais baixo, que são mais sensíveis à versão. Nesse caso, consulte a documentação exata do release e mantenha esse código isolado em um adaptador pequeno.

## Checklist para headers HTTP em Zig

- [ ] Executei `zig version` e usei documentação do mesmo release.
- [ ] Troquei `req.headers.append` por opções compatíveis com a versão atual.
- [ ] Usei `extra_headers` para headers customizados.
- [ ] Usei o campo tipado para `Content-Type` quando disponível.
- [ ] Mantive buffers dinâmicos vivos durante a requisição.
- [ ] Não registrei token, cookie, API key ou header `Authorization`.
- [ ] Validei o status HTTP antes de interpretar JSON.
- [ ] Limitei o tamanho da resposta conforme o risco da integração.
- [ ] Reutilizei `std.http.Client` quando faço várias chamadas.
- [ ] Fixei a versão do Zig no CI e no ambiente de desenvolvimento.

## Conclusão

O erro em `req.headers.append` quase sempre é um sinal de **exemplo desatualizado**, não de ausência de suporte a headers no Zig. Para requisições comuns, passe os cabeçalhos em `extra_headers` dentro das opções de `std.http.Client.fetch`; use campos tipados para headers conhecidos e mantenha valores dinâmicos válidos durante toda a chamada.

A lição mais importante é não migrar `std.http` linha por linha entre versões. Migre a operação inteira — criação, headers, body, armazenamento da resposta e validação de status — usando uma única API coerente com o release do projeto.

Para continuar, leia [Zig HTTP Client: GET, POST, JSON e APIs REST](/tutoriais/zig-http-client/), a receita de [HTTP GET com `std.http.Client`](/receitas/zig-http-get-request/) e o guia de [tratamento de erros em Zig](/tutoriais/tratamento-de-erros-em-zig/).
