Responses
Set headers and status from a resolver, or return a response of your own.
On this page
response sets the call's headers and status; Effect code uses the Response service over the same handle:
import { const Response: ResponseServiceResponse } from '@trpc12/trpc/server';
import { import EffectEffect } from 'effect';
const const login: BuildProcedure<RootDef<Context, {}>, "mutation", {
output: void;
errors: never;
services: never;
unmapped: never;
}>
login = const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure.ProcedureBuilder<RootDef<Context, {}>>.mutation<void>(resolver: (opts: ResolverOpts<RootDef<Context, {}>>) => void): BuildProcedure<RootDef<Context, {}>, "mutation", {
output: void;
errors: never;
services: never;
unmapped: never;
}>
mutation((opts: ResolverOpts<RootDef<Context, {}>>opts) => {
opts: ResolverOpts<RootDef<Context, {}>>opts.ResolverOpts<RootDef<Context, {}>>.response: ResponseHandleresponse.ResponseHandle.headers: Headersheaders.Headers.append(name: string, value: string): voidappend('set-cookie', 'session=…; HttpOnly');
opts: ResolverOpts<RootDef<Context, {}>>opts.ResolverOpts<RootDef<Context, {}>>.response: ResponseHandleresponse.ResponseHandle.status: number | undefinedstatus = 201;
});
const const list: BuildProcedure<RootDef<Context, {}>, "query", {
output: Post[];
errors: never;
services: Response;
unmapped: never;
}>
list = const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure.ProcedureBuilder<RootDef<Context, {}>>.query<Effect.Effect<Post[], never, Response>>(resolver: (opts: ResolverOpts<RootDef<Context, {}>>) => Effect.Effect<Post[], never, Response>): BuildProcedure<RootDef<Context, {}>, "query", {
output: Post[];
errors: never;
services: Response;
unmapped: never;
}>
query(() =>
import EffectEffect.const gen: <Effect.Effect<void, never, Response>, Post[]>(f: () => Generator<Effect.Effect<void, never, Response>, Post[], never>) => Effect.Effect<Post[], never, Response> (+1 overload)gen(function* () {
yield* const Response: ResponseServiceResponse.ResponseService.setHeader(name: string, value: string): Effect.Effect<void, never, Response>setHeader('cache-control', 'max-age=60');
return const db: {
post: {
find: (id: string) => Post | undefined;
list: () => Post[];
create: (input: {
title: string;
author?: string | null;
}) => Post;
};
}
db.post: {
find: (id: string) => Post | undefined;
list: () => Post[];
create: (input: {
title: string;
author?: string | null;
}) => Post;
}
post.list: () => Post[]list();
}),
);In a batch, headers merge (set-cookie appends) and each call keeps its own status.
Returning a response
A procedure can also return its own response, an HttpServerResponse from effect/http or a web Response, for redirects, proxied upstreams or downloads. It's sent as is, with the handle's headers added, and the client's output is the web Response:
const const report: BuildProcedure<RootDef<Context, {}>, "query", {
output: HttpServerResponse.HttpServerResponse;
errors: never;
services: never;
unmapped: never;
}>
report = const t: TrpcRoot<Context, {}, RootDef<Context, {}>>t.TrpcRoot<Context, {}, RootDef<Context, {}>>.procedure: ProcedureBuilder<RootDef<Context, {}>>procedure.ProcedureBuilder<RootDef<Context, {}>>.query<HttpServerResponse.HttpServerResponse>(resolver: (opts: ResolverOpts<RootDef<Context, {}>>) => HttpServerResponse.HttpServerResponse): BuildProcedure<RootDef<Context, {}>, "query", {
output: HttpServerResponse.HttpServerResponse;
errors: never;
services: never;
unmapped: never;
}>
query(() =>
import HttpServerResponseHttpServerResponse.const text: (body: string, options?: HttpServerResponse.Options.WithContentType) => HttpServerResponse.HttpServerResponsetext(function toCsv(rows: string[][]): stringtoCsv(const rows: string[][]rows), { contentType?: string | undefinedcontentType: 'text/csv' }),
);
const const res: Responseres = await const client: TrpcClient<{
report: typeof report;
}, {}, undefined, LinksTypes<readonly [TrpcLink<{
form: JsonForm;
provides: "response";
}, any>]>>
client.report: {
query(input?: undefined, opts?: CallOptions<{}> | undefined): TrpcPromise<Response, UnexpectedError>;
}
report.function query(input?: undefined, opts?: CallOptions<{}> | undefined): TrpcPromise<Response, UnexpectedError>query(); // ResponseOnly an unbatched HTTP call can carry one: in a batch, over WebSockets or in-process, the call fails with BAD_REQUEST. With httpLink({ batch: true }), the client's types require { batch: false } on calls to procedures that may return a response, and the link sends them alone: client.report.query(undefined, { batch: false }).
Reading the response on the client
httpLink hands each call's response to an onResponse call option ({ status, headers }). A batched call gets its own line's status and the batch's headers (Custom links).