API8 min de lectura

Cómo codificar correctamente los parámetros de consulta en las APIs REST

Los parámetros de consulta de las APIs REST deben codificarse en formato percent-encoding según el RFC 3986 para incluir de forma segura caracteres especiales como &, =, espacios y Unicode. Usa encodeURIComponent() en JavaScript, urllib.parse.quote() en Python o URLEncoder.encode() en Java.

Por qué los parámetros de consulta necesitan codificación

Las cadenas de consulta de las APIs REST utilizan un formato estructurado en el que los pares clave-valor se separan mediante & y las claves se separan de los valores mediante =. Si el valor de un parámetro contiene alguno de estos caracteres delimitadores, u otros caracteres reservados como #, + o espacios, la estructura de la cadena de consulta se rompe y el servidor recibe datos incorrectos.

Considera este ejemplo: quieres buscar "salt & pepper" en una API. Sin codificación, la URL /search?q=salt & pepper le indica al servidor que hay dos parámetros: q=salt y pepper (sin valor). Con la codificación adecuada, /search?q=salt%20%26%20pepper envía correctamente un único parámetro q con el valor "salt & pepper".

Más allá de la corrección, una codificación adecuada también previene vulnerabilidades de seguridad. La entrada del usuario sin codificar en las URL puede dar lugar a ataques de inyección, envenenamiento de caché y otros exploits. Codifica siempre los valores de los parámetros antes de incluirlos en las URL.

Codificación en distintos lenguajes

Todos los lenguajes de programación importantes ofrecen funciones integradas para la codificación de URL. A continuación te mostramos cómo codificar correctamente los parámetros de consulta en los lenguajes más populares.

// JavaScript
// Usa encodeURIComponent() para los valores de parámetros individuales
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"

// O usa URLSearchParams para múltiples 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últiples 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 un ú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"
// Nota: URLEncoder usa + para los espacios (codificación de formularios)

// Para la codificación RFC 3986, reemplaza + 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 sigue el RFC 3986
string encoded = Uri.EscapeDataString(query);
// "price%20%3E%3D%20100%20%26%20category%20%3D%20books"

// HttpUtility.UrlEncode usa la codificación de formularios (+ para los espacios)
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 cadenas de consulta (+ para los espacios)
    encoded := url.QueryEscape("price >= 100 & category = books")
    // "price+%3E%3D+100+%26+category+%3D+books"

    // url.PathEscape codifica para segmentos de ruta (%20 para los espacios)
    pathEncoded := url.PathEscape("my file name.pdf")
    // "my%20file%20name.pdf"

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

Codificación de arrays y objetos anidados

Las APIs REST a menudo necesitan aceptar arrays u objetos anidados como parámetros de consulta. No existe un estándar único para codificar estos tipos complejos, por lo que las distintas APIs utilizan convenciones diferentes.

// Claves repetidas (las más ampliamente compatibles)
// GET /api/items?tag=javascript&tag=python&tag=go
const params = new URLSearchParams();
['javascript', 'python', 'go'].forEach(tag => params.append('tag', tag));

// Notación de corchetes (habitual en PHP, Rails, Express con qs)
// GET /api/items?tags[]=javascript&tags[]=python&tags[]=go
// Debe codificarse manualmente:
const tags = ['javascript', 'python', 'go'];
const qs = tags.map(t => 'tags[]=' + encodeURIComponent(t)).join('&');

// Separados por comas (simple pero limitado)
// GET /api/items?tags=javascript,python,go
const tagList = encodeURIComponent('javascript,python,go');

// Objetos anidados (notación de corchetes)
// GET /api/search?filter[status]=active&filter[min_price]=10
// En Python:
params = {
    'filter[status]': 'active',
    'filter[min_price]': '10'
}

Consulta siempre la documentación de tu API para conocer el formato esperado. Al diseñar una nueva API, el enfoque de claves repetidas es el más portable entre lenguajes de programación y bibliotecas HTTP.

Buenas prácticas de decodificación en el servidor

Al gestionar las solicitudes entrantes en el lado del servidor, la mayoría de los frameworks web decodifican automáticamente los parámetros de consulta por ti. Sin embargo, hay consideraciones importantes que tener en cuenta para un manejo robusto en el servidor.

  • La mayoría de los frameworks (Express, Django, Spring, ASP.NET) decodifican los parámetros de consulta automáticamente. No los decodifiques manualmente de nuevo, o realizarás una doble decodificación.
  • Valida los valores decodificados frente a los tipos y rangos esperados antes de usarlos.
  • Establece límites máximos de longitud de URL a nivel del servidor web (habitualmente 2048 u 8192 caracteres).
  • Gestiona el caso en el que + pueda significar tanto un espacio como un signo de suma literal, dependiendo del tipo de contenido.
  • Registra la URL original (codificada) para depuración, ya que los valores decodificados pueden resultar engañosos en los registros.
// Express.js - los parámetros se decodifican automáticamente
app.get('/search', (req, res) => {
  const query = req.query.q; // Ya decodificado
  // NO hagas: decodeURIComponent(req.query.q)

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

  // Usa el valor decodificado de forma segura
  const results = search(query);
  res.json(results);
});

Consideraciones de seguridad

La codificación adecuada de los parámetros de consulta es una parte clave de la seguridad de las APIs. Estas son las prácticas de seguridad más importantes que debes seguir.

  • Nunca confíes en la codificación del lado del cliente. Valida y sanea siempre los parámetros decodificados en el servidor, incluso si el cliente los codificó correctamente.
  • Vigila los ataques de doble codificación. Un atacante podría codificar caracteres maliciosos dos veces para eludir los filtros de entrada que solo decodifican una vez. Asegúrate de que tus filtros de seguridad vean los valores completamente decodificados.
  • Evita el path traversal. Las secuencias codificadas como %2e%2e%2f (../) en los parámetros de ruta pueden utilizarse para acceder a archivos fuera del directorio previsto. Decodifica y valida las rutas antes de realizar operaciones con archivos.
  • Usa consultas parametrizadas. Incluso después de la decodificación de la URL, nunca concatenes la entrada del usuario directamente en consultas SQL o NoSQL. Usa consultas parametrizadas o un ORM.
  • Limita la longitud de la URL. Las cadenas de consulta extremadamente largas pueden provocar una denegación de servicio. Configura tu servidor web para rechazar las URL que superen una longitud razonable.
  • Codifica también la salida. Al reflejar los valores de los parámetros de consulta en las respuestas HTML, aplica la codificación de entidades HTML para prevenir ataques de cross-site scripting (XSS).

Artículos relacionados

Prueba nuestras herramientas gratuitas