API8 min de leitura

Como Codificar Corretamente Parâmetros de Consulta em APIs REST

Os parâmetros de consulta de APIs REST devem ser codificados em percent-encoding conforme a RFC 3986 para incluir com segurança caracteres especiais como &, =, espaços e Unicode. Use encodeURIComponent() em JavaScript, urllib.parse.quote() em Python ou URLEncoder.encode() em Java.

Por Que os Parâmetros de Consulta Precisam de Codificação

As query strings em APIs REST usam um formato estruturado no qual os pares chave-valor são separados por & e as chaves são separadas dos valores por =. Se o valor de um parâmetro contiver algum desses caracteres delimitadores, ou outros caracteres reservados como #, + ou espaços, a estrutura da query string se rompe e o servidor recebe dados incorretos.

Considere este exemplo: você quer pesquisar por "salt & pepper" em uma API. Sem codificação, a URL /search?q=salt & pepper diz ao servidor que existem dois parâmetros: q=salt e pepper (sem valor). Com a codificação adequada, /search?q=salt%20%26%20pepper envia corretamente um único parâmetro q com o valor "salt & pepper".

Além da correção, a codificação adequada também previne vulnerabilidades de segurança. Entradas de usuário não codificadas em URLs podem levar a ataques de injeção, envenenamento de cache e outras explorações. Sempre codifique os valores dos parâmetros antes de incluí-los em URLs.

Codificação em Diferentes Linguagens

Toda linguagem de programação relevante oferece funções nativas para codificação de URLs. Veja como codificar corretamente parâmetros de consulta nas linguagens mais populares.

// JavaScript
// Use encodeURIComponent() para valores de parâmetros individuais
const query = 'price >= 100 & category = books';
const url = 'https://api.example.com/search?q=' + encodeURIComponent(query);
// "https://api.example.com/search?q=price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// Ou use URLSearchParams para múltiplos parâmetros
const params = new URLSearchParams({
  q: 'price >= 100 & category = books',
  page: '1',
  sort: 'price'
});
const url2 = 'https://api.example.com/search?' + params.toString();
# Python
from urllib.parse import urlencode, quote

# Usando urlencode para múltiplos parâmetros
params = {
    'q': 'price >= 100 & category = books',
    'page': 1,
    'sort': 'price'
}
query_string = urlencode(params)
url = f'https://api.example.com/search?{query_string}'

# Usando quote para um único valor
value = quote('price >= 100 & category = books', safe='')
url = f'https://api.example.com/search?q={value}'
// Java
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

String query = "price >= 100 & category = books";
String encoded = URLEncoder.encode(query, StandardCharsets.UTF_8);
// "price+%3E%3D+100+%26+category+%3D+books"
// Observação: URLEncoder usa + para espaços (codificação de formulário)

// Para a codificação RFC 3986, substitua + por %20
String rfc3986 = encoded.replace("+", "%20");
String url = "https://api.example.com/search?q=" + rfc3986;
// C#
using System.Net;
using System.Web;

string query = "price >= 100 & category = books";

// Uri.EscapeDataString segue a RFC 3986
string encoded = Uri.EscapeDataString(query);
// "price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// HttpUtility.UrlEncode usa codificação de formulário (+ para espaços)
string formEncoded = HttpUtility.UrlEncode(query);
// "price+%3e%3d+100+%26+category+%3d+books"
// Go
package main

import (
    "fmt"
    "net/url"
)

func main() {
    // url.QueryEscape codifica para query strings (+ para espaços)
    encoded := url.QueryEscape("price >= 100 & category = books")
    // "price+%3E%3D+100+%26+category+%3D+books"

    // url.PathEscape codifica para segmentos de caminho (%20 para espaços)
    pathEncoded := url.PathEscape("my file name.pdf")
    // "my%20file%20name.pdf"

    // Usando url.Values para construir query strings
    params := url.Values{}
    params.Set("q", "price >= 100 & category = books")
    params.Set("page", "1")
    queryString := params.Encode()
    fmt.Println(queryString)
}

Codificando Arrays e Objetos Aninhados

