Typed parsers and formatters for common HTTP header values
Los mantenedores suelen responder en 1 día
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Problem
effect/http treats header values as plain strings. Each place that needs to understand a value parses it on the spot, and the copies disagree.
Retry-After is parsed in eight places with six different rules. RFC 9110 §10.2.3 allows whole seconds or an HTTP date. For the invalid value -5:
HttpClient(http/HttpClient.ts:1461) falls through toDate.parse("-5"), which V8 reads as a date in 2001, so it retries after 1 ms.- The OTLP exporter and the Anthropic, OpenAI, OpenRouter and OpenAI-compatible clients return a delay of −5 seconds. These four AI clients also ignore HTTP dates and accept
1e3andInfinity. - GraphQL and Cloudflare return
undefined, and the typesafe client returns 0.
Other examples on main:
- Media types are matched by substring (
HttpServerRequest.ts:274,GraphQLProtocol.ts:260,HttpStaticServer.ts:438). The static server treatsAccept: text/html;q=0, which means "never send HTML", as asking for HTML. - There are three separate
Accept-style parsers: compression,McpServerand HttpApi. - HTTP dates go through
Date.parse, which reads the asctime format in local time. WithTZ=America/New_York,Sun Nov 6 08:49:37 1994comes out five hours off. Etagcan format a tag but not parse or compare one. The static server splitsIf-None-Matchon raw commas (HttpStaticServer.ts:448), but a comma is valid inside a tag.- There is nothing for
Cache-Control,Range,Link,WWW-Authenticateor Structured Fields.
Two related bugs are filed separately: basicAuth encoding (#9678) and multipart filenames (#9679).
Proposal
Add one small module per header family to effect/http. Each one provides:
- an immutable value;
parse, which returns aResultand is forgiving where the RFC allows;format, which always produces the canonical form;- an
Equivalence; - a Schema codec from string, so the value can be used directly in HttpApi
headersschemas and inWithHeaders.
| Module | Standard |
|---|---|
MediaType |
RFC 9110 §8.3.1 |
Accept, AcceptEncoding, AcceptLanguage, with negotiation |
RFC 9110 §12.5, RFC 4647 |
ContentDisposition |
RFC 6266, RFC 8187 |
HttpDate, RetryAfter |
RFC 9110 §5.6.7, §10.2.3 |
Etag lists and comparison, conditional requests |
RFC 9110 §8.8.3, §13 |
Range, ContentRange |
RFC 9110 §14 |
CacheControl |
RFC 9111 §5.2 |
Link |
RFC 8288 |
Authorization, WWW-Authenticate (Basic, Bearer) |
RFC 9110 §11, RFC 7617, RFC 6750 |
StructuredField |
RFC 9651 |
// names illustrative
RetryAfter.parse("Wed, 21 Oct 2015 07:28:00 GMT") // Result<RetryAfter, HeaderValueError>
RetryAfter.delay(value, now) // Duration, never negative
Etag.parseList(`"a,b", W/"c"`) // two tags
HttpApiEndpoint.get("file", "/file", {
headers: { "if-none-match": Schema.optional(Etag.ListFromString) }
})
Then switch Effect's own call sites over to these modules.
Why in Effect
- Effect's own code needs these parsers, and today every bug has to be fixed in every copy.
- Header values are wire data. Schema codecs give HttpApi users typed headers, decode errors and OpenAPI output without writing their own parsers.
- Other ecosystems provide them too. Go has
mime.ParseMediaType,http.ParseTime, and precondition and range handling inhttp.ServeContent. Rust has theheadersandsfvcrates. Node has jshttp'scontent-type,negotiator,range-parserandfresh.
Scope
In scope:
- The modules above, and switching Effect's own call sites over to them.
Out of scope:
- An HTTP cache.
- Cookies and trace context, which already have modules.
Forwarded(#9681) and Problem Details (#9686), which have their own issues.- Accept-based response selection in HttpApi.
Open questions
- Should conditional-request evaluation (
If-Match,If-None-Match,If-Modified-Since,If-Range) be a public helper that any handler can call? The static server would then use it too. - One issue with a checklist, or one PR per module?
- Lenguaje dominante
- TypeScript
- Estrellas
- 16.7k
- Forks
- 808
- Merge medio
- 11 h 24 min
- PR fusionados (30 d)
- 848
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Effect-TS/effect
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 35/100
Los mantenedores suelen responder en 1 día
-
AI providers: tool results cannot carry images because non-string results are JSON.stringify'dPosiblemente ocupada @nmnmcc la tomó hoy. Abierto
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
Effect-TS/effect#9857 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 1 día
-
`Schema.Literals`: add `omit`, the complement of `pick`Posiblemente ocupada @effect-bot la tomó hace 1 día. Abiertoenhancement Needs Evaluation
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
Los mantenedores suelen responder en 1 día
-
Support the `openapi-3.0` target in `Schema.toStandardJSONSchemaV1`Posiblemente ocupada @MichaelDeBoey la tomó hace 1 día. Abiertoenhancement Needs Evaluation
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
Effect-TS/effect#9764 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de Effect-TS/effect
Issues similares
-
[Feature]: 建议导入源后,自动切换到新导入的源Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
lyswhut/lx-music-desktop#3026 ·
-
area: ci type: test
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
schlessera/brain-kit#2769 ·
Los mantenedores suelen responder en 1 día
-
Read a vector index's quantization back on Neo4j 2026.10, which reports vector.quantization.typeAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
liberation-data/drivine#231 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
alveusgg/alveusgg#2502 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día