Tema representativo de entrevista

Entrevista de backend: ¿Cómo diseñarías HTTP Structured Fields evolucionables?

BackendDifícil
Equipo editorial de Offer.ccPublicado Actualizado

Pregunta

Necesitas agregar un campo de respuesta HTTP que transporte capacidades y parámetros a una API pública. ¿Cómo utilizarías Structured Fields para definir la sintaxis, manejar campos duplicados y entradas no válidas, y mantener seguros a los clientes antiguos?

Planteamiento y alcance

Una API pública necesita un campo de respuesta Features que contenga nombres de capacidades, prioridades y parámetros de experimentos. Clientes, CDNs, gateways y SDKs en varios lenguajes lo leerán; los clientes heredados solo pueden ignorar los campos desconocidos. Diseña el formato del campo, las reglas de serialización y parseo, la política de compatibilidad y el plan de verificación.

Esta es una pregunta sobre contratos de API de backend. La clave es transformar un "header tipo string" en un protocolo interoperable. La RFC 8941 define el modelo común de Item, List, Dictionary y parámetros, y la RFC 9651 es su revisión. La RFC 9110 exige que los campos nuevos especifiquen su gramática y rechacen caracteres de control peligrosos. No necesitas implementar cada algoritmo de las RFC, pero debes definir los límites.

Qué está evaluando el entrevistador

El entrevistador quiere ver si defines la semántica antes de elegir List, Dictionary o Item en lugar de concatenar texto separado por comas. Una respuesta sólida cubre la serialización del emisor, el parseo del receptor, los miembros desconocidos, la combinación de campos duplicados, los límites de tamaño y la telemetría.

Una respuesta débil muestra un único valor de ejemplo. Una respuesta sólida explica por qué un conjunto de capacidades es un Dictionary, por qué las claves de los parámetros van en minúsculas, por qué el texto arbitrario no ASCII no debe ocultarse en un String y cómo una falla de parseo evita habilitar accidentalmente una funcionalidad. Las guías actuales de entrevistas de API de backend también enfatizan los contratos estables, la compatibilidad hacia atrás y los modos de falla.

Preguntas para aclarar primero

Semántica del campo y límite de confianza

Confirma si se trata de una sugerencia (hint), una decisión de autorización o un hecho de negocio. Si afecta permisos, facturación o seguridad, el servidor sigue siendo la autoridad y no debe confiar en lo que el cliente devuelva como eco. Pregunta si el campo se puede almacenar en caché y si su valor varía según el usuario.

Tipo y envolvente de compatibilidad

Pregunta si el valor es un conjunto no ordenado de capacidades, una lista ordenada por prioridad o un único identificador de versión. Confirma si los clientes antiguos deben seguir funcionando, si pueden aparecer nuevos parámetros y si los gateways combinan líneas de campos duplicados. Esas respuestas determinan el tipo de contenedor y la política para miembros desconocidos.

Presupuestos de fallas y recursos

Decide si una entrada no válida hace que se ignore todo el campo, un solo miembro o la respuesta completa. Establece límites de bytes, miembros, anidamiento y tiempo de parseo; estas elecciones forman parte del límite de protección contra DoS.

Marco de respuesta de 30 segundos

"Definiría esto como un contrato de máquina versionable, no como JSON oculto en un string. Un conjunto de capacidades utiliza un Dictionary, donde cada clave transporta un Item booleano o parametrizado; las claves y los parámetros siguen las reglas de serialización de la RFC, y los miembros desconocidos se ignoran. El servidor emite ASCII restringido y aplica límites de tamaño total y de miembros. Los receptores usan la misma gramática, tratan la sintaxis no válida como la ausencia del campo y nunca infieren que una funcionalidad está habilitada. Probaría la combinación de campos duplicados y la variación de caché en el gateway, haría primero un parseo en la sombra (shadow-parsing) y compararía fallas de parseo, tamaño del campo y habilitaciones accidentales de funcionalidades antes del despliegue".

Solución paso a paso

Paso 1: Modelar el valor antes de elegir un contenedor

Usa un Dictionary para interruptores de capacidades, como search;v=2, upload=?1. Usa una List cuando cada miembro tenga un orden o parámetros significativos. Usa un Item para una sola versión o nombre de política. No coloques JSON dentro de un header simplemente por conveniencia: los intermediarios y SDKs aún necesitarán un parser a medida.

Paso 2: Definir un campo extensible

Define claves como search y upload; parámetros como v=2 y tier="pro" utilizan únicamente los tipos permitidos por la gramática de structured fields. Las claves de parámetros van en minúsculas. Mantén el texto para visualización fuera del campo, o utiliza una extensión Display String soportada explícitamente tras verificar cada intermediario. Documenta la semántica de cada miembro, su valor por defecto y la consecuencia de un valor no válido.

http
Features: search;v=2, upload=?1

La serialización debe ser determinista para que valores equivalentes no produzcan diferencias innecesarias en las claves de caché o en las firmas. Los receptores no deben reemplazar un parser consciente de la gramática por split(','); las comas, paréntesis, comillas y parámetros tienen límites definidos.

Paso 3: Especificar campos duplicados y miembros desconocidos

Primero indica si se permiten líneas repetidas. Si el campo es un Dictionary, el middleware puede combinar líneas, por lo que el contrato debe definir el significado combinado y una regla de conflicto para claves duplicadas. Ignora claves desconocidas y parámetros opcionales por defecto. Para una clave conocida con un tipo no válido, descarta ese miembro o el campo completo, pero haz que la elección sea normativa. Un interruptor de seguridad nunca debe habilitarse porque el parseo haya fallado.

Paso 4: Construir un límite de parseo estricto pero utilizable