APIs REST frequentemente precisam aceitar arrays ou objetos aninhados como parâmetros de consulta. Não existe um padrão único para codificar esses tipos complexos, portanto diferentes APIs adotam convenções diferentes.

// Chaves repetidas (com maior suporte)
// GET /api/items?tag=javascript&tag=python&tag=go
const params = new URLSearchParams();
['javascript', 'python', 'go'].forEach(tag => params.append('tag', tag));

// Notação de colchetes (comum em PHP, Rails, Express com qs)
// GET /api/items?tags[]=javascript&tags[]=python&tags[]=go
// Deve ser codificada manualmente:
const tags = ['javascript', 'python', 'go'];
const qs = tags.map(t => 'tags[]=' + encodeURIComponent(t)).join('&');

// Separado por vírgulas (simples, porém limitado)
// GET /api/items?tags=javascript,python,go
const tagList = encodeURIComponent('javascript,python,go');

// Objetos aninhados (notação de colchetes)
// GET /api/search?filter[status]=active&filter[min_price]=10
// Em Python:
params = {
    'filter[status]': 'active',
    'filter[min_price]': '10'
}

Sempre consulte a documentação da sua API para saber o formato esperado. Ao projetar uma nova API, a abordagem de chaves repetidas é a mais portável entre linguagens de programação e bibliotecas HTTP.

Boas Práticas de Decodificação no Servidor

Ao lidar com requisições recebidas no lado do servidor, a maioria dos frameworks web decodifica automaticamente os parâmetros de consulta para você. No entanto, há considerações importantes a ter em mente para um tratamento robusto no servidor.

  • A maioria dos frameworks (Express, Django, Spring, ASP.NET) decodifica os parâmetros de consulta automaticamente. Não os decodifique manualmente de novo, ou você fará uma dupla decodificação.
  • Valide os valores decodificados em relação aos tipos e intervalos esperados antes de usá-los.
  • Defina limites máximos de comprimento de URL no nível do servidor web (comumente 2048 ou 8192 caracteres).
  • Trate o caso em que + pode significar tanto um espaço quanto um sinal de mais literal, dependendo do content type.
  • Registre a URL original (codificada) para depuração, pois valores decodificados podem ser enganosos nos logs.
// Express.js - os parâmetros são decodificados automaticamente
app.get('/search', (req, res) => {
  const query = req.query.q; // Já decodificado
  // NÃO faça: decodeURIComponent(req.query.q)

  // Valide a entrada
  if (typeof query !== 'string' || query.length > 200) {
    return res.status(400).json({ error: 'Invalid query parameter' });
  }

  // Use o valor decodificado com segurança
  const results = search(query);
  res.json(results);
});

Considerações de Segurança

A codificação adequada dos parâmetros de consulta é uma parte essencial da segurança de APIs. A seguir estão as práticas de segurança mais importantes a serem seguidas.

  • Nunca confie na codificação feita no cliente. Sempre valide e sanitize os parâmetros decodificados no servidor, mesmo que o cliente os tenha codificado corretamente.
  • Fique atento a ataques de dupla codificação. Um atacante pode codificar caracteres maliciosos duas vezes para contornar filtros de entrada que decodificam apenas uma vez. Garanta que seus filtros de segurança vejam os valores totalmente decodificados.
  • Previna path traversal. Sequências codificadas como %2e%2e%2f (../) em parâmetros de caminho podem ser usadas para acessar arquivos fora do diretório pretendido. Decodifique e valide os caminhos antes de operações com arquivos.
  • Use consultas parametrizadas. Mesmo após a decodificação da URL, nunca concatene a entrada do usuário diretamente em consultas SQL ou NoSQL. Use consultas parametrizadas ou um ORM.
  • Limite o comprimento da URL. Query strings extremamente longas podem causar negação de serviço. Configure seu servidor web para rejeitar URLs além de um comprimento razoável.
  • Codifique também a saída. Ao refletir valores de parâmetros de consulta de volta em respostas HTML, aplique a codificação de entidades HTML para prevenir ataques de cross-site scripting (XSS).

Artigos relacionados

Experimente as nossas ferramentas gratuitas