@effect/platform 0.57.8 → 0.58.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Cookies/package.json +6 -0
- package/Etag/package.json +6 -0
- package/Headers/package.json +6 -0
- package/HttpApp/package.json +6 -0
- package/HttpBody/package.json +6 -0
- package/HttpClientError/package.json +6 -0
- package/HttpClientRequest/package.json +6 -0
- package/HttpClientResponse/package.json +6 -0
- package/HttpIncomingMessage/package.json +6 -0
- package/HttpMethod/package.json +6 -0
- package/HttpMiddleware/package.json +6 -0
- package/HttpMultiplex/package.json +6 -0
- package/HttpPlatform/package.json +6 -0
- package/HttpRouter/package.json +6 -0
- package/HttpServerError/package.json +6 -0
- package/HttpServerRequest/package.json +6 -0
- package/HttpServerResponse/package.json +6 -0
- package/HttpTraceContext/package.json +6 -0
- package/Multipart/package.json +6 -0
- package/README.md +403 -330
- package/UrlParams/package.json +6 -0
- package/dist/cjs/{Http/Cookies.js → Cookies.js} +6 -6
- package/dist/cjs/Cookies.js.map +1 -0
- package/dist/cjs/{Http/Etag.js → Etag.js} +1 -1
- package/dist/cjs/Etag.js.map +1 -0
- package/dist/cjs/{Http/Headers.js → Headers.js} +2 -2
- package/dist/cjs/Headers.js.map +1 -0
- package/dist/cjs/{Http/App.js → HttpApp.js} +8 -8
- package/dist/cjs/HttpApp.js.map +1 -0
- package/dist/cjs/{Http/Body.js → HttpBody.js} +6 -6
- package/dist/cjs/HttpBody.js.map +1 -0
- package/dist/cjs/HttpClient.js +182 -17
- package/dist/cjs/HttpClient.js.map +1 -1
- package/dist/cjs/{Http/ClientError.js → HttpClientError.js} +2 -2
- package/dist/cjs/{Http/ClientError.js.map → HttpClientError.js.map} +1 -1
- package/dist/cjs/{Http/ClientRequest.js → HttpClientRequest.js} +3 -3
- package/dist/cjs/HttpClientRequest.js.map +1 -0
- package/dist/cjs/{Http/ClientResponse.js → HttpClientResponse.js} +9 -9
- package/dist/cjs/HttpClientResponse.js.map +1 -0
- package/dist/cjs/{Http/IncomingMessage.js → HttpIncomingMessage.js} +4 -4
- package/dist/cjs/{Http/IncomingMessage.js.map → HttpIncomingMessage.js.map} +1 -1
- package/dist/cjs/{Http/Method.js → HttpMethod.js} +1 -1
- package/dist/cjs/HttpMethod.js.map +1 -0
- package/dist/cjs/{Http/Middleware.js → HttpMiddleware.js} +2 -2
- package/dist/cjs/{Http/Middleware.js.map → HttpMiddleware.js.map} +1 -1
- package/dist/cjs/{Http/Multiplex.js → HttpMultiplex.js} +2 -2
- package/dist/cjs/{Http/Multiplex.js.map → HttpMultiplex.js.map} +1 -1
- package/dist/cjs/{Http/Platform.js → HttpPlatform.js} +4 -4
- package/dist/cjs/HttpPlatform.js.map +1 -0
- package/dist/cjs/{Http/Router.js → HttpRouter.js} +2 -2
- package/dist/cjs/HttpRouter.js.map +1 -0
- package/dist/cjs/HttpServer.js +52 -31
- package/dist/cjs/HttpServer.js.map +1 -1
- package/dist/cjs/{Http/ServerError.js → HttpServerError.js} +3 -3
- package/dist/cjs/{Http/ServerError.js.map → HttpServerError.js.map} +1 -1
- package/dist/cjs/{Http/ServerRequest.js → HttpServerRequest.js} +6 -6
- package/dist/cjs/HttpServerRequest.js.map +1 -0
- package/dist/cjs/{Http/ServerResponse.js → HttpServerResponse.js} +3 -3
- package/dist/cjs/HttpServerResponse.js.map +1 -0
- package/dist/cjs/{Http/TraceContext.js → HttpTraceContext.js} +1 -1
- package/dist/cjs/{Http/TraceContext.js.map → HttpTraceContext.js.map} +1 -1
- package/dist/cjs/{Http/Multipart.js → Multipart.js} +1 -1
- package/dist/cjs/Multipart.js.map +1 -0
- package/dist/cjs/Socket.js +83 -1
- package/dist/cjs/Socket.js.map +1 -1
- package/dist/cjs/UrlParams.js.map +1 -0
- package/dist/cjs/index.js +41 -1
- package/dist/cjs/internal/{http/etag.js → etag.js} +2 -2
- package/dist/cjs/internal/etag.js.map +1 -0
- package/dist/cjs/internal/{http/body.js → httpBody.js} +16 -16
- package/dist/cjs/internal/httpBody.js.map +1 -0
- package/dist/cjs/internal/{http/client.js → httpClient.js} +16 -16
- package/dist/cjs/internal/{http/client.js.map → httpClient.js.map} +1 -1
- package/dist/cjs/internal/{http/clientError.js → httpClientError.js} +2 -2
- package/dist/cjs/internal/httpClientError.js.map +1 -0
- package/dist/cjs/internal/{http/clientRequest.js → httpClientRequest.js} +7 -7
- package/dist/cjs/internal/httpClientRequest.js.map +1 -0
- package/dist/cjs/internal/{http/clientResponse.js → httpClientResponse.js} +8 -8
- package/dist/cjs/internal/{http/clientResponse.js.map → httpClientResponse.js.map} +1 -1
- package/dist/cjs/internal/{http/middleware.js → httpMiddleware.js} +11 -11
- package/dist/cjs/internal/httpMiddleware.js.map +1 -0
- package/dist/cjs/internal/{http/multiplex.js → httpMultiplex.js} +6 -6
- package/dist/cjs/internal/httpMultiplex.js.map +1 -0
- package/dist/cjs/internal/{http/platform.js → httpPlatform.js} +6 -6
- package/dist/cjs/internal/{http/platform.js.map → httpPlatform.js.map} +1 -1
- package/dist/cjs/internal/{http/router.js → httpRouter.js} +13 -13
- package/dist/cjs/internal/httpRouter.js.map +1 -0
- package/dist/cjs/internal/{http/server.js → httpServer.js} +3 -3
- package/dist/cjs/internal/{http/server.js.map → httpServer.js.map} +1 -1
- package/dist/cjs/internal/{http/serverError.js → httpServerError.js} +3 -3
- package/dist/cjs/internal/httpServerError.js.map +1 -0
- package/dist/cjs/internal/{http/serverRequest.js → httpServerRequest.js} +12 -12
- package/dist/cjs/internal/httpServerRequest.js.map +1 -0
- package/dist/cjs/internal/{http/serverResponse.js → httpServerResponse.js} +11 -11
- package/dist/cjs/internal/httpServerResponse.js.map +1 -0
- package/dist/cjs/internal/{http/multipart.js → multipart.js} +13 -13
- package/dist/cjs/internal/multipart.js.map +1 -0
- package/dist/dts/Cookies.d.ts.map +1 -0
- package/dist/dts/{Http/Etag.d.ts → Etag.d.ts} +3 -3
- package/dist/dts/Etag.d.ts.map +1 -0
- package/dist/dts/Headers.d.ts.map +1 -0
- package/dist/dts/{Http/App.d.ts → HttpApp.d.ts} +9 -9
- package/dist/dts/HttpApp.d.ts.map +1 -0
- package/dist/dts/{Http/Body.d.ts → HttpBody.d.ts} +20 -20
- package/dist/dts/HttpBody.d.ts.map +1 -0
- package/dist/dts/HttpClient.d.ts +330 -41
- package/dist/dts/HttpClient.d.ts.map +1 -1
- package/dist/dts/{Http/ClientError.d.ts → HttpClientError.d.ts} +6 -6
- package/dist/dts/HttpClientError.d.ts.map +1 -0
- package/dist/dts/HttpClientRequest.d.ts +350 -0
- package/dist/dts/HttpClientRequest.d.ts.map +1 -0
- package/dist/dts/{Http/ClientResponse.d.ts → HttpClientResponse.d.ts} +18 -18
- package/dist/dts/HttpClientResponse.d.ts.map +1 -0
- package/dist/dts/{Http/IncomingMessage.d.ts → HttpIncomingMessage.d.ts} +10 -10
- package/dist/dts/HttpIncomingMessage.d.ts.map +1 -0
- package/dist/dts/HttpMethod.d.ts +10 -0
- package/dist/dts/HttpMethod.d.ts.map +1 -0
- package/dist/dts/{Http/Middleware.d.ts → HttpMiddleware.d.ts} +11 -11
- package/dist/dts/HttpMiddleware.d.ts.map +1 -0
- package/dist/dts/HttpMultiplex.d.ts +115 -0
- package/dist/dts/HttpMultiplex.d.ts.map +1 -0
- package/dist/dts/HttpPlatform.d.ts +44 -0
- package/dist/dts/HttpPlatform.d.ts.map +1 -0
- package/dist/dts/{Http/Router.d.ts → HttpRouter.d.ts} +72 -72
- package/dist/dts/HttpRouter.d.ts.map +1 -0
- package/dist/dts/HttpServer.d.ts +71 -76
- package/dist/dts/HttpServer.d.ts.map +1 -1
- package/dist/dts/{Http/ServerError.d.ts → HttpServerError.d.ts} +7 -7
- package/dist/dts/HttpServerError.d.ts.map +1 -0
- package/dist/dts/{Http/ServerRequest.d.ts → HttpServerRequest.d.ts} +23 -23
- package/dist/dts/HttpServerRequest.d.ts.map +1 -0
- package/dist/dts/{Http/ServerResponse.d.ts → HttpServerResponse.d.ts} +49 -49
- package/dist/dts/HttpServerResponse.d.ts.map +1 -0
- package/dist/dts/{Http/TraceContext.d.ts → HttpTraceContext.d.ts} +1 -1
- package/dist/dts/{Http/TraceContext.d.ts.map → HttpTraceContext.d.ts.map} +1 -1
- package/dist/dts/{Http/Multipart.d.ts → Multipart.d.ts} +2 -2
- package/dist/dts/Multipart.d.ts.map +1 -0
- package/dist/dts/Socket.d.ts +20 -0
- package/dist/dts/Socket.d.ts.map +1 -1
- package/dist/dts/UrlParams.d.ts.map +1 -0
- package/dist/dts/index.d.ts +81 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/{http/etag.d.ts.map → etag.d.ts.map} +1 -1
- package/dist/dts/internal/httpBody.d.ts +2 -0
- package/dist/dts/internal/httpBody.d.ts.map +1 -0
- package/dist/dts/internal/httpClient.d.ts +2 -0
- package/dist/dts/internal/httpClient.d.ts.map +1 -0
- package/dist/dts/internal/httpClientError.d.ts +2 -0
- package/dist/dts/internal/httpClientError.d.ts.map +1 -0
- package/dist/dts/internal/httpClientRequest.d.ts +2 -0
- package/dist/dts/internal/httpClientRequest.d.ts.map +1 -0
- package/dist/dts/internal/httpClientResponse.d.ts +2 -0
- package/dist/dts/internal/httpClientResponse.d.ts.map +1 -0
- package/dist/dts/internal/httpMiddleware.d.ts +2 -0
- package/dist/dts/internal/httpMiddleware.d.ts.map +1 -0
- package/dist/dts/internal/httpMultiplex.d.ts +2 -0
- package/dist/dts/internal/httpMultiplex.d.ts.map +1 -0
- package/dist/dts/internal/httpPlatform.d.ts +2 -0
- package/dist/dts/internal/httpPlatform.d.ts.map +1 -0
- package/dist/dts/internal/httpRouter.d.ts +4 -0
- package/dist/dts/internal/httpRouter.d.ts.map +1 -0
- package/dist/dts/internal/httpServer.d.ts +2 -0
- package/dist/dts/internal/httpServer.d.ts.map +1 -0
- package/dist/dts/internal/httpServerError.d.ts +2 -0
- package/dist/dts/internal/httpServerError.d.ts.map +1 -0
- package/dist/dts/internal/httpServerRequest.d.ts +2 -0
- package/dist/dts/internal/httpServerRequest.d.ts.map +1 -0
- package/dist/dts/internal/httpServerResponse.d.ts +2 -0
- package/dist/dts/internal/httpServerResponse.d.ts.map +1 -0
- package/dist/dts/internal/multipart.d.ts.map +1 -0
- package/dist/esm/{Http/Cookies.js → Cookies.js} +6 -6
- package/dist/esm/Cookies.js.map +1 -0
- package/dist/esm/{Http/Etag.js → Etag.js} +1 -1
- package/dist/esm/Etag.js.map +1 -0
- package/dist/esm/{Http/Headers.js → Headers.js} +2 -2
- package/dist/esm/Headers.js.map +1 -0
- package/dist/esm/{Http/App.js → HttpApp.js} +8 -8
- package/dist/esm/HttpApp.js.map +1 -0
- package/dist/esm/{Http/Body.js → HttpBody.js} +4 -4
- package/dist/esm/HttpBody.js.map +1 -0
- package/dist/esm/HttpClient.js +154 -41
- package/dist/esm/HttpClient.js.map +1 -1
- package/dist/esm/{Http/ClientError.js → HttpClientError.js} +2 -2
- package/dist/esm/{Http/ClientError.js.map → HttpClientError.js.map} +1 -1
- package/dist/esm/{Http/ClientRequest.js → HttpClientRequest.js} +3 -3
- package/dist/esm/HttpClientRequest.js.map +1 -0
- package/dist/esm/{Http/ClientResponse.js → HttpClientResponse.js} +3 -3
- package/dist/esm/HttpClientResponse.js.map +1 -0
- package/dist/esm/{Http/IncomingMessage.js → HttpIncomingMessage.js} +4 -4
- package/dist/esm/{Http/IncomingMessage.js.map → HttpIncomingMessage.js.map} +1 -1
- package/dist/esm/{Http/Method.js → HttpMethod.js} +1 -1
- package/dist/esm/HttpMethod.js.map +1 -0
- package/dist/esm/{Http/Middleware.js → HttpMiddleware.js} +2 -2
- package/dist/esm/HttpMiddleware.js.map +1 -0
- package/dist/esm/{Http/Multiplex.js → HttpMultiplex.js} +2 -2
- package/dist/esm/HttpMultiplex.js.map +1 -0
- package/dist/esm/{Http/Platform.js → HttpPlatform.js} +3 -3
- package/dist/esm/HttpPlatform.js.map +1 -0
- package/dist/esm/{Http/Router.js → HttpRouter.js} +2 -2
- package/dist/esm/HttpRouter.js.map +1 -0
- package/dist/esm/HttpServer.js +21 -94
- package/dist/esm/HttpServer.js.map +1 -1
- package/dist/esm/{Http/ServerError.js → HttpServerError.js} +3 -3
- package/dist/esm/{Http/ServerError.js.map → HttpServerError.js.map} +1 -1
- package/dist/esm/{Http/ServerRequest.js → HttpServerRequest.js} +4 -4
- package/dist/esm/HttpServerRequest.js.map +1 -0
- package/dist/esm/{Http/ServerResponse.js → HttpServerResponse.js} +3 -3
- package/dist/esm/HttpServerResponse.js.map +1 -0
- package/dist/esm/{Http/TraceContext.js → HttpTraceContext.js} +1 -1
- package/dist/esm/{Http/TraceContext.js.map → HttpTraceContext.js.map} +1 -1
- package/dist/esm/{Http/Multipart.js → Multipart.js} +1 -1
- package/dist/esm/Multipart.js.map +1 -0
- package/dist/esm/Socket.js +81 -0
- package/dist/esm/Socket.js.map +1 -1
- package/dist/esm/UrlParams.js.map +1 -0
- package/dist/esm/index.js +81 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/{http/etag.js → etag.js} +2 -2
- package/dist/esm/internal/etag.js.map +1 -0
- package/dist/esm/internal/{http/body.js → httpBody.js} +14 -14
- package/dist/esm/internal/httpBody.js.map +1 -0
- package/dist/esm/internal/{http/client.js → httpClient.js} +16 -16
- package/dist/esm/internal/httpClient.js.map +1 -0
- package/dist/esm/internal/{http/clientError.js → httpClientError.js} +2 -2
- package/dist/esm/internal/httpClientError.js.map +1 -0
- package/dist/esm/internal/{http/clientRequest.js → httpClientRequest.js} +7 -7
- package/dist/esm/internal/httpClientRequest.js.map +1 -0
- package/dist/esm/internal/{http/clientResponse.js → httpClientResponse.js} +8 -8
- package/dist/esm/internal/httpClientResponse.js.map +1 -0
- package/dist/esm/internal/{http/middleware.js → httpMiddleware.js} +11 -11
- package/dist/esm/internal/httpMiddleware.js.map +1 -0
- package/dist/esm/internal/{http/multiplex.js → httpMultiplex.js} +6 -6
- package/dist/esm/internal/httpMultiplex.js.map +1 -0
- package/dist/esm/internal/{http/platform.js → httpPlatform.js} +6 -6
- package/dist/esm/internal/httpPlatform.js.map +1 -0
- package/dist/esm/internal/{http/router.js → httpRouter.js} +13 -13
- package/dist/esm/internal/httpRouter.js.map +1 -0
- package/dist/esm/internal/{http/server.js → httpServer.js} +3 -3
- package/dist/esm/internal/httpServer.js.map +1 -0
- package/dist/esm/internal/{http/serverError.js → httpServerError.js} +3 -3
- package/dist/esm/internal/httpServerError.js.map +1 -0
- package/dist/esm/internal/{http/serverRequest.js → httpServerRequest.js} +12 -12
- package/dist/esm/internal/httpServerRequest.js.map +1 -0
- package/dist/esm/internal/{http/serverResponse.js → httpServerResponse.js} +12 -12
- package/dist/esm/internal/httpServerResponse.js.map +1 -0
- package/dist/esm/internal/{http/multipart.js → multipart.js} +13 -13
- package/dist/esm/internal/multipart.js.map +1 -0
- package/package.json +150 -166
- package/src/{Http/Cookies.ts → Cookies.ts} +6 -6
- package/src/{Http/Etag.ts → Etag.ts} +4 -4
- package/src/{Http/Headers.ts → Headers.ts} +2 -2
- package/src/{Http/App.ts → HttpApp.ts} +19 -19
- package/src/{Http/Body.ts → HttpBody.ts} +20 -20
- package/src/HttpClient.ts +501 -54
- package/src/{Http/ClientError.ts → HttpClientError.ts} +6 -6
- package/src/{Http/ClientRequest.ts → HttpClientRequest.ts} +82 -82
- package/src/{Http/ClientResponse.ts → HttpClientResponse.ts} +22 -19
- package/src/{Http/IncomingMessage.ts → HttpIncomingMessage.ts} +11 -11
- package/src/{Http/Method.ts → HttpMethod.ts} +2 -2
- package/src/{Http/Middleware.ts → HttpMiddleware.ts} +11 -11
- package/src/{Http/Multiplex.ts → HttpMultiplex.ts} +37 -34
- package/src/{Http/Platform.ts → HttpPlatform.ts} +14 -14
- package/src/{Http/Router.ts → HttpRouter.ts} +100 -100
- package/src/HttpServer.ts +191 -122
- package/src/{Http/ServerError.ts → HttpServerError.ts} +8 -8
- package/src/{Http/ServerRequest.ts → HttpServerRequest.ts} +23 -23
- package/src/{Http/ServerResponse.ts → HttpServerResponse.ts} +58 -55
- package/src/{Http/Multipart.ts → Multipart.ts} +3 -3
- package/src/Socket.ts +140 -0
- package/src/index.ts +101 -0
- package/src/internal/{http/etag.ts → etag.ts} +3 -3
- package/src/internal/{http/body.ts → httpBody.ts} +19 -19
- package/src/internal/{http/client.ts → httpClient.ts} +132 -132
- package/src/internal/httpClientError.ts +6 -0
- package/src/internal/{http/clientRequest.ts → httpClientRequest.ts} +94 -81
- package/src/internal/{http/clientResponse.ts → httpClientResponse.ts} +24 -24
- package/src/internal/{http/middleware.ts → httpMiddleware.ts} +21 -21
- package/src/internal/{http/multiplex.ts → httpMultiplex.ts} +50 -46
- package/src/internal/{http/platform.ts → httpPlatform.ts} +12 -12
- package/src/internal/{http/router.ts → httpRouter.ts} +95 -93
- package/src/internal/{http/server.ts → httpServer.ts} +29 -29
- package/src/internal/{http/serverError.ts → httpServerError.ts} +3 -3
- package/src/internal/{http/serverRequest.ts → httpServerRequest.ts} +24 -22
- package/src/internal/{http/serverResponse.ts → httpServerResponse.ts} +74 -64
- package/src/internal/{http/multipart.ts → multipart.ts} +14 -14
- package/Http/App/package.json +0 -6
- package/Http/Body/package.json +0 -6
- package/Http/Client/package.json +0 -6
- package/Http/ClientError/package.json +0 -6
- package/Http/ClientRequest/package.json +0 -6
- package/Http/ClientResponse/package.json +0 -6
- package/Http/Cookies/package.json +0 -6
- package/Http/Etag/package.json +0 -6
- package/Http/Headers/package.json +0 -6
- package/Http/IncomingMessage/package.json +0 -6
- package/Http/Method/package.json +0 -6
- package/Http/Middleware/package.json +0 -6
- package/Http/Multipart/package.json +0 -6
- package/Http/Multiplex/package.json +0 -6
- package/Http/Platform/package.json +0 -6
- package/Http/Router/package.json +0 -6
- package/Http/Server/package.json +0 -6
- package/Http/ServerError/package.json +0 -6
- package/Http/ServerRequest/package.json +0 -6
- package/Http/ServerResponse/package.json +0 -6
- package/Http/TraceContext/package.json +0 -6
- package/Http/UrlParams/package.json +0 -6
- package/dist/cjs/Http/App.js.map +0 -1
- package/dist/cjs/Http/Body.js.map +0 -1
- package/dist/cjs/Http/Client.js +0 -213
- package/dist/cjs/Http/Client.js.map +0 -1
- package/dist/cjs/Http/ClientRequest.js.map +0 -1
- package/dist/cjs/Http/ClientResponse.js.map +0 -1
- package/dist/cjs/Http/Cookies.js.map +0 -1
- package/dist/cjs/Http/Etag.js.map +0 -1
- package/dist/cjs/Http/Headers.js.map +0 -1
- package/dist/cjs/Http/Method.js.map +0 -1
- package/dist/cjs/Http/Multipart.js.map +0 -1
- package/dist/cjs/Http/Platform.js.map +0 -1
- package/dist/cjs/Http/Router.js.map +0 -1
- package/dist/cjs/Http/Server.js +0 -83
- package/dist/cjs/Http/Server.js.map +0 -1
- package/dist/cjs/Http/ServerRequest.js.map +0 -1
- package/dist/cjs/Http/ServerResponse.js.map +0 -1
- package/dist/cjs/Http/UrlParams.js.map +0 -1
- package/dist/cjs/internal/http/body.js.map +0 -1
- package/dist/cjs/internal/http/clientError.js.map +0 -1
- package/dist/cjs/internal/http/clientRequest.js.map +0 -1
- package/dist/cjs/internal/http/etag.js.map +0 -1
- package/dist/cjs/internal/http/middleware.js.map +0 -1
- package/dist/cjs/internal/http/multipart.js.map +0 -1
- package/dist/cjs/internal/http/multiplex.js.map +0 -1
- package/dist/cjs/internal/http/router.js.map +0 -1
- package/dist/cjs/internal/http/serverError.js.map +0 -1
- package/dist/cjs/internal/http/serverRequest.js.map +0 -1
- package/dist/cjs/internal/http/serverResponse.js.map +0 -1
- package/dist/dts/Http/App.d.ts.map +0 -1
- package/dist/dts/Http/Body.d.ts.map +0 -1
- package/dist/dts/Http/Client.d.ts +0 -358
- package/dist/dts/Http/Client.d.ts.map +0 -1
- package/dist/dts/Http/ClientError.d.ts.map +0 -1
- package/dist/dts/Http/ClientRequest.d.ts +0 -350
- package/dist/dts/Http/ClientRequest.d.ts.map +0 -1
- package/dist/dts/Http/ClientResponse.d.ts.map +0 -1
- package/dist/dts/Http/Cookies.d.ts.map +0 -1
- package/dist/dts/Http/Etag.d.ts.map +0 -1
- package/dist/dts/Http/Headers.d.ts.map +0 -1
- package/dist/dts/Http/IncomingMessage.d.ts.map +0 -1
- package/dist/dts/Http/Method.d.ts +0 -10
- package/dist/dts/Http/Method.d.ts.map +0 -1
- package/dist/dts/Http/Middleware.d.ts.map +0 -1
- package/dist/dts/Http/Multipart.d.ts.map +0 -1
- package/dist/dts/Http/Multiplex.d.ts +0 -112
- package/dist/dts/Http/Multiplex.d.ts.map +0 -1
- package/dist/dts/Http/Platform.d.ts +0 -44
- package/dist/dts/Http/Platform.d.ts.map +0 -1
- package/dist/dts/Http/Router.d.ts.map +0 -1
- package/dist/dts/Http/Server.d.ts +0 -120
- package/dist/dts/Http/Server.d.ts.map +0 -1
- package/dist/dts/Http/ServerError.d.ts.map +0 -1
- package/dist/dts/Http/ServerRequest.d.ts.map +0 -1
- package/dist/dts/Http/ServerResponse.d.ts.map +0 -1
- package/dist/dts/Http/UrlParams.d.ts.map +0 -1
- package/dist/dts/internal/http/body.d.ts +0 -2
- package/dist/dts/internal/http/body.d.ts.map +0 -1
- package/dist/dts/internal/http/client.d.ts +0 -2
- package/dist/dts/internal/http/client.d.ts.map +0 -1
- package/dist/dts/internal/http/clientError.d.ts +0 -2
- package/dist/dts/internal/http/clientError.d.ts.map +0 -1
- package/dist/dts/internal/http/clientRequest.d.ts +0 -2
- package/dist/dts/internal/http/clientRequest.d.ts.map +0 -1
- package/dist/dts/internal/http/clientResponse.d.ts +0 -2
- package/dist/dts/internal/http/clientResponse.d.ts.map +0 -1
- package/dist/dts/internal/http/middleware.d.ts +0 -2
- package/dist/dts/internal/http/middleware.d.ts.map +0 -1
- package/dist/dts/internal/http/multipart.d.ts.map +0 -1
- package/dist/dts/internal/http/multiplex.d.ts +0 -2
- package/dist/dts/internal/http/multiplex.d.ts.map +0 -1
- package/dist/dts/internal/http/platform.d.ts +0 -2
- package/dist/dts/internal/http/platform.d.ts.map +0 -1
- package/dist/dts/internal/http/router.d.ts +0 -4
- package/dist/dts/internal/http/router.d.ts.map +0 -1
- package/dist/dts/internal/http/server.d.ts +0 -2
- package/dist/dts/internal/http/server.d.ts.map +0 -1
- package/dist/dts/internal/http/serverError.d.ts +0 -2
- package/dist/dts/internal/http/serverError.d.ts.map +0 -1
- package/dist/dts/internal/http/serverRequest.d.ts +0 -2
- package/dist/dts/internal/http/serverRequest.d.ts.map +0 -1
- package/dist/dts/internal/http/serverResponse.d.ts +0 -2
- package/dist/dts/internal/http/serverResponse.d.ts.map +0 -1
- package/dist/esm/Http/App.js.map +0 -1
- package/dist/esm/Http/Body.js.map +0 -1
- package/dist/esm/Http/Client.js +0 -182
- package/dist/esm/Http/Client.js.map +0 -1
- package/dist/esm/Http/ClientRequest.js.map +0 -1
- package/dist/esm/Http/ClientResponse.js.map +0 -1
- package/dist/esm/Http/Cookies.js.map +0 -1
- package/dist/esm/Http/Etag.js.map +0 -1
- package/dist/esm/Http/Headers.js.map +0 -1
- package/dist/esm/Http/Method.js.map +0 -1
- package/dist/esm/Http/Middleware.js.map +0 -1
- package/dist/esm/Http/Multipart.js.map +0 -1
- package/dist/esm/Http/Multiplex.js.map +0 -1
- package/dist/esm/Http/Platform.js.map +0 -1
- package/dist/esm/Http/Router.js.map +0 -1
- package/dist/esm/Http/Server.js +0 -52
- package/dist/esm/Http/Server.js.map +0 -1
- package/dist/esm/Http/ServerRequest.js.map +0 -1
- package/dist/esm/Http/ServerResponse.js.map +0 -1
- package/dist/esm/Http/UrlParams.js.map +0 -1
- package/dist/esm/internal/http/body.js.map +0 -1
- package/dist/esm/internal/http/client.js.map +0 -1
- package/dist/esm/internal/http/clientError.js.map +0 -1
- package/dist/esm/internal/http/clientRequest.js.map +0 -1
- package/dist/esm/internal/http/clientResponse.js.map +0 -1
- package/dist/esm/internal/http/etag.js.map +0 -1
- package/dist/esm/internal/http/middleware.js.map +0 -1
- package/dist/esm/internal/http/multipart.js.map +0 -1
- package/dist/esm/internal/http/multiplex.js.map +0 -1
- package/dist/esm/internal/http/platform.js.map +0 -1
- package/dist/esm/internal/http/router.js.map +0 -1
- package/dist/esm/internal/http/server.js.map +0 -1
- package/dist/esm/internal/http/serverError.js.map +0 -1
- package/dist/esm/internal/http/serverRequest.js.map +0 -1
- package/dist/esm/internal/http/serverResponse.js.map +0 -1
- package/src/Http/Client.ts +0 -490
- package/src/Http/Server.ts +0 -187
- package/src/internal/http/clientError.ts +0 -6
- /package/dist/cjs/{Http/UrlParams.js → UrlParams.js} +0 -0
- /package/dist/dts/{Http/Cookies.d.ts → Cookies.d.ts} +0 -0
- /package/dist/dts/{Http/Headers.d.ts → Headers.d.ts} +0 -0
- /package/dist/dts/{Http/UrlParams.d.ts → UrlParams.d.ts} +0 -0
- /package/dist/dts/internal/{http/etag.d.ts → etag.d.ts} +0 -0
- /package/dist/dts/internal/{http/multipart.d.ts → multipart.d.ts} +0 -0
- /package/dist/esm/{Http/UrlParams.js → UrlParams.js} +0 -0
- /package/src/{Http/TraceContext.ts → HttpTraceContext.ts} +0 -0
- /package/src/{Http/UrlParams.ts → UrlParams.ts} +0 -0
package/README.md
CHANGED
|
@@ -426,12 +426,16 @@ In this section, we'll explore how to retrieve data using the `HttpClient` modul
|
|
|
426
426
|
|
|
427
427
|
```ts
|
|
428
428
|
import { NodeRuntime } from "@effect/platform-node"
|
|
429
|
-
import
|
|
429
|
+
import {
|
|
430
|
+
HttpClient,
|
|
431
|
+
HttpClientRequest,
|
|
432
|
+
HttpClientResponse
|
|
433
|
+
} from "@effect/platform"
|
|
430
434
|
import { Console, Effect } from "effect"
|
|
431
435
|
|
|
432
|
-
const getPostAsJson =
|
|
433
|
-
|
|
434
|
-
|
|
436
|
+
const getPostAsJson = HttpClientRequest.get(
|
|
437
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
438
|
+
).pipe(HttpClient.fetch, HttpClientResponse.json)
|
|
435
439
|
|
|
436
440
|
NodeRuntime.runMain(
|
|
437
441
|
getPostAsJson.pipe(Effect.andThen((post) => Console.log(typeof post, post)))
|
|
@@ -450,18 +454,22 @@ object {
|
|
|
450
454
|
*/
|
|
451
455
|
```
|
|
452
456
|
|
|
453
|
-
If you want a response in a different format other than JSON, you can utilize other APIs provided by `
|
|
457
|
+
If you want a response in a different format other than JSON, you can utilize other APIs provided by `HttpClientResponse`.
|
|
454
458
|
|
|
455
459
|
In the following example, we fetch the post as text:
|
|
456
460
|
|
|
457
461
|
```ts
|
|
458
462
|
import { NodeRuntime } from "@effect/platform-node"
|
|
459
|
-
import
|
|
463
|
+
import {
|
|
464
|
+
HttpClient,
|
|
465
|
+
HttpClientRequest,
|
|
466
|
+
HttpClientResponse
|
|
467
|
+
} from "@effect/platform"
|
|
460
468
|
import { Console, Effect } from "effect"
|
|
461
469
|
|
|
462
|
-
const getPostAsText =
|
|
463
|
-
|
|
464
|
-
|
|
470
|
+
const getPostAsText = HttpClientRequest.get(
|
|
471
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
472
|
+
).pipe(HttpClient.fetch, HttpClientResponse.text)
|
|
465
473
|
|
|
466
474
|
NodeRuntime.runMain(
|
|
467
475
|
getPostAsText.pipe(Effect.andThen((post) => Console.log(typeof post, post)))
|
|
@@ -482,34 +490,37 @@ string {
|
|
|
482
490
|
|
|
483
491
|
Here are some APIs you can use to convert the response:
|
|
484
492
|
|
|
485
|
-
| **API**
|
|
486
|
-
|
|
|
487
|
-
| `
|
|
488
|
-
| `
|
|
489
|
-
| `
|
|
490
|
-
| `
|
|
491
|
-
| `
|
|
492
|
-
| `
|
|
493
|
+
| **API** | **Description** |
|
|
494
|
+
| ---------------------------------- | ------------------------------------- |
|
|
495
|
+
| `HttpClientResponse.arrayBuffer` | Convert to `ArrayBuffer` |
|
|
496
|
+
| `HttpClientResponse.formData` | Convert to `FormData` |
|
|
497
|
+
| `HttpClientResponse.json` | Convert to JSON |
|
|
498
|
+
| `HttpClientResponse.stream` | Convert to a `Stream` of `Uint8Array` |
|
|
499
|
+
| `HttpClientResponse.text` | Convert to text |
|
|
500
|
+
| `HttpClientResponse.urlParamsBody` | Convert to `Http.urlParams.UrlParams` |
|
|
493
501
|
|
|
494
502
|
### Setting Headers
|
|
495
503
|
|
|
496
504
|
When making HTTP requests, sometimes you need to include additional information in the request headers. You can set headers using the `setHeader` function for a single header or `setHeaders` for multiple headers simultaneously.
|
|
497
505
|
|
|
498
506
|
```ts
|
|
499
|
-
import
|
|
500
|
-
|
|
501
|
-
const getPost =
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
507
|
+
import { HttpClient, HttpClientRequest } from "@effect/platform"
|
|
508
|
+
|
|
509
|
+
const getPost = HttpClientRequest.get(
|
|
510
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
511
|
+
).pipe(
|
|
512
|
+
// Setting a single header
|
|
513
|
+
HttpClientRequest.setHeader(
|
|
514
|
+
"Content-type",
|
|
515
|
+
"application/json; charset=UTF-8"
|
|
516
|
+
),
|
|
517
|
+
// Setting multiple headers
|
|
518
|
+
HttpClientRequest.setHeaders({
|
|
519
|
+
"Content-type": "application/json; charset=UTF-8",
|
|
520
|
+
Foo: "Bar"
|
|
521
|
+
}),
|
|
522
|
+
HttpClient.fetch
|
|
523
|
+
)
|
|
513
524
|
```
|
|
514
525
|
|
|
515
526
|
### Decoding Data with Schemas
|
|
@@ -518,7 +529,11 @@ A common use case when fetching data is to validate the received format. For thi
|
|
|
518
529
|
|
|
519
530
|
```ts
|
|
520
531
|
import { NodeRuntime } from "@effect/platform-node"
|
|
521
|
-
import
|
|
532
|
+
import {
|
|
533
|
+
HttpClient,
|
|
534
|
+
HttpClientRequest,
|
|
535
|
+
HttpClientResponse
|
|
536
|
+
} from "@effect/platform"
|
|
522
537
|
import { Schema } from "@effect/schema"
|
|
523
538
|
import { Console, Effect } from "effect"
|
|
524
539
|
|
|
@@ -533,13 +548,13 @@ const getPostAndValidate: Effect.Effect<{
|
|
|
533
548
|
readonly title: string;
|
|
534
549
|
}, Http.error.HttpClientError | ParseError, never>
|
|
535
550
|
*/
|
|
536
|
-
const getPostAndValidate =
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
551
|
+
const getPostAndValidate = HttpClientRequest.get(
|
|
552
|
+
"https://jsonplaceholder.typicode.com/posts/1"
|
|
553
|
+
).pipe(
|
|
554
|
+
HttpClient.fetch,
|
|
555
|
+
Effect.andThen(HttpClientResponse.schemaBodyJson(Post)),
|
|
556
|
+
Effect.scoped
|
|
557
|
+
)
|
|
543
558
|
|
|
544
559
|
NodeRuntime.runMain(getPostAndValidate.pipe(Effect.andThen(Console.log)))
|
|
545
560
|
/*
|
|
@@ -551,26 +566,30 @@ Output:
|
|
|
551
566
|
*/
|
|
552
567
|
```
|
|
553
568
|
|
|
554
|
-
In this example, we define a schema for a post object with properties `id` and `title`. Then, we fetch the data and validate it against this schema using `
|
|
569
|
+
In this example, we define a schema for a post object with properties `id` and `title`. Then, we fetch the data and validate it against this schema using `HttpClientResponse.schemaBodyJson`. Finally, we log the validated post object.
|
|
555
570
|
|
|
556
571
|
Note that we use `Effect.scoped` after consuming the response. This ensures that any resources associated with the HTTP request are properly cleaned up once we're done processing the response.
|
|
557
572
|
|
|
558
573
|
### Filtering And Error Handling
|
|
559
574
|
|
|
560
|
-
It's important to note that `
|
|
575
|
+
It's important to note that `HttpClient.fetch` doesn't consider non-`200` status codes as errors by default. This design choice allows for flexibility in handling different response scenarios. For instance, you might have a schema union where the status code serves as the discriminator, enabling you to define a schema that encompasses all possible response cases.
|
|
561
576
|
|
|
562
|
-
You can use `
|
|
577
|
+
You can use `HttpClient.filterStatusOk`, or `HttpClient.fetchOk` to ensure only `2xx` responses are treated as successes.
|
|
563
578
|
|
|
564
579
|
In this example, we attempt to fetch a non-existent page and don't receive any error:
|
|
565
580
|
|
|
566
581
|
```ts
|
|
567
582
|
import { NodeRuntime } from "@effect/platform-node"
|
|
568
|
-
import
|
|
583
|
+
import {
|
|
584
|
+
HttpClient,
|
|
585
|
+
HttpClientRequest,
|
|
586
|
+
HttpClientResponse
|
|
587
|
+
} from "@effect/platform"
|
|
569
588
|
import { Console, Effect } from "effect"
|
|
570
589
|
|
|
571
|
-
const getText =
|
|
572
|
-
|
|
573
|
-
|
|
590
|
+
const getText = HttpClientRequest.get(
|
|
591
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
592
|
+
).pipe(HttpClient.fetch, HttpClientResponse.text)
|
|
574
593
|
|
|
575
594
|
NodeRuntime.runMain(getText.pipe(Effect.andThen(Console.log)))
|
|
576
595
|
/*
|
|
@@ -579,16 +598,20 @@ Output:
|
|
|
579
598
|
*/
|
|
580
599
|
```
|
|
581
600
|
|
|
582
|
-
However, if we use `
|
|
601
|
+
However, if we use `HttpClient.filterStatusOk`, an error is logged:
|
|
583
602
|
|
|
584
603
|
```ts
|
|
585
604
|
import { NodeRuntime } from "@effect/platform-node"
|
|
586
|
-
import
|
|
605
|
+
import {
|
|
606
|
+
HttpClient,
|
|
607
|
+
HttpClientRequest,
|
|
608
|
+
HttpClientResponse
|
|
609
|
+
} from "@effect/platform"
|
|
587
610
|
import { Console, Effect } from "effect"
|
|
588
611
|
|
|
589
|
-
const getText =
|
|
590
|
-
|
|
591
|
-
|
|
612
|
+
const getText = HttpClientRequest.get(
|
|
613
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
614
|
+
).pipe(HttpClient.filterStatusOk(HttpClient.fetch), HttpClientResponse.text)
|
|
592
615
|
|
|
593
616
|
NodeRuntime.runMain(getText.pipe(Effect.andThen(Console.log)))
|
|
594
617
|
/*
|
|
@@ -597,48 +620,52 @@ timestamp=2024-03-25T10:21:16.972Z level=ERROR fiber=#0 cause="ResponseError: St
|
|
|
597
620
|
*/
|
|
598
621
|
```
|
|
599
622
|
|
|
600
|
-
Note that you can use `
|
|
623
|
+
Note that you can use `HttpClient.fetchOk` as a shortcut for `HttpClient.filterStatusOk(HttpClient.fetch)`:
|
|
601
624
|
|
|
602
625
|
```ts
|
|
603
|
-
const getText =
|
|
604
|
-
|
|
605
|
-
|
|
626
|
+
const getText = HttpClientRequest.get(
|
|
627
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
628
|
+
).pipe(HttpClient.fetchOk, HttpClientResponse.text)
|
|
606
629
|
```
|
|
607
630
|
|
|
608
|
-
You can also create your own status-based filters. In fact, `
|
|
631
|
+
You can also create your own status-based filters. In fact, `HttpClient.filterStatusOk` is just a shortcut for the following filter:
|
|
609
632
|
|
|
610
633
|
```ts
|
|
611
|
-
const getText =
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
634
|
+
const getText = HttpClientRequest.get(
|
|
635
|
+
"https://jsonplaceholder.typicode.com/non-existing-page"
|
|
636
|
+
).pipe(
|
|
637
|
+
HttpClient.filterStatus(
|
|
638
|
+
HttpClient.fetch,
|
|
639
|
+
(status) => status >= 200 && status < 300
|
|
640
|
+
),
|
|
641
|
+
HttpClientResponse.text
|
|
642
|
+
)
|
|
620
643
|
```
|
|
621
644
|
|
|
622
645
|
## POST
|
|
623
646
|
|
|
624
|
-
To make a POST request, you can use the `
|
|
647
|
+
To make a POST request, you can use the `HttpClientRequest.post` function provided by the `HttpClient` module. Here's an example of how to create and send a POST request:
|
|
625
648
|
|
|
626
649
|
```ts
|
|
627
650
|
import { NodeRuntime } from "@effect/platform-node"
|
|
628
|
-
import
|
|
651
|
+
import {
|
|
652
|
+
HttpClient,
|
|
653
|
+
HttpClientRequest,
|
|
654
|
+
HttpClientResponse
|
|
655
|
+
} from "@effect/platform"
|
|
629
656
|
import { Console, Effect } from "effect"
|
|
630
657
|
|
|
631
|
-
const addPost =
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
658
|
+
const addPost = HttpClientRequest.post(
|
|
659
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
660
|
+
).pipe(
|
|
661
|
+
HttpClientRequest.jsonBody({
|
|
662
|
+
title: "foo",
|
|
663
|
+
body: "bar",
|
|
664
|
+
userId: 1
|
|
665
|
+
}),
|
|
666
|
+
Effect.andThen(HttpClient.fetch),
|
|
667
|
+
HttpClientResponse.json
|
|
668
|
+
)
|
|
642
669
|
|
|
643
670
|
NodeRuntime.runMain(addPost.pipe(Effect.andThen(Console.log)))
|
|
644
671
|
/*
|
|
@@ -647,29 +674,33 @@ Output:
|
|
|
647
674
|
*/
|
|
648
675
|
```
|
|
649
676
|
|
|
650
|
-
If you need to send data in a format other than JSON, such as plain text, you can use different APIs provided by `
|
|
677
|
+
If you need to send data in a format other than JSON, such as plain text, you can use different APIs provided by `HttpClientRequest`.
|
|
651
678
|
|
|
652
679
|
In the following example, we send the data as text:
|
|
653
680
|
|
|
654
681
|
```ts
|
|
655
682
|
import { NodeRuntime } from "@effect/platform-node"
|
|
656
|
-
import
|
|
683
|
+
import {
|
|
684
|
+
HttpClient,
|
|
685
|
+
HttpClientRequest,
|
|
686
|
+
HttpClientResponse
|
|
687
|
+
} from "@effect/platform"
|
|
657
688
|
import { Console, Effect } from "effect"
|
|
658
689
|
|
|
659
|
-
const addPost =
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
690
|
+
const addPost = HttpClientRequest.post(
|
|
691
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
692
|
+
).pipe(
|
|
693
|
+
HttpClientRequest.textBody(
|
|
694
|
+
JSON.stringify({
|
|
695
|
+
title: "foo",
|
|
696
|
+
body: "bar",
|
|
697
|
+
userId: 1
|
|
698
|
+
}),
|
|
699
|
+
"application/json; charset=UTF-8"
|
|
700
|
+
),
|
|
701
|
+
HttpClient.fetch,
|
|
702
|
+
HttpClientResponse.json
|
|
703
|
+
)
|
|
673
704
|
|
|
674
705
|
NodeRuntime.runMain(Effect.andThen(addPost, Console.log))
|
|
675
706
|
/*
|
|
@@ -684,7 +715,11 @@ A common use case when fetching data is to validate the received format. For thi
|
|
|
684
715
|
|
|
685
716
|
```ts
|
|
686
717
|
import { NodeRuntime } from "@effect/platform-node"
|
|
687
|
-
import
|
|
718
|
+
import {
|
|
719
|
+
HttpClient,
|
|
720
|
+
HttpClientRequest,
|
|
721
|
+
HttpClientResponse
|
|
722
|
+
} from "@effect/platform"
|
|
688
723
|
import { Schema } from "@effect/schema"
|
|
689
724
|
import { Console, Effect } from "effect"
|
|
690
725
|
|
|
@@ -693,18 +728,18 @@ const Post = Schema.Struct({
|
|
|
693
728
|
title: Schema.String
|
|
694
729
|
})
|
|
695
730
|
|
|
696
|
-
const addPost =
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
731
|
+
const addPost = HttpClientRequest.post(
|
|
732
|
+
"https://jsonplaceholder.typicode.com/posts"
|
|
733
|
+
).pipe(
|
|
734
|
+
HttpClientRequest.jsonBody({
|
|
735
|
+
title: "foo",
|
|
736
|
+
body: "bar",
|
|
737
|
+
userId: 1
|
|
738
|
+
}),
|
|
739
|
+
Effect.andThen(HttpClient.fetch),
|
|
740
|
+
Effect.andThen(HttpClientResponse.schemaBodyJson(Post)),
|
|
741
|
+
Effect.scoped
|
|
742
|
+
)
|
|
708
743
|
|
|
709
744
|
NodeRuntime.runMain(addPost.pipe(Effect.andThen(Console.log)))
|
|
710
745
|
/*
|
|
@@ -720,19 +755,24 @@ Output:
|
|
|
720
755
|
To test HTTP requests, you can inject a mock fetch implementation.
|
|
721
756
|
|
|
722
757
|
```ts
|
|
723
|
-
import
|
|
758
|
+
import {
|
|
759
|
+
HttpClient,
|
|
760
|
+
HttpClientRequest,
|
|
761
|
+
HttpClientResponse
|
|
762
|
+
} from "@effect/platform"
|
|
724
763
|
import { Effect, Layer } from "effect"
|
|
725
764
|
import * as assert from "node:assert"
|
|
726
765
|
|
|
727
766
|
// Mock fetch implementation
|
|
728
|
-
const FetchTest = Layer.succeed(
|
|
767
|
+
const FetchTest = Layer.succeed(HttpClient.Fetch, () =>
|
|
729
768
|
Promise.resolve(new Response("not found", { status: 404 }))
|
|
730
769
|
)
|
|
731
770
|
|
|
732
771
|
// Program to test
|
|
733
|
-
const program =
|
|
734
|
-
.
|
|
735
|
-
.
|
|
772
|
+
const program = HttpClientRequest.get("https://www.google.com/").pipe(
|
|
773
|
+
HttpClient.fetch,
|
|
774
|
+
HttpClientResponse.text
|
|
775
|
+
)
|
|
736
776
|
|
|
737
777
|
// Test
|
|
738
778
|
Effect.gen(function* () {
|
|
@@ -784,27 +824,24 @@ In this example, we will create a simple HTTP server that listens on port `3000`
|
|
|
784
824
|
Node.js Example
|
|
785
825
|
|
|
786
826
|
```ts
|
|
787
|
-
import { HttpServer } from "@effect/platform"
|
|
827
|
+
import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform"
|
|
788
828
|
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node"
|
|
789
829
|
import { Layer } from "effect"
|
|
790
830
|
import { createServer } from "node:http"
|
|
791
831
|
|
|
792
832
|
// Define the router with a single route for the root URL
|
|
793
|
-
const router =
|
|
794
|
-
|
|
833
|
+
const router = HttpRouter.empty.pipe(
|
|
834
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
795
835
|
)
|
|
796
836
|
|
|
797
837
|
// Set up the application server with logging
|
|
798
|
-
const app = router.pipe(
|
|
799
|
-
HttpServer.server.serve(),
|
|
800
|
-
HttpServer.server.withLogAddress
|
|
801
|
-
)
|
|
838
|
+
const app = router.pipe(HttpServer.serve(), HttpServer.withLogAddress)
|
|
802
839
|
|
|
803
840
|
// Specify the port
|
|
804
841
|
const port = 3000
|
|
805
842
|
|
|
806
843
|
// Create a server layer with the specified port
|
|
807
|
-
const ServerLive = NodeHttpServer.
|
|
844
|
+
const ServerLive = NodeHttpServer.layer(() => createServer(), { port })
|
|
808
845
|
|
|
809
846
|
// Run the application
|
|
810
847
|
NodeRuntime.runMain(Layer.launch(Layer.provide(app, ServerLive)))
|
|
@@ -816,31 +853,28 @@ timestamp=... level=INFO fiber=#0 message="Listening on http://localhost:3000"
|
|
|
816
853
|
```
|
|
817
854
|
|
|
818
855
|
> [!NOTE]
|
|
819
|
-
> The `HttpServer.
|
|
856
|
+
> The `HttpServer.withLogAddress` middleware logs the address and port where the server is listening, helping to confirm that the server is running correctly and accessible on the expected endpoint.
|
|
820
857
|
|
|
821
858
|
Bun Example
|
|
822
859
|
|
|
823
860
|
```ts
|
|
824
|
-
import { HttpServer } from "@effect/platform"
|
|
861
|
+
import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform"
|
|
825
862
|
import { BunHttpServer, BunRuntime } from "@effect/platform-bun"
|
|
826
863
|
import { Layer } from "effect"
|
|
827
864
|
|
|
828
865
|
// Define the router with a single route for the root URL
|
|
829
|
-
const router =
|
|
830
|
-
|
|
866
|
+
const router = HttpRouter.empty.pipe(
|
|
867
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
831
868
|
)
|
|
832
869
|
|
|
833
870
|
// Set up the application server with logging
|
|
834
|
-
const app = router.pipe(
|
|
835
|
-
HttpServer.server.serve(),
|
|
836
|
-
HttpServer.server.withLogAddress
|
|
837
|
-
)
|
|
871
|
+
const app = router.pipe(HttpServer.serve(), HttpServer.withLogAddress)
|
|
838
872
|
|
|
839
873
|
// Specify the port
|
|
840
874
|
const port = 3000
|
|
841
875
|
|
|
842
876
|
// Create a server layer with the specified port
|
|
843
|
-
const ServerLive = BunHttpServer.
|
|
877
|
+
const ServerLive = BunHttpServer.layer({ port })
|
|
844
878
|
|
|
845
879
|
// Run the application
|
|
846
880
|
BunRuntime.runMain(Layer.launch(Layer.provide(app, ServerLive)))
|
|
@@ -854,7 +888,7 @@ timestamp=... level=INFO fiber=#0 message="Listening on http://localhost:3000"
|
|
|
854
888
|
To avoid boilerplate code for the final server setup, we'll use a helper function from the `listen.ts` file:
|
|
855
889
|
|
|
856
890
|
```ts
|
|
857
|
-
import
|
|
891
|
+
import { HttpPlatform, HttpServer } from "@effect/platform"
|
|
858
892
|
import { NodeHttpServer, NodeRuntime } from "@effect/platform-node"
|
|
859
893
|
import { Layer } from "effect"
|
|
860
894
|
import { createServer } from "node:http"
|
|
@@ -863,7 +897,7 @@ export const listen = (
|
|
|
863
897
|
app: Layer.Layer<
|
|
864
898
|
never,
|
|
865
899
|
never,
|
|
866
|
-
|
|
900
|
+
HttpPlatform.HttpPlatform | HttpServer.HttpServer
|
|
867
901
|
>,
|
|
868
902
|
port: number
|
|
869
903
|
) =>
|
|
@@ -871,7 +905,7 @@ export const listen = (
|
|
|
871
905
|
Layer.launch(
|
|
872
906
|
Layer.provide(
|
|
873
907
|
app,
|
|
874
|
-
NodeHttpServer.
|
|
908
|
+
NodeHttpServer.layer(() => createServer(), { port })
|
|
875
909
|
)
|
|
876
910
|
)
|
|
877
911
|
)
|
|
@@ -884,7 +918,7 @@ Routing refers to determining how an application responds to a client request to
|
|
|
884
918
|
Route definition takes the following structure:
|
|
885
919
|
|
|
886
920
|
```
|
|
887
|
-
router.pipe(
|
|
921
|
+
router.pipe(HttpRouter.METHOD(PATH, HANDLER))
|
|
888
922
|
```
|
|
889
923
|
|
|
890
924
|
Where:
|
|
@@ -899,25 +933,20 @@ The following examples illustrate defining simple routes.
|
|
|
899
933
|
Respond with `"Hello World!"` on the homepage:
|
|
900
934
|
|
|
901
935
|
```ts
|
|
902
|
-
router.pipe(
|
|
936
|
+
router.pipe(HttpRouter.get("/", HttpServerResponse.text("Hello World")))
|
|
903
937
|
```
|
|
904
938
|
|
|
905
939
|
Respond to POST request on the root route (/), the application's home page:
|
|
906
940
|
|
|
907
941
|
```ts
|
|
908
|
-
router.pipe(
|
|
909
|
-
HttpServer.router.post("/", HttpServer.response.text("Got a POST request"))
|
|
910
|
-
)
|
|
942
|
+
router.pipe(HttpRouter.post("/", HttpServerResponse.text("Got a POST request")))
|
|
911
943
|
```
|
|
912
944
|
|
|
913
945
|
Respond to a PUT request to the `/user` route:
|
|
914
946
|
|
|
915
947
|
```ts
|
|
916
948
|
router.pipe(
|
|
917
|
-
|
|
918
|
-
"/user",
|
|
919
|
-
HttpServer.response.text("Got a PUT request at /user")
|
|
920
|
-
)
|
|
949
|
+
HttpRouter.put("/user", HttpServerResponse.text("Got a PUT request at /user"))
|
|
921
950
|
)
|
|
922
951
|
```
|
|
923
952
|
|
|
@@ -925,26 +954,26 @@ Respond to a DELETE request to the `/user` route:
|
|
|
925
954
|
|
|
926
955
|
```ts
|
|
927
956
|
router.pipe(
|
|
928
|
-
|
|
957
|
+
HttpRouter.del(
|
|
929
958
|
"/user",
|
|
930
|
-
|
|
959
|
+
HttpServerResponse.text("Got a DELETE request at /user")
|
|
931
960
|
)
|
|
932
961
|
)
|
|
933
962
|
```
|
|
934
963
|
|
|
935
964
|
### Serving static files
|
|
936
965
|
|
|
937
|
-
To serve static files such as images, CSS files, and JavaScript files, use the `
|
|
966
|
+
To serve static files such as images, CSS files, and JavaScript files, use the `HttpServerResponse.file` built-in action.
|
|
938
967
|
|
|
939
968
|
```ts
|
|
940
|
-
import { HttpServer } from "@effect/platform"
|
|
969
|
+
import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform"
|
|
941
970
|
import { listen } from "./listen.js"
|
|
942
971
|
|
|
943
|
-
const router =
|
|
944
|
-
|
|
972
|
+
const router = HttpRouter.empty.pipe(
|
|
973
|
+
HttpRouter.get("/", HttpServerResponse.file("index.html"))
|
|
945
974
|
)
|
|
946
975
|
|
|
947
|
-
const app = router.pipe(HttpServer.
|
|
976
|
+
const app = router.pipe(HttpServer.serve())
|
|
948
977
|
|
|
949
978
|
listen(app, 3000)
|
|
950
979
|
```
|
|
@@ -970,7 +999,7 @@ Create an `index.html` file in your project directory:
|
|
|
970
999
|
|
|
971
1000
|
Routing refers to how an application's endpoints (URIs) respond to client requests.
|
|
972
1001
|
|
|
973
|
-
You define routing using methods of the `
|
|
1002
|
+
You define routing using methods of the `HttpRouter` object that correspond to HTTP methods; for example, `HttpRouter.get()` to handle GET requests and `HttpRouter.post` to handle POST requests. You can also use `HttpRouter.all()` to handle all HTTP methods.
|
|
974
1003
|
|
|
975
1004
|
These routing methods specify a `Route.Handler` called when the application receives a request to the specified route (endpoint) and HTTP method. In other words, the application “listens” for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified handler.
|
|
976
1005
|
|
|
@@ -978,39 +1007,33 @@ The following code is an example of a very basic route.
|
|
|
978
1007
|
|
|
979
1008
|
```ts
|
|
980
1009
|
// respond with "hello world" when a GET request is made to the homepage
|
|
981
|
-
|
|
1010
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
982
1011
|
```
|
|
983
1012
|
|
|
984
1013
|
### Route methods
|
|
985
1014
|
|
|
986
|
-
A route method is derived from one of the HTTP methods, and is attached to an instance of the `
|
|
1015
|
+
A route method is derived from one of the HTTP methods, and is attached to an instance of the `HttpRouter` object.
|
|
987
1016
|
|
|
988
1017
|
The following code is an example of routes that are defined for the GET and the POST methods to the root of the app.
|
|
989
1018
|
|
|
990
1019
|
```ts
|
|
991
1020
|
// GET method route
|
|
992
|
-
|
|
993
|
-
"/",
|
|
994
|
-
HttpServer.response.text("GET request to the homepage")
|
|
995
|
-
)
|
|
1021
|
+
HttpRouter.get("/", HttpServerResponse.text("GET request to the homepage"))
|
|
996
1022
|
|
|
997
1023
|
// POST method route
|
|
998
|
-
|
|
999
|
-
"/",
|
|
1000
|
-
HttpServer.response.text("POST request to the homepage")
|
|
1001
|
-
)
|
|
1024
|
+
HttpRouter.post("/", HttpServerResponse.text("POST request to the homepage"))
|
|
1002
1025
|
```
|
|
1003
1026
|
|
|
1004
|
-
`
|
|
1027
|
+
`HttpRouter` supports methods that correspond to all HTTP request methods: `get`, `post`, and so on.
|
|
1005
1028
|
|
|
1006
|
-
There is a special routing method, `
|
|
1029
|
+
There is a special routing method, `HttpRouter.all()`, used to load middleware functions at a path for **all** HTTP request methods. For example, the following handler is executed for requests to the route “/secret” whether using GET, POST, PUT, DELETE.
|
|
1007
1030
|
|
|
1008
1031
|
```ts
|
|
1009
|
-
|
|
1032
|
+
HttpRouter.all(
|
|
1010
1033
|
"/secret",
|
|
1011
|
-
|
|
1012
|
-
.
|
|
1013
|
-
|
|
1034
|
+
HttpServerResponse.empty().pipe(
|
|
1035
|
+
Effect.tap(Console.log("Accessing the secret section ..."))
|
|
1036
|
+
)
|
|
1014
1037
|
)
|
|
1015
1038
|
```
|
|
1016
1039
|
|
|
@@ -1030,22 +1053,22 @@ Here are some examples of route paths based on strings.
|
|
|
1030
1053
|
This route path will match requests to the root route, /.
|
|
1031
1054
|
|
|
1032
1055
|
```ts
|
|
1033
|
-
|
|
1056
|
+
HttpRouter.get("/", HttpServerResponse.text("root"))
|
|
1034
1057
|
```
|
|
1035
1058
|
|
|
1036
1059
|
This route path will match requests to `/user`.
|
|
1037
1060
|
|
|
1038
1061
|
```ts
|
|
1039
|
-
|
|
1062
|
+
HttpRouter.get("/user", HttpServerResponse.text("user"))
|
|
1040
1063
|
```
|
|
1041
1064
|
|
|
1042
1065
|
This route path matches requests to any path starting with `/user` (e.g., `/user`, `/users`, etc.)
|
|
1043
1066
|
|
|
1044
1067
|
```ts
|
|
1045
|
-
|
|
1068
|
+
HttpRouter.get(
|
|
1046
1069
|
"/user*",
|
|
1047
|
-
Effect.map(
|
|
1048
|
-
|
|
1070
|
+
Effect.map(HttpServerRequest.HttpServerRequest, (req) =>
|
|
1071
|
+
HttpServerResponse.text(req.url)
|
|
1049
1072
|
)
|
|
1050
1073
|
)
|
|
1051
1074
|
```
|
|
@@ -1067,7 +1090,7 @@ params: { "userId": "34", "bookId": "8989" }
|
|
|
1067
1090
|
To define routes with parameters, include the parameter names in the path and use a schema to validate and parse these parameters, as shown below.
|
|
1068
1091
|
|
|
1069
1092
|
```ts
|
|
1070
|
-
import { HttpServer } from "@effect/platform"
|
|
1093
|
+
import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform"
|
|
1071
1094
|
import { Schema } from "@effect/schema"
|
|
1072
1095
|
import { Effect } from "effect"
|
|
1073
1096
|
import { listen } from "./listen.js"
|
|
@@ -1079,23 +1102,23 @@ const Params = Schema.Struct({
|
|
|
1079
1102
|
})
|
|
1080
1103
|
|
|
1081
1104
|
// Create a router with a route that captures parameters
|
|
1082
|
-
const router =
|
|
1083
|
-
|
|
1105
|
+
const router = HttpRouter.empty.pipe(
|
|
1106
|
+
HttpRouter.get(
|
|
1084
1107
|
"/users/:userId/books/:bookId",
|
|
1085
|
-
|
|
1086
|
-
.
|
|
1087
|
-
|
|
1108
|
+
HttpRouter.schemaPathParams(Params).pipe(
|
|
1109
|
+
Effect.flatMap((params) => HttpServerResponse.json(params))
|
|
1110
|
+
)
|
|
1088
1111
|
)
|
|
1089
1112
|
)
|
|
1090
1113
|
|
|
1091
|
-
const app = router.pipe(HttpServer.
|
|
1114
|
+
const app = router.pipe(HttpServer.serve())
|
|
1092
1115
|
|
|
1093
1116
|
listen(app, 3000)
|
|
1094
1117
|
```
|
|
1095
1118
|
|
|
1096
1119
|
### Response methods
|
|
1097
1120
|
|
|
1098
|
-
The methods on `
|
|
1121
|
+
The methods on `HttpServerResponse` object in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.
|
|
1099
1122
|
|
|
1100
1123
|
| Method | Description |
|
|
1101
1124
|
| ------------ | ------------------------------ |
|
|
@@ -1109,34 +1132,32 @@ The methods on `HttpServer.response` object in the following table can send a re
|
|
|
1109
1132
|
|
|
1110
1133
|
### Router
|
|
1111
1134
|
|
|
1112
|
-
Use the `
|
|
1135
|
+
Use the `HttpRouter` object to create modular, mountable route handlers. A `Router` instance is a complete middleware and routing system, often referred to as a "mini-app."
|
|
1113
1136
|
|
|
1114
1137
|
The following example shows how to create a router as a module, define some routes, and mount the router module on a path in the main app.
|
|
1115
1138
|
|
|
1116
1139
|
Create a file named `birds.ts` in your app directory with the following content:
|
|
1117
1140
|
|
|
1118
1141
|
```ts
|
|
1119
|
-
import {
|
|
1142
|
+
import { HttpRouter, HttpServerResponse } from "@effect/platform"
|
|
1120
1143
|
|
|
1121
|
-
export const birds =
|
|
1122
|
-
|
|
1123
|
-
|
|
1144
|
+
export const birds = HttpRouter.empty.pipe(
|
|
1145
|
+
HttpRouter.get("/", HttpServerResponse.text("Birds home page")),
|
|
1146
|
+
HttpRouter.get("/about", HttpServerResponse.text("About birds"))
|
|
1124
1147
|
)
|
|
1125
1148
|
```
|
|
1126
1149
|
|
|
1127
1150
|
In your main application file, load the router module and mount it.
|
|
1128
1151
|
|
|
1129
1152
|
```ts
|
|
1130
|
-
import { HttpServer } from "@effect/platform"
|
|
1153
|
+
import { HttpRouter, HttpServer } from "@effect/platform"
|
|
1131
1154
|
import { birds } from "./birds.js"
|
|
1132
1155
|
import { listen } from "./listen.js"
|
|
1133
1156
|
|
|
1134
1157
|
// Create the main router and mount the birds router
|
|
1135
|
-
const router =
|
|
1136
|
-
HttpServer.router.mount("/birds", birds)
|
|
1137
|
-
)
|
|
1158
|
+
const router = HttpRouter.empty.pipe(HttpRouter.mount("/birds", birds))
|
|
1138
1159
|
|
|
1139
|
-
const app = router.pipe(HttpServer.
|
|
1160
|
+
const app = router.pipe(HttpServer.serve())
|
|
1140
1161
|
|
|
1141
1162
|
listen(app, 3000)
|
|
1142
1163
|
```
|
|
@@ -1156,7 +1177,7 @@ Here is an example of a basic "Hello World" application with middleware.
|
|
|
1156
1177
|
This middleware logs "LOGGED" whenever a request passes through it.
|
|
1157
1178
|
|
|
1158
1179
|
```ts
|
|
1159
|
-
const myLogger =
|
|
1180
|
+
const myLogger = HttpMiddleware.make((app) =>
|
|
1160
1181
|
Effect.gen(function* () {
|
|
1161
1182
|
console.log("LOGGED")
|
|
1162
1183
|
return yield* app
|
|
@@ -1164,28 +1185,30 @@ const myLogger = HttpServer.middleware.make((app) =>
|
|
|
1164
1185
|
)
|
|
1165
1186
|
```
|
|
1166
1187
|
|
|
1167
|
-
To use the middleware, add it to the router using `
|
|
1188
|
+
To use the middleware, add it to the router using `HttpRouter.use()`:
|
|
1168
1189
|
|
|
1169
1190
|
```ts
|
|
1170
|
-
import {
|
|
1191
|
+
import {
|
|
1192
|
+
HttpMiddleware,
|
|
1193
|
+
HttpRouter,
|
|
1194
|
+
HttpServer,
|
|
1195
|
+
HttpServerResponse
|
|
1196
|
+
} from "@effect/platform"
|
|
1171
1197
|
import { Effect } from "effect"
|
|
1172
1198
|
import { listen } from "./listen.js"
|
|
1173
1199
|
|
|
1174
|
-
const myLogger =
|
|
1200
|
+
const myLogger = HttpMiddleware.make((app) =>
|
|
1175
1201
|
Effect.gen(function* () {
|
|
1176
1202
|
console.log("LOGGED")
|
|
1177
1203
|
return yield* app
|
|
1178
1204
|
})
|
|
1179
1205
|
)
|
|
1180
1206
|
|
|
1181
|
-
const router =
|
|
1182
|
-
|
|
1207
|
+
const router = HttpRouter.empty.pipe(
|
|
1208
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
1183
1209
|
)
|
|
1184
1210
|
|
|
1185
|
-
const app = router.pipe(
|
|
1186
|
-
HttpServer.router.use(myLogger),
|
|
1187
|
-
HttpServer.server.serve()
|
|
1188
|
-
)
|
|
1211
|
+
const app = router.pipe(HttpRouter.use(myLogger), HttpServer.serve())
|
|
1189
1212
|
|
|
1190
1213
|
listen(app, 3000)
|
|
1191
1214
|
```
|
|
@@ -1199,7 +1222,7 @@ Next, we'll create a middleware that records the timestamp of each HTTP request
|
|
|
1199
1222
|
```ts
|
|
1200
1223
|
class RequestTime extends Context.Tag("RequestTime")<RequestTime, number>() {}
|
|
1201
1224
|
|
|
1202
|
-
const requestTime =
|
|
1225
|
+
const requestTime = HttpMiddleware.make((app) =>
|
|
1203
1226
|
Effect.gen(function* () {
|
|
1204
1227
|
return yield* app.pipe(Effect.provideService(RequestTime, Date.now()))
|
|
1205
1228
|
})
|
|
@@ -1209,33 +1232,35 @@ const requestTime = HttpServer.middleware.make((app) =>
|
|
|
1209
1232
|
Update the app to use this middleware and display the timestamp in the response:
|
|
1210
1233
|
|
|
1211
1234
|
```ts
|
|
1212
|
-
import {
|
|
1235
|
+
import {
|
|
1236
|
+
HttpMiddleware,
|
|
1237
|
+
HttpRouter,
|
|
1238
|
+
HttpServer,
|
|
1239
|
+
HttpServerResponse
|
|
1240
|
+
} from "@effect/platform"
|
|
1213
1241
|
import { Context, Effect } from "effect"
|
|
1214
1242
|
import { listen } from "./listen.js"
|
|
1215
1243
|
|
|
1216
1244
|
class RequestTime extends Context.Tag("RequestTime")<RequestTime, number>() {}
|
|
1217
1245
|
|
|
1218
|
-
const requestTime =
|
|
1246
|
+
const requestTime = HttpMiddleware.make((app) =>
|
|
1219
1247
|
Effect.gen(function* () {
|
|
1220
1248
|
return yield* app.pipe(Effect.provideService(RequestTime, Date.now()))
|
|
1221
1249
|
})
|
|
1222
1250
|
)
|
|
1223
1251
|
|
|
1224
|
-
const router =
|
|
1225
|
-
|
|
1252
|
+
const router = HttpRouter.empty.pipe(
|
|
1253
|
+
HttpRouter.get(
|
|
1226
1254
|
"/",
|
|
1227
1255
|
Effect.gen(function* () {
|
|
1228
1256
|
const requestTime = yield* RequestTime
|
|
1229
1257
|
const responseText = `Hello World<br/><small>Requested at: ${requestTime}</small>`
|
|
1230
|
-
return yield*
|
|
1258
|
+
return yield* HttpServerResponse.html(responseText)
|
|
1231
1259
|
})
|
|
1232
1260
|
)
|
|
1233
1261
|
)
|
|
1234
1262
|
|
|
1235
|
-
const app = router.pipe(
|
|
1236
|
-
HttpServer.router.use(requestTime),
|
|
1237
|
-
HttpServer.server.serve()
|
|
1238
|
-
)
|
|
1263
|
+
const app = router.pipe(HttpRouter.use(requestTime), HttpServer.serve())
|
|
1239
1264
|
|
|
1240
1265
|
listen(app, 3000)
|
|
1241
1266
|
```
|
|
@@ -1258,14 +1283,14 @@ const externallyValidateCookie = (testCookie: string | undefined) =>
|
|
|
1258
1283
|
? Effect.succeed(testCookie)
|
|
1259
1284
|
: Effect.fail(new CookieError())
|
|
1260
1285
|
|
|
1261
|
-
const cookieValidator =
|
|
1286
|
+
const cookieValidator = HttpMiddleware.make((app) =>
|
|
1262
1287
|
Effect.gen(function* () {
|
|
1263
|
-
const req = yield*
|
|
1288
|
+
const req = yield* HttpServerRequest.HttpServerRequest
|
|
1264
1289
|
yield* externallyValidateCookie(req.cookies.testCookie)
|
|
1265
1290
|
return yield* app
|
|
1266
1291
|
}).pipe(
|
|
1267
1292
|
Effect.catchTag("CookieError", () =>
|
|
1268
|
-
|
|
1293
|
+
HttpServerResponse.text("Invalid cookie")
|
|
1269
1294
|
)
|
|
1270
1295
|
)
|
|
1271
1296
|
)
|
|
@@ -1274,7 +1299,13 @@ const cookieValidator = HttpServer.middleware.make((app) =>
|
|
|
1274
1299
|
Update the app to use the `cookieValidator` middleware:
|
|
1275
1300
|
|
|
1276
1301
|
```ts
|
|
1277
|
-
import {
|
|
1302
|
+
import {
|
|
1303
|
+
HttpMiddleware,
|
|
1304
|
+
HttpRouter,
|
|
1305
|
+
HttpServer,
|
|
1306
|
+
HttpServerRequest,
|
|
1307
|
+
HttpServerResponse
|
|
1308
|
+
} from "@effect/platform"
|
|
1278
1309
|
import { Effect } from "effect"
|
|
1279
1310
|
import { listen } from "./listen.js"
|
|
1280
1311
|
|
|
@@ -1287,26 +1318,23 @@ const externallyValidateCookie = (testCookie: string | undefined) =>
|
|
|
1287
1318
|
? Effect.succeed(testCookie)
|
|
1288
1319
|
: Effect.fail(new CookieError())
|
|
1289
1320
|
|
|
1290
|
-
const cookieValidator =
|
|
1321
|
+
const cookieValidator = HttpMiddleware.make((app) =>
|
|
1291
1322
|
Effect.gen(function* () {
|
|
1292
|
-
const req = yield*
|
|
1323
|
+
const req = yield* HttpServerRequest.HttpServerRequest
|
|
1293
1324
|
yield* externallyValidateCookie(req.cookies.testCookie)
|
|
1294
1325
|
return yield* app
|
|
1295
1326
|
}).pipe(
|
|
1296
1327
|
Effect.catchTag("CookieError", () =>
|
|
1297
|
-
|
|
1328
|
+
HttpServerResponse.text("Invalid cookie")
|
|
1298
1329
|
)
|
|
1299
1330
|
)
|
|
1300
1331
|
)
|
|
1301
1332
|
|
|
1302
|
-
const router =
|
|
1303
|
-
|
|
1333
|
+
const router = HttpRouter.empty.pipe(
|
|
1334
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
1304
1335
|
)
|
|
1305
1336
|
|
|
1306
|
-
const app = router.pipe(
|
|
1307
|
-
HttpServer.router.use(cookieValidator),
|
|
1308
|
-
HttpServer.server.serve()
|
|
1309
|
-
)
|
|
1337
|
+
const app = router.pipe(HttpRouter.use(cookieValidator), HttpServer.serve())
|
|
1310
1338
|
|
|
1311
1339
|
listen(app, 3000)
|
|
1312
1340
|
```
|
|
@@ -1338,33 +1366,32 @@ At the route level, middlewares are applied to specific endpoints, allowing for
|
|
|
1338
1366
|
Here’s a practical example showing how to apply middleware at the route level:
|
|
1339
1367
|
|
|
1340
1368
|
```ts
|
|
1341
|
-
import {
|
|
1369
|
+
import {
|
|
1370
|
+
HttpMiddleware,
|
|
1371
|
+
HttpRouter,
|
|
1372
|
+
HttpServer,
|
|
1373
|
+
HttpServerResponse
|
|
1374
|
+
} from "@effect/platform"
|
|
1342
1375
|
import { Effect } from "effect"
|
|
1343
1376
|
import { listen } from "./listen.js"
|
|
1344
1377
|
|
|
1345
1378
|
// Middleware constructor that logs the name of the middleware
|
|
1346
1379
|
const withMiddleware = (name: string) =>
|
|
1347
|
-
|
|
1380
|
+
HttpMiddleware.make((app) =>
|
|
1348
1381
|
Effect.gen(function* () {
|
|
1349
1382
|
console.log(name) // Log the middleware name when the route is accessed
|
|
1350
1383
|
return yield* app // Continue with the original application flow
|
|
1351
1384
|
})
|
|
1352
1385
|
)
|
|
1353
1386
|
|
|
1354
|
-
const router =
|
|
1387
|
+
const router = HttpRouter.empty.pipe(
|
|
1355
1388
|
// Applying middleware to route "/a"
|
|
1356
|
-
|
|
1357
|
-
"/a",
|
|
1358
|
-
HttpServer.response.text("a").pipe(withMiddleware("M1"))
|
|
1359
|
-
),
|
|
1389
|
+
HttpRouter.get("/a", HttpServerResponse.text("a").pipe(withMiddleware("M1"))),
|
|
1360
1390
|
// Applying middleware to route "/b"
|
|
1361
|
-
|
|
1362
|
-
"/b",
|
|
1363
|
-
HttpServer.response.text("b").pipe(withMiddleware("M2"))
|
|
1364
|
-
)
|
|
1391
|
+
HttpRouter.get("/b", HttpServerResponse.text("b").pipe(withMiddleware("M2")))
|
|
1365
1392
|
)
|
|
1366
1393
|
|
|
1367
|
-
const app = router.pipe(HttpServer.
|
|
1394
|
+
const app = router.pipe(HttpServer.serve())
|
|
1368
1395
|
|
|
1369
1396
|
listen(app, 3000)
|
|
1370
1397
|
```
|
|
@@ -1392,13 +1419,18 @@ Applying middleware at the router level is an efficient way to manage common fun
|
|
|
1392
1419
|
Here’s how you can structure and apply middleware across different routers using the `@effect/platform` library:
|
|
1393
1420
|
|
|
1394
1421
|
```ts
|
|
1395
|
-
import {
|
|
1422
|
+
import {
|
|
1423
|
+
HttpMiddleware,
|
|
1424
|
+
HttpRouter,
|
|
1425
|
+
HttpServer,
|
|
1426
|
+
HttpServerResponse
|
|
1427
|
+
} from "@effect/platform"
|
|
1396
1428
|
import { Effect } from "effect"
|
|
1397
1429
|
import { listen } from "./listen.js"
|
|
1398
1430
|
|
|
1399
1431
|
// Middleware constructor that logs the name of the middleware
|
|
1400
1432
|
const withMiddleware = (name: string) =>
|
|
1401
|
-
|
|
1433
|
+
HttpMiddleware.make((app) =>
|
|
1402
1434
|
Effect.gen(function* () {
|
|
1403
1435
|
console.log(name) // Log the middleware name when a route is accessed
|
|
1404
1436
|
return yield* app // Continue with the original application flow
|
|
@@ -1406,36 +1438,36 @@ const withMiddleware = (name: string) =>
|
|
|
1406
1438
|
)
|
|
1407
1439
|
|
|
1408
1440
|
// Define Router1 with specific routes
|
|
1409
|
-
const router1 =
|
|
1410
|
-
|
|
1411
|
-
|
|
1441
|
+
const router1 = HttpRouter.empty.pipe(
|
|
1442
|
+
HttpRouter.get("/a", HttpServerResponse.text("a")), // Middleware M4, M3, M1 will apply
|
|
1443
|
+
HttpRouter.get("/b", HttpServerResponse.text("b")), // Middleware M4, M3, M1 will apply
|
|
1412
1444
|
// Apply Middleware at the router level
|
|
1413
|
-
|
|
1414
|
-
|
|
1445
|
+
HttpRouter.use(withMiddleware("M1")),
|
|
1446
|
+
HttpRouter.get("/c", HttpServerResponse.text("c")) // Middleware M4, M3 will apply
|
|
1415
1447
|
)
|
|
1416
1448
|
|
|
1417
1449
|
// Define Router2 with specific routes
|
|
1418
|
-
const router2 =
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1450
|
+
const router2 = HttpRouter.empty.pipe(
|
|
1451
|
+
HttpRouter.get("/d", HttpServerResponse.text("d")), // Middleware M4, M2 will apply
|
|
1452
|
+
HttpRouter.get("/e", HttpServerResponse.text("e")), // Middleware M4, M2 will apply
|
|
1453
|
+
HttpRouter.get("/f", HttpServerResponse.text("f")), // Middleware M4, M2 will apply
|
|
1422
1454
|
// Apply Middleware at the router level
|
|
1423
|
-
|
|
1455
|
+
HttpRouter.use(withMiddleware("M2"))
|
|
1424
1456
|
)
|
|
1425
1457
|
|
|
1426
1458
|
// Main router combining Router1 and Router2
|
|
1427
|
-
const router =
|
|
1428
|
-
|
|
1459
|
+
const router = HttpRouter.empty.pipe(
|
|
1460
|
+
HttpRouter.mount("/r1", router1),
|
|
1429
1461
|
// Apply Middleware affecting all routes under /r1
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1462
|
+
HttpRouter.use(withMiddleware("M3")),
|
|
1463
|
+
HttpRouter.get("/g", HttpServerResponse.text("g")), // Only Middleware M4 will apply
|
|
1464
|
+
HttpRouter.mount("/r2", router2),
|
|
1433
1465
|
// Apply Middleware affecting all routes
|
|
1434
|
-
|
|
1466
|
+
HttpRouter.use(withMiddleware("M4"))
|
|
1435
1467
|
)
|
|
1436
1468
|
|
|
1437
1469
|
// Configure the application with the server middleware
|
|
1438
|
-
const app = router.pipe(HttpServer.
|
|
1470
|
+
const app = router.pipe(HttpServer.serve())
|
|
1439
1471
|
|
|
1440
1472
|
listen(app, 3000)
|
|
1441
1473
|
```
|
|
@@ -1469,30 +1501,32 @@ Applying middleware at the server level allows you to introduce certain function
|
|
|
1469
1501
|
**Example**
|
|
1470
1502
|
|
|
1471
1503
|
```ts
|
|
1472
|
-
import {
|
|
1504
|
+
import {
|
|
1505
|
+
HttpMiddleware,
|
|
1506
|
+
HttpRouter,
|
|
1507
|
+
HttpServer,
|
|
1508
|
+
HttpServerResponse
|
|
1509
|
+
} from "@effect/platform"
|
|
1473
1510
|
import { Effect } from "effect"
|
|
1474
1511
|
import { listen } from "./listen.js"
|
|
1475
1512
|
|
|
1476
1513
|
// Middleware constructor that logs the name of the middleware
|
|
1477
1514
|
const withMiddleware = (name: string) =>
|
|
1478
|
-
|
|
1515
|
+
HttpMiddleware.make((app) =>
|
|
1479
1516
|
Effect.gen(function* () {
|
|
1480
1517
|
console.log(name) // Log the middleware name when the route is accessed
|
|
1481
1518
|
return yield* app // Continue with the original application flow
|
|
1482
1519
|
})
|
|
1483
1520
|
)
|
|
1484
1521
|
|
|
1485
|
-
const router =
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
)
|
|
1490
|
-
HttpServer.router.get("/b", HttpServer.response.text("b")),
|
|
1491
|
-
HttpServer.router.use(withMiddleware("M2")),
|
|
1492
|
-
HttpServer.router.get("/", HttpServer.response.text("root"))
|
|
1522
|
+
const router = HttpRouter.empty.pipe(
|
|
1523
|
+
HttpRouter.get("/a", HttpServerResponse.text("a").pipe(withMiddleware("M1"))),
|
|
1524
|
+
HttpRouter.get("/b", HttpServerResponse.text("b")),
|
|
1525
|
+
HttpRouter.use(withMiddleware("M2")),
|
|
1526
|
+
HttpRouter.get("/", HttpServerResponse.text("root"))
|
|
1493
1527
|
)
|
|
1494
1528
|
|
|
1495
|
-
const app = router.pipe(HttpServer.
|
|
1529
|
+
const app = router.pipe(HttpServer.serve(withMiddleware("M3")))
|
|
1496
1530
|
|
|
1497
1531
|
listen(app, 3000)
|
|
1498
1532
|
```
|
|
@@ -1522,13 +1556,18 @@ Middleware functions are simply functions that transform a `Default` app into an
|
|
|
1522
1556
|
**Example**
|
|
1523
1557
|
|
|
1524
1558
|
```ts
|
|
1525
|
-
import {
|
|
1559
|
+
import {
|
|
1560
|
+
HttpMiddleware,
|
|
1561
|
+
HttpRouter,
|
|
1562
|
+
HttpServer,
|
|
1563
|
+
HttpServerResponse
|
|
1564
|
+
} from "@effect/platform"
|
|
1526
1565
|
import { Effect, flow } from "effect"
|
|
1527
1566
|
import { listen } from "./listen.js"
|
|
1528
1567
|
|
|
1529
1568
|
// Middleware constructor that logs the middleware's name when a route is accessed
|
|
1530
1569
|
const withMiddleware = (name: string) =>
|
|
1531
|
-
|
|
1570
|
+
HttpMiddleware.make((app) =>
|
|
1532
1571
|
Effect.gen(function* () {
|
|
1533
1572
|
console.log(name) // Log the middleware name
|
|
1534
1573
|
return yield* app // Continue with the original application flow
|
|
@@ -1536,22 +1575,22 @@ const withMiddleware = (name: string) =>
|
|
|
1536
1575
|
)
|
|
1537
1576
|
|
|
1538
1577
|
// Setup routes and apply multiple middlewares using flow for function composition
|
|
1539
|
-
const router =
|
|
1540
|
-
|
|
1578
|
+
const router = HttpRouter.empty.pipe(
|
|
1579
|
+
HttpRouter.get(
|
|
1541
1580
|
"/a",
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1581
|
+
HttpServerResponse.text("a").pipe(
|
|
1582
|
+
flow(withMiddleware("M1"), withMiddleware("M2"))
|
|
1583
|
+
)
|
|
1545
1584
|
),
|
|
1546
|
-
|
|
1585
|
+
HttpRouter.get("/b", HttpServerResponse.text("b")),
|
|
1547
1586
|
// Apply combined middlewares to the entire router
|
|
1548
|
-
|
|
1549
|
-
|
|
1587
|
+
HttpRouter.use(flow(withMiddleware("M3"), withMiddleware("M4"))),
|
|
1588
|
+
HttpRouter.get("/", HttpServerResponse.text("root"))
|
|
1550
1589
|
)
|
|
1551
1590
|
|
|
1552
1591
|
// Apply combined middlewares at the server level
|
|
1553
1592
|
const app = router.pipe(
|
|
1554
|
-
HttpServer.
|
|
1593
|
+
HttpServer.serve(flow(withMiddleware("M5"), withMiddleware("M6")))
|
|
1555
1594
|
)
|
|
1556
1595
|
|
|
1557
1596
|
listen(app, 3000)
|
|
@@ -1586,18 +1625,23 @@ curl -i http://localhost:3000/
|
|
|
1586
1625
|
|
|
1587
1626
|
### logger
|
|
1588
1627
|
|
|
1589
|
-
The `
|
|
1628
|
+
The `HttpMiddleware.logger` middleware enables logging for your entire application, providing insights into each request and response. Here’s how to set it up:
|
|
1590
1629
|
|
|
1591
1630
|
```ts
|
|
1592
|
-
import {
|
|
1631
|
+
import {
|
|
1632
|
+
HttpMiddleware,
|
|
1633
|
+
HttpRouter,
|
|
1634
|
+
HttpServer,
|
|
1635
|
+
HttpServerResponse
|
|
1636
|
+
} from "@effect/platform"
|
|
1593
1637
|
import { listen } from "./listen.js"
|
|
1594
1638
|
|
|
1595
|
-
const router =
|
|
1596
|
-
|
|
1639
|
+
const router = HttpRouter.empty.pipe(
|
|
1640
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World"))
|
|
1597
1641
|
)
|
|
1598
1642
|
|
|
1599
1643
|
// Apply the logger middleware globally
|
|
1600
|
-
const app = router.pipe(HttpServer.
|
|
1644
|
+
const app = router.pipe(HttpServer.serve(HttpMiddleware.logger))
|
|
1601
1645
|
|
|
1602
1646
|
listen(app, 3000)
|
|
1603
1647
|
/*
|
|
@@ -1610,25 +1654,28 @@ timestamp=... level=INFO fiber=#20 cause="RouteNotFound: GET /favicon.ico not fo
|
|
|
1610
1654
|
*/
|
|
1611
1655
|
```
|
|
1612
1656
|
|
|
1613
|
-
To disable the logger for specific routes, you can use `
|
|
1657
|
+
To disable the logger for specific routes, you can use `HttpMiddleware.withLoggerDisabled`:
|
|
1614
1658
|
|
|
1615
1659
|
```ts
|
|
1616
|
-
import {
|
|
1660
|
+
import {
|
|
1661
|
+
HttpMiddleware,
|
|
1662
|
+
HttpRouter,
|
|
1663
|
+
HttpServer,
|
|
1664
|
+
HttpServerResponse
|
|
1665
|
+
} from "@effect/platform"
|
|
1617
1666
|
import { listen } from "./listen.js"
|
|
1618
1667
|
|
|
1619
1668
|
// Create the router with routes that will and will not have logging
|
|
1620
|
-
const router =
|
|
1621
|
-
|
|
1622
|
-
|
|
1669
|
+
const router = HttpRouter.empty.pipe(
|
|
1670
|
+
HttpRouter.get("/", HttpServerResponse.text("Hello World")),
|
|
1671
|
+
HttpRouter.get(
|
|
1623
1672
|
"/no-logger",
|
|
1624
|
-
|
|
1625
|
-
.text("no-logger")
|
|
1626
|
-
.pipe(HttpServer.middleware.withLoggerDisabled)
|
|
1673
|
+
HttpServerResponse.text("no-logger").pipe(HttpMiddleware.withLoggerDisabled)
|
|
1627
1674
|
)
|
|
1628
1675
|
)
|
|
1629
1676
|
|
|
1630
1677
|
// Apply the logger middleware globally
|
|
1631
|
-
const app = router.pipe(HttpServer.
|
|
1678
|
+
const app = router.pipe(HttpServer.serve(HttpMiddleware.logger))
|
|
1632
1679
|
|
|
1633
1680
|
listen(app, 3000)
|
|
1634
1681
|
/*
|
|
@@ -1642,27 +1689,31 @@ timestamp=2024-05-19T09:53:29.877Z level=INFO fiber=#0 message="Listening on htt
|
|
|
1642
1689
|
This middleware handles `X-Forwarded-*` headers, useful when your app is behind a reverse proxy or load balancer and you need to retrieve the original client's IP and host information.
|
|
1643
1690
|
|
|
1644
1691
|
```ts
|
|
1645
|
-
import {
|
|
1692
|
+
import {
|
|
1693
|
+
HttpMiddleware,
|
|
1694
|
+
HttpRouter,
|
|
1695
|
+
HttpServer,
|
|
1696
|
+
HttpServerRequest,
|
|
1697
|
+
HttpServerResponse
|
|
1698
|
+
} from "@effect/platform"
|
|
1646
1699
|
import { Effect } from "effect"
|
|
1647
1700
|
import { listen } from "./listen.js"
|
|
1648
1701
|
|
|
1649
1702
|
// Create a router and a route that logs request headers and remote address
|
|
1650
|
-
const router =
|
|
1651
|
-
|
|
1703
|
+
const router = HttpRouter.empty.pipe(
|
|
1704
|
+
HttpRouter.get(
|
|
1652
1705
|
"/",
|
|
1653
1706
|
Effect.gen(function* () {
|
|
1654
|
-
const req = yield*
|
|
1707
|
+
const req = yield* HttpServerRequest.HttpServerRequest
|
|
1655
1708
|
console.log(req.headers)
|
|
1656
1709
|
console.log(req.remoteAddress)
|
|
1657
|
-
return yield*
|
|
1710
|
+
return yield* HttpServerResponse.text("Hello World")
|
|
1658
1711
|
})
|
|
1659
1712
|
)
|
|
1660
1713
|
)
|
|
1661
1714
|
|
|
1662
1715
|
// Set up the server with xForwardedHeaders middleware
|
|
1663
|
-
const app = router.pipe(
|
|
1664
|
-
HttpServer.server.serve(HttpServer.middleware.xForwardedHeaders)
|
|
1665
|
-
)
|
|
1716
|
+
const app = router.pipe(HttpServer.serve(HttpMiddleware.xForwardedHeaders))
|
|
1666
1717
|
|
|
1667
1718
|
listen(app, 3000)
|
|
1668
1719
|
/*
|
|
@@ -1686,31 +1737,31 @@ timestamp=... level=INFO fiber=#0 message="Listening on http://0.0.0.0:3000"
|
|
|
1686
1737
|
Below is an example illustrating how to catch and manage errors that occur during the execution of route handlers:
|
|
1687
1738
|
|
|
1688
1739
|
```ts
|
|
1689
|
-
import { HttpServer } from "@effect/platform"
|
|
1740
|
+
import { HttpRouter, HttpServer, HttpServerResponse } from "@effect/platform"
|
|
1690
1741
|
import { Effect } from "effect"
|
|
1691
1742
|
import { listen } from "./listen.js"
|
|
1692
1743
|
|
|
1693
1744
|
// Define routes that might throw errors or fail
|
|
1694
|
-
const router =
|
|
1695
|
-
|
|
1745
|
+
const router = HttpRouter.empty.pipe(
|
|
1746
|
+
HttpRouter.get(
|
|
1696
1747
|
"/throw",
|
|
1697
1748
|
Effect.sync(() => {
|
|
1698
1749
|
throw new Error("BROKEN") // This will intentionally throw an error
|
|
1699
1750
|
})
|
|
1700
1751
|
),
|
|
1701
|
-
|
|
1752
|
+
HttpRouter.get("/fail", Effect.fail("Uh oh!")) // This will intentionally fail
|
|
1702
1753
|
)
|
|
1703
1754
|
|
|
1704
1755
|
// Configure the application to handle different types of errors
|
|
1705
1756
|
const app = router.pipe(
|
|
1706
1757
|
Effect.catchTags({
|
|
1707
1758
|
RouteNotFound: () =>
|
|
1708
|
-
|
|
1759
|
+
HttpServerResponse.text("Route Not Found", { status: 404 })
|
|
1709
1760
|
}),
|
|
1710
1761
|
Effect.catchAllCause((cause) =>
|
|
1711
|
-
|
|
1762
|
+
HttpServerResponse.text(cause.toString(), { status: 500 })
|
|
1712
1763
|
),
|
|
1713
|
-
HttpServer.
|
|
1764
|
+
HttpServer.serve()
|
|
1714
1765
|
)
|
|
1715
1766
|
|
|
1716
1767
|
listen(app, 3000)
|
|
@@ -1738,30 +1789,35 @@ Validation is a critical aspect of handling HTTP requests to ensure that the dat
|
|
|
1738
1789
|
Headers often contain important information needed by your application, such as content types, authentication tokens, or session data. Validating these headers ensures that your application can trust and correctly process the information it receives.
|
|
1739
1790
|
|
|
1740
1791
|
```ts
|
|
1741
|
-
import {
|
|
1792
|
+
import {
|
|
1793
|
+
HttpRouter,
|
|
1794
|
+
HttpServer,
|
|
1795
|
+
HttpServerRequest,
|
|
1796
|
+
HttpServerResponse
|
|
1797
|
+
} from "@effect/platform"
|
|
1742
1798
|
import { Schema } from "@effect/schema"
|
|
1743
1799
|
import { Effect } from "effect"
|
|
1744
1800
|
import { listen } from "./listen.js"
|
|
1745
1801
|
|
|
1746
|
-
const router =
|
|
1747
|
-
|
|
1802
|
+
const router = HttpRouter.empty.pipe(
|
|
1803
|
+
HttpRouter.get(
|
|
1748
1804
|
"/",
|
|
1749
1805
|
Effect.gen(function* () {
|
|
1750
1806
|
// Define the schema for expected headers and validate them
|
|
1751
|
-
const headers = yield*
|
|
1807
|
+
const headers = yield* HttpServerRequest.schemaHeaders(
|
|
1752
1808
|
Schema.Struct({ test: Schema.String })
|
|
1753
1809
|
)
|
|
1754
|
-
return yield*
|
|
1810
|
+
return yield* HttpServerResponse.text("header: " + headers.test)
|
|
1755
1811
|
}).pipe(
|
|
1756
1812
|
// Handle parsing errors
|
|
1757
1813
|
Effect.catchTag("ParseError", (e) =>
|
|
1758
|
-
|
|
1814
|
+
HttpServerResponse.text(`Invalid header: ${e.message}`)
|
|
1759
1815
|
)
|
|
1760
1816
|
)
|
|
1761
1817
|
)
|
|
1762
1818
|
)
|
|
1763
1819
|
|
|
1764
|
-
const app = router.pipe(HttpServer.
|
|
1820
|
+
const app = router.pipe(HttpServer.serve())
|
|
1765
1821
|
|
|
1766
1822
|
listen(app, 3000)
|
|
1767
1823
|
```
|
|
@@ -1783,28 +1839,34 @@ Cookies are commonly used to maintain session state or user preferences. Validat
|
|
|
1783
1839
|
Here’s how you can validate cookies received in HTTP requests:
|
|
1784
1840
|
|
|
1785
1841
|
```ts
|
|
1786
|
-
import {
|
|
1842
|
+
import {
|
|
1843
|
+
Cookies,
|
|
1844
|
+
HttpRouter,
|
|
1845
|
+
HttpServer,
|
|
1846
|
+
HttpServerRequest,
|
|
1847
|
+
HttpServerResponse
|
|
1848
|
+
} from "@effect/platform"
|
|
1787
1849
|
import { Schema } from "@effect/schema"
|
|
1788
1850
|
import { Effect } from "effect"
|
|
1789
1851
|
import { listen } from "./listen.js"
|
|
1790
1852
|
|
|
1791
|
-
const router =
|
|
1792
|
-
|
|
1853
|
+
const router = HttpRouter.empty.pipe(
|
|
1854
|
+
HttpRouter.get(
|
|
1793
1855
|
"/",
|
|
1794
1856
|
Effect.gen(function* () {
|
|
1795
|
-
const cookies = yield*
|
|
1857
|
+
const cookies = yield* HttpServerRequest.schemaCookies(
|
|
1796
1858
|
Schema.Struct({ test: Schema.String })
|
|
1797
1859
|
)
|
|
1798
|
-
return yield*
|
|
1860
|
+
return yield* HttpServerResponse.text("cookie: " + cookies.test)
|
|
1799
1861
|
}).pipe(
|
|
1800
1862
|
Effect.catchTag("ParseError", (e) =>
|
|
1801
|
-
|
|
1863
|
+
HttpServerResponse.text(`Invalid cookie: ${e.message}`)
|
|
1802
1864
|
)
|
|
1803
1865
|
)
|
|
1804
1866
|
)
|
|
1805
1867
|
)
|
|
1806
1868
|
|
|
1807
|
-
const app = router.pipe(HttpServer.
|
|
1869
|
+
const app = router.pipe(HttpServer.serve())
|
|
1808
1870
|
|
|
1809
1871
|
listen(app, 3000)
|
|
1810
1872
|
```
|
|
@@ -1828,24 +1890,29 @@ The native request object depends on the platform you are using, and it is not d
|
|
|
1828
1890
|
Here is an example using Node.js:
|
|
1829
1891
|
|
|
1830
1892
|
```ts
|
|
1831
|
-
import {
|
|
1832
|
-
|
|
1893
|
+
import {
|
|
1894
|
+
HttpRouter,
|
|
1895
|
+
HttpServer,
|
|
1896
|
+
HttpServerRequest,
|
|
1897
|
+
HttpServerResponse
|
|
1898
|
+
} from "@effect/platform"
|
|
1899
|
+
import { NodeHttpServer, NodeHttpServerRequest } from "@effect/platform-node"
|
|
1833
1900
|
import { Effect } from "effect"
|
|
1834
1901
|
import { listen } from "./listen.js"
|
|
1835
1902
|
|
|
1836
|
-
const router =
|
|
1837
|
-
|
|
1903
|
+
const router = HttpRouter.empty.pipe(
|
|
1904
|
+
HttpRouter.get(
|
|
1838
1905
|
"/",
|
|
1839
1906
|
Effect.gen(function* () {
|
|
1840
|
-
const req = yield*
|
|
1841
|
-
const raw =
|
|
1907
|
+
const req = yield* HttpServerRequest.HttpServerRequest
|
|
1908
|
+
const raw = NodeHttpServerRequest.toIncomingMessage(req)
|
|
1842
1909
|
console.log(raw)
|
|
1843
|
-
return
|
|
1910
|
+
return HttpServerResponse.empty()
|
|
1844
1911
|
})
|
|
1845
1912
|
)
|
|
1846
1913
|
)
|
|
1847
1914
|
|
|
1848
|
-
listen(HttpServer.
|
|
1915
|
+
listen(HttpServer.serve(router), 3000)
|
|
1849
1916
|
```
|
|
1850
1917
|
|
|
1851
1918
|
## Conversions
|
|
@@ -1855,17 +1922,23 @@ listen(HttpServer.server.serve(router), 3000)
|
|
|
1855
1922
|
The `toWebHandler` function converts a `Default` (i.e. a type of `HttpApp` that specifically produces a `ServerResponse` as its output) into a web handler that can process `Request` objects and return `Response` objects.
|
|
1856
1923
|
|
|
1857
1924
|
```ts
|
|
1858
|
-
import
|
|
1925
|
+
import {
|
|
1926
|
+
HttpApp,
|
|
1927
|
+
HttpRouter,
|
|
1928
|
+
HttpServer,
|
|
1929
|
+
HttpServerRequest,
|
|
1930
|
+
HttpServerResponse
|
|
1931
|
+
} from "@effect/platform"
|
|
1859
1932
|
|
|
1860
1933
|
// Define the router with some routes
|
|
1861
|
-
const router =
|
|
1862
|
-
|
|
1863
|
-
|
|
1934
|
+
const router = HttpRouter.empty.pipe(
|
|
1935
|
+
HttpRouter.get("/", HttpServerResponse.text("content 1")),
|
|
1936
|
+
HttpRouter.get("/foo", HttpServerResponse.text("content 2"))
|
|
1864
1937
|
)
|
|
1865
1938
|
|
|
1866
1939
|
// Convert the router to a web handler
|
|
1867
1940
|
// const handler: (request: Request) => Promise<Response>
|
|
1868
|
-
const handler =
|
|
1941
|
+
const handler = HttpApp.toWebHandler(router)
|
|
1869
1942
|
|
|
1870
1943
|
// Test the handler with a request
|
|
1871
1944
|
const response = await handler(new Request("http://localhost:3000/foo"))
|