Skip to content

HttpApiBuilder does not expose payload parse options #8266

Description

@Chasewhip8

What version of Effect is running?

4.0.0-rc.115

What steps can reproduce the bug?

Run with Bun:

import { Console, Effect, Layer, Schema } from "effect"
import { HttpRouter, HttpServer } from "effect/unstable/http"
import {
  HttpApi,
  HttpApiBuilder,
  HttpApiEndpoint,
  HttpApiError,
  HttpApiGroup,
  HttpApiMiddleware,
} from "effect/unstable/httpapi"

const Payload = Schema.Struct({ firstName: Schema.String, lastName: Schema.String })

class Inspect extends HttpApiMiddleware.Service<Inspect>()("Inspect") {}

class Api extends HttpApi.make("api")
  .add(
    HttpApiGroup.make("users").add(
      HttpApiEndpoint.post("create", "/users", { payload: Payload }),
    ),
  )
  .middleware(Inspect) {}

const inspectLayer = Layer.succeed(
  Inspect,
  Inspect.of((effect) =>
    effect.pipe(
      Effect.tapError((error) =>
        HttpApiError.HttpApiSchemaError.is(error)
          ? Console.log(error.cause.message)
          : Effect.void,
      ),
    ),
  ),
)

const server = HttpRouter.toWebHandler(
  HttpApiBuilder.layer(Api).pipe(
    Layer.provide(
      HttpApiBuilder.group(Api, "users", (handlers) =>
        handlers.handle("create", () => Effect.void),
      ),
    ),
    Layer.provide(inspectLayer),
    Layer.provide(HttpServer.layerServices),
  ),
  { disableLogger: true },
)

try {
  await server.handler(
    new Request("http://localhost/users", {
      method: "POST",
      headers: { "content-type": "application/json" },
      body: "{}",
    }),
  )
} finally {
  await server.dispose()
}

What is the expected behavior?

A way to pass { errors: "all" } to automatic request payload decoding, so middleware can return errors for both missing fields in one response.

What do you see instead?

Only the first missing field is reported:

Missing key
  at ["firstName"]

There is no exposed parse-options setting on HttpApiBuilder for collecting the remaining errors.

Additional information

buildPayloadDecoders calls Schema.decodeUnknownEffect(Schema.Union(schemas)) without parse options, which defaults to errors: "first".

Calling Schema.decodeUnknownEffect(Payload, { errors: "all" })({}) directly reports both missing fields. The same limitation applies to PATCH payload decoding.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions