Skip to content

Commit 65bff45

Browse files
authored
add basic apis for converting to web Request/Response (#5896)
1 parent 59760c1 commit 65bff45

File tree

3 files changed

+64
-15
lines changed

3 files changed

+64
-15
lines changed

.changeset/blue-onions-stop.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@effect/platform": patch
3+
---
4+
5+
add basic apis for converting to web Request/Response

packages/platform/src/HttpServerRequest.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@ import type { Channel } from "effect/Channel"
55
import type { Chunk } from "effect/Chunk"
66
import type * as Context from "effect/Context"
77
import type * as Effect from "effect/Effect"
8-
import type { Option } from "effect/Option"
8+
import * as Option from "effect/Option"
99
import type * as ParseResult from "effect/ParseResult"
1010
import type { ReadonlyRecord } from "effect/Record"
1111
import type * as Schema from "effect/Schema"
1212
import type { ParseOptions } from "effect/SchemaAST"
1313
import type * as Scope from "effect/Scope"
14-
import type * as Stream from "effect/Stream"
14+
import * as Stream from "effect/Stream"
1515
import type * as FileSystem from "./FileSystem.js"
1616
import type * as Headers from "./Headers.js"
1717
import type * as IncomingMessage from "./HttpIncomingMessage.js"
18-
import type { HttpMethod } from "./HttpMethod.js"
18+
import { hasBody, type HttpMethod } from "./HttpMethod.js"
1919
import type * as Error from "./HttpServerError.js"
2020
import * as internal from "./internal/httpServerRequest.js"
2121
import type * as Multipart from "./Multipart.js"
@@ -235,4 +235,21 @@ export const fromWeb: (request: Request) => HttpServerRequest = internal.fromWeb
235235
* @since 1.0.0
236236
* @category conversions
237237
*/
238-
export const toURL: (self: HttpServerRequest) => Option<URL> = internal.toURL
238+
export const toWeb = (self: HttpServerRequest): Request | undefined => {
239+
if (self.source instanceof Request) {
240+
return self.source
241+
}
242+
const ourl = toURL(self)
243+
if (Option.isNone(ourl)) return undefined
244+
return new Request(ourl.value, {
245+
method: self.method,
246+
body: hasBody(self.method) ? Stream.toReadableStream(self.stream) : undefined,
247+
headers: self.headers
248+
})
249+
}
250+
251+
/**
252+
* @since 1.0.0
253+
* @category conversions
254+
*/
255+
export const toURL: (self: HttpServerRequest) => Option.Option<URL> = internal.toURL

packages/platform/src/HttpServerResponse.ts

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ import type { Inspectable } from "effect/Inspectable"
66
import type * as Runtime from "effect/Runtime"
77
import type * as Schema from "effect/Schema"
88
import type { ParseOptions } from "effect/SchemaAST"
9-
import type * as Stream from "effect/Stream"
10-
import type { Cookie, Cookies, CookiesError } from "./Cookies.js"
9+
import * as Stream from "effect/Stream"
10+
import type { Cookie, CookiesError } from "./Cookies.js"
11+
import * as Cookies from "./Cookies.js"
1112
import type * as PlatformError from "./Error.js"
1213
import type * as FileSystem from "./FileSystem.js"
1314
import type * as Headers from "./Headers.js"
14-
import type * as Body from "./HttpBody.js"
15+
import * as Body from "./HttpBody.js"
1516
import type * as Platform from "./HttpPlatform.js"
1617
import type { Respondable } from "./HttpServerRespondable.js"
1718
import * as internal from "./internal/httpServerResponse.js"
@@ -39,7 +40,7 @@ export interface HttpServerResponse extends Effect.Effect<HttpServerResponse>, I
3940
readonly status: number
4041
readonly statusText?: string | undefined
4142
readonly headers: Headers.Headers
42-
readonly cookies: Cookies
43+
readonly cookies: Cookies.Cookies
4344
readonly body: Body.HttpBody
4445
}
4546

@@ -51,7 +52,7 @@ export interface Options {
5152
readonly status?: number | undefined
5253
readonly statusText?: string | undefined
5354
readonly headers?: Headers.Input | undefined
54-
readonly cookies?: Cookies | undefined
55+
readonly cookies?: Cookies.Cookies | undefined
5556
readonly contentType?: string | undefined
5657
readonly contentLength?: number | undefined
5758
}
@@ -246,8 +247,8 @@ export const expireCookie: {
246247
* @category combinators
247248
*/
248249
export const replaceCookies: {
249-
(cookies: Cookies): (self: HttpServerResponse) => HttpServerResponse
250-
(self: HttpServerResponse, cookies: Cookies): HttpServerResponse
250+
(cookies: Cookies.Cookies): (self: HttpServerResponse) => HttpServerResponse
251+
(self: HttpServerResponse, cookies: Cookies.Cookies): HttpServerResponse
251252
} = internal.replaceCookies
252253

253254
/**
@@ -299,17 +300,17 @@ export const unsafeSetCookie: {
299300
* @category combinators
300301
*/
301302
export const updateCookies: {
302-
(f: (cookies: Cookies) => Cookies): (self: HttpServerResponse) => HttpServerResponse
303-
(self: HttpServerResponse, f: (cookies: Cookies) => Cookies): HttpServerResponse
303+
(f: (cookies: Cookies.Cookies) => Cookies.Cookies): (self: HttpServerResponse) => HttpServerResponse
304+
(self: HttpServerResponse, f: (cookies: Cookies.Cookies) => Cookies.Cookies): HttpServerResponse
304305
} = internal.updateCookies
305306

306307
/**
307308
* @since 1.0.0
308309
* @category combinators
309310
*/
310311
export const mergeCookies: {
311-
(cookies: Cookies): (self: HttpServerResponse) => HttpServerResponse
312-
(self: HttpServerResponse, cookies: Cookies): HttpServerResponse
312+
(cookies: Cookies.Cookies): (self: HttpServerResponse) => HttpServerResponse
313+
(self: HttpServerResponse, cookies: Cookies.Cookies): HttpServerResponse
313314
} = internal.mergeCookies
314315

315316
/**
@@ -393,3 +394,29 @@ export const toWeb: (
393394
readonly runtime?: Runtime.Runtime<never> | undefined
394395
}
395396
) => Response = internal.toWeb
397+
398+
/**
399+
* @since 1.0.0
400+
* @category conversions
401+
*/
402+
export const fromWeb = (response: Response): HttpServerResponse => {
403+
const headers = response.headers
404+
const setCookieHeaders = headers.getSetCookie()
405+
headers.delete("set-cookie")
406+
let self = empty({
407+
status: response.status,
408+
statusText: response.statusText,
409+
headers: headers as any,
410+
cookies: Cookies.fromSetCookie(setCookieHeaders)
411+
})
412+
if (response.body) {
413+
self = setBody(
414+
self,
415+
Body.stream(Stream.fromReadableStream({
416+
evaluate: () => response.body!,
417+
onError: (e) => e
418+
}))
419+
)
420+
}
421+
return self
422+
}

0 commit comments

Comments
 (0)