02-http-client
Effect-TS 4 HTTP client — HttpClient, request building, response decoding, and error handling via effect/unstable/http
- License 许可
- MIT
- 最近更新
- 2026-05-31
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- 02-http-client
- license
- MIT
- description
- Effect-TS 4 HTTP client — HttpClient, request building, response decoding, and error handling via effect/unstable/http
- compatibility
- opencode
03 SKILL.md 正文
HTTP Client
Import path: effect/unstable/http
Basic service wrapping HttpClient
import { Context, Effect, Layer, Schedule, Schema } from "effect";
import { FetchHttpClient, HttpClient, HttpClientRequest, HttpClientResponse } from "effect/unstable/http";
export class JsonApi extends Context.Service<
JsonApi,
{
getTodo(id: number): Effect.Effect<Todo, ApiError>;
}
>()("app/JsonApi") {
static readonly layer = Layer.effect(
JsonApi,
Effect.gen(function* () {
const client = (yield* HttpClient.HttpClient).pipe(
HttpClient.mapRequest(HttpClientRequest.prependUrl("https://api.example.com")),
HttpClient.filterStatusOk,
HttpClient.retryTransient({
schedule: Schedule.exponential("100 millis"),
times: 3,
}),
);
const getTodo = Effect.fn("JsonApi.getTodo")(function* (id: number) {
yield* Effect.annotateCurrentSpan({ id });
return yield* client.get(`/todos/${id}`).pipe(
Effect.flatMap(HttpClientResponse.schemaBodyJson(Todo)),
Effect.mapError((cause) => new ApiError({ cause })),
);
});
return JsonApi.of({ getTodo });
}),
).pipe(Layer.provide(FetchHttpClient.layer));
}
Making requests
// GET with query params
client.get("/path", { urlParams: { format: "json" } });
// POST JSON body
HttpClientRequest.post("/todos").pipe(HttpClientRequest.bodyJsonUnsafe(payload), client.execute);
// Set headers — note: Effect HTTP headers are lowercased
HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("authorization", `Bearer ${token}`));
Reading responses
// Typed body via Schema
HttpClientResponse.schemaBodyJson(MySchema);
// Raw JSON (untyped)
const body = yield * response.json;
// Raw text
const text = yield * response.text;
// Status code
response.status;
Headers — always lowercase
Effect normalises header names to lowercase:
// ✅ lowercase
request.headers["authorization"];
request.headers["content-type"];
// ❌ will not match
request.headers["Authorization"];
Middleware composition
const client = (yield * HttpClient.HttpClient).pipe(
HttpClient.mapRequest(flow(HttpClientRequest.prependUrl(baseUrl), HttpClientRequest.acceptJson)),
HttpClient.filterStatusOk,
HttpClient.retryTransient({
schedule: Schedule.exponential("100 millis"),
times: 3,
}),
HttpClient.transformResponse(Effect.mapError((cause) => new ApiError({ cause }))),
);
BunHttpClient vs FetchHttpClient
import { BunHttpClient } from "@effect/platform-bun";
import { FetchHttpClient } from "effect/unstable/http";
// Server (Bun runtime)
Layer.provide(BunHttpClient.layer);
// Browser / client atoms
Layer.provide(FetchHttpClient.layer);
In lambench-pro client atoms
export const benchmarkAtom = runtime.atom(
Effect.gen(function* () {
const client = yield* HttpClient.HttpClient;
const response = yield* client.get(`${import.meta.env.BASE_URL}data/results.json`);
const body = yield* response.json;
return yield* Schema.decode(BenchmarkDataSchema)(body);
}),
);
04 同仓库更多 Skills
tmux-workflow
Development workflow with tmux — run dev servers, Storybook, and background processes in persistent sessions with live logs, while keeping OpenCode free for chat
04-anti-patterns
React anti-patterns to avoid — manual JSX repetition, useEffect misuse, reference instability, prop drilling, conditional hooks, and common performance traps
03-state-management
React state management patterns — lifting state, colocation, URL state, server state with TanStack Query, local state with useState/useReducer
02-component-composition
React component composition patterns — render props, compound components, list rendering with map, slot patterns, and layout primitives
01-fp-style
React functional programming style — pure components, hooks conventions, Effect Atom integration, and Tailwind patterns
react-animation
React animation with react/motion (Framer Motion) — declarative animations, gestures, layout animations, and performance best practices