Limita los bytes totales, los miembros, la profundidad de anidamiento y el tiempo de CPU antes de realizar un parseo profundo. Rechaza CR, LF, NUL y otros caracteres fuera de la gramática del campo. La entrada externa no requiere un parseo en tiempo constante, pero las rutas de excepción no deben parsear repetidamente un valor enorme. Registra fallas categorizadas sin guardar en el log todo el campo potencialmente confidencial.

Paso 5: Manejar almacenamiento en caché, firmas y evolución

Si el campo varía según el usuario o la cohorte de experimento, utiliza el comportamiento de respuesta Vary correcto o caché privada; de lo contrario, una CDN puede exponer las capacidades de un usuario a otro. Si el campo está cubierto por HTTP Message Signatures, los firmantes y verificadores necesitan el mismo valor estructurado canónico. Las claves aditivas y los parámetros opcionales deben permanecer ignorables para clientes antiguos; eliminar o cambiar la semántica requiere una versión o una ventana de migración.

Paso 6: Demostrar el diseño con despliegue y contraejemplos

Realiza primero un shadow-parsing sin cambiar el comportamiento, luego habilítalo para una pequeña cohorte interna. Prueba claves duplicadas, listas vacías, comillas rotas, parámetros desconocidos, campos excesivamente grandes, combinación por proxies y desajustes de caché. Compara el éxito de parseo, habilitaciones accidentales, bytes de respuesta, CPU, aciertos de caché y versiones de SDK con y sin el campo. Cada falla de parseo vuelve al valor predeterminado seguro.

Respuesta de muestra de alta calidad

Trataría esto como un problema de diseño de protocolos. Primero confirmaría si el campo es solo una sugerencia de capacidad; si controla autorización, el servidor sigue siendo la autoridad. Para un conjunto de capacidades elegiría un Dictionary de Structured Fields y definiría cada clave como un Item booleano o parametrizado. No usaría una List para capacidades no ordenadas. El contrato especificaría la serialización, tipos de parámetros, líneas duplicadas, miembros desconocidos y las consecuencias de valores no válidos.

El emisor emite ASCII restringido y aplica límites de tamaño de campo y de miembros. El receptor utiliza un parser compatible con RFC en lugar de dividir por comas, rechaza caracteres de control, ignora claves desconocidas y trata una clave conocida con el tipo incorrecto como ausente. El gateway tiene una regla fija de combinación de duplicados, nunca un "el último valor gana" accidental.

También revisaría el comportamiento de caché y firmas: las capacidades específicas de usuario requieren Vary, caché privada o no almacenar en caché, y ambos lados de una firma deben normalizar el valor de forma idéntica. Haría shadow-parsing y luego un despliegue canary del campo mientras monitoreo fallas de parseo, habilitaciones accidentales, tamaño y CPU. Los clientes antiguos continúan ignorando el campo; solo los clientes que soportan explícitamente la versión habilitan el nuevo comportamiento.

Errores comunes

  • Poner JSON en un header de texto → Los proxies y SDKs aún necesitan parseo personalizado, con escape inconsistente y semántica de duplicados inconsistente → Usa el modelo Item, List o Dictionary de la RFC y documenta el significado de los miembros.
  • Parsear con split(',') Las comillas, listas internas y delimitadores de parámetros se cortan incorrectamente → Usa un parser consciente de la gramática y pruebas de sintaxis no válida.
  • Fallar ante cada parámetro desconocido → Los nuevos emisores no pueden interoperar con clientes antiguos → Ignora los parámetros de extensión a menos que falle una restricción de seguridad conocida.
  • Habilitar una funcionalidad tras una falla de parseo → El truncamiento o la manipulación de intermediarios pueden convertirse en un experimento o privilegio accidental → Vuelve a un valor predeterminado seguro y registra una falla categorizada.
  • Ignorar la variación de caché → Una CDN puede reutilizar capacidades personalizadas para otro usuario → Configura Vary, usa caché privada o no almacenes la respuesta en caché.

Preguntas de seguimiento y respuestas

Pregunta de seguimiento 1: ¿Por qué no poner esto en el JSON de respuesta?

JSON puede ser mejor cuando la capacidad es únicamente un dato de negocio en el cuerpo. Structured Fields son útiles cuando los metadatos HTTP, los gateways y la política de caché necesitan inspeccionar el valor antes de consumir el cuerpo. No otorgues autoridad independiente a ambas representaciones; si ambas existen, define la precedencia y detecta discrepancias.

Pregunta de seguimiento 2: ¿Qué sucede si varios proxies combinan el campo?

Especifica si las líneas repetidas son válidas y normalízalas en una única entrada para el parser en un límite de confianza. Para un Dictionary, rechaza claves duplicadas o define una regla de conflicto explícita; no dependas de cuál valor resulta ser el último. Las pruebas de integración deben cubrir líneas repetidas en HTTP/1.1, la representación de campos en HTTP/2 y la ruta real de la CDN.

Pregunta de seguimiento 3: ¿Qué pasa si un nuevo parámetro necesita texto no ASCII?

No coloques UTF-8 directamente en un tipo String que esté limitado por la gramática elegida. Define y verifica una extensión Display String soportada, o mantén el texto para visualización en el cuerpo y transporta un identificador estable en el campo. Habilítalo únicamente después de que cada intermediario y SDK soporte el tipo.

Pregunta de seguimiento 4: El parser causa un pico de CPU. ¿Qué haces?

Ajusta inmediatamente los límites de bytes, miembros, anidamiento y cantidad de parámetros, y trata los campos que superen los límites como ausentes. Conserva un hash de la entrada y la categoría de falla para el diagnóstico, no el valor completo. Mover el parseo a un worker restringido puede reducir el radio de impacto, pero no reemplaza los límites gramaticales y un rollback del canary.

Fuentes públicas

Preguntas relacionadas