Skip to content

Commit

Permalink
add HttpServerResponse.redirect api (#4152)
Browse files Browse the repository at this point in the history
  • Loading branch information
tim-smart authored Dec 16, 2024
1 parent 1a6b52d commit 909181a
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 24 deletions.
5 changes: 5 additions & 0 deletions .changeset/gentle-ears-pay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": patch
---

accept Headers.Input in HttpServerResponse constructors
5 changes: 5 additions & 0 deletions .changeset/gold-seals-suffer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@effect/platform": patch
---

add HttpServerResponse.redirect api
9 changes: 8 additions & 1 deletion packages/platform/src/HttpServerResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export interface HttpServerResponse extends Effect.Effect<HttpServerResponse>, I
export interface Options {
readonly status?: number | undefined
readonly statusText?: string | undefined
readonly headers?: Headers.Headers | undefined
readonly headers?: Headers.Input | undefined
readonly cookies?: Cookies | undefined
readonly contentType?: string | undefined
readonly contentLength?: number | undefined
Expand Down Expand Up @@ -84,6 +84,13 @@ export const isServerResponse: (u: unknown) => u is HttpServerResponse = interna
*/
export const empty: (options?: Options.WithContent | undefined) => HttpServerResponse = internal.empty

/**
* @since 1.0.0
* @category constructors
*/
export const redirect: (location: string, options?: Options.WithContentType | undefined) => HttpServerResponse =
internal.redirect

/**
* @since 1.0.0
* @category constructors
Expand Down
8 changes: 6 additions & 2 deletions packages/platform/src/internal/httpPlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ export const make = (impl: {
Effect.map(({ etag, info }) => {
const start = Number(options?.offset ?? 0)
const end = options?.bytesToRead !== undefined ? start + Number(options.bytesToRead) : undefined
const headers = Headers.set(options?.headers ?? Headers.empty, "etag", Etag.toString(etag))
const headers = Headers.set(
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
"etag",
Etag.toString(etag)
)
if (info.mtime._tag === "Some") {
;(headers as any)["last-modified"] = info.mtime.value.toUTCString()
}
Expand All @@ -69,7 +73,7 @@ export const make = (impl: {
fileWebResponse(file, options) {
return Effect.map(etagGen.fromFileWeb(file), (etag) => {
const headers = Headers.merge(
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
Headers.unsafeFromRecord({
etag: Etag.toString(etag),
"last-modified": new Date(file.lastModified).toUTCString()
Expand Down
71 changes: 50 additions & 21 deletions packages/platform/src/internal/httpServerResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,36 +91,60 @@ export const empty = (options?: ServerResponse.Options.WithContent | undefined):
new ServerResponseImpl(
options?.status ?? 204,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
internalBody.empty
)

/** @internal */
export const redirect = (
location: string,
options?: ServerResponse.Options.WithContentType | undefined
): ServerResponse.HttpServerResponse => {
const headers = Headers.unsafeFromRecord({ location })
return new ServerResponseImpl(
options?.status ?? 301,
options?.statusText,
options?.headers ?
Headers.merge(
headers,
Headers.fromInput(options.headers)
) :
headers,
options?.cookies ?? Cookies.empty,
internalBody.empty
)
}

/** @internal */
export const uint8Array = (
body: Uint8Array,
options?: ServerResponse.Options.WithContentType
): ServerResponse.HttpServerResponse =>
new ServerResponseImpl(
): ServerResponse.HttpServerResponse => {
const headers = options?.headers ? Headers.fromInput(options.headers) : Headers.empty
return new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
headers,
options?.cookies ?? Cookies.empty,
internalBody.uint8Array(body, getContentType(options))
internalBody.uint8Array(body, getContentType(options, headers))
)
}

/** @internal */
export const text = (
body: string,
options?: ServerResponse.Options.WithContentType
): ServerResponse.HttpServerResponse =>
new ServerResponseImpl(
): ServerResponse.HttpServerResponse => {
const headers = options?.headers ? Headers.fromInput(options.headers) : Headers.empty
return new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
headers,
options?.cookies ?? Cookies.empty,
internalBody.text(body, getContentType(options))
internalBody.text(body, getContentType(options, headers))
)
}

/** @internal */
export const html: {
Expand Down Expand Up @@ -177,7 +201,7 @@ export const json = (
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
body
))
Expand All @@ -190,7 +214,7 @@ export const unsafeJson = (
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
internalBody.unsafeJson(body)
)
Expand All @@ -209,7 +233,7 @@ export const schemaJson = <A, I, R>(
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
body
))
Expand Down Expand Up @@ -245,7 +269,7 @@ export const urlParams = (
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
internalBody.text(UrlParams.toString(UrlParams.fromInput(body)), "application/x-www-form-urlencoded")
)
Expand All @@ -255,7 +279,7 @@ export const raw = (body: unknown, options?: ServerResponse.Options | undefined)
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
internalBody.raw(body)
)
Expand All @@ -268,7 +292,7 @@ export const formData = (
new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
options?.headers ? Headers.fromInput(options.headers) : Headers.empty,
options?.cookies ?? Cookies.empty,
internalBody.formData(body)
)
Expand All @@ -277,21 +301,26 @@ export const formData = (
export const stream = <E>(
body: Stream.Stream<Uint8Array, E>,
options?: ServerResponse.Options | undefined
): ServerResponse.HttpServerResponse =>
new ServerResponseImpl(
): ServerResponse.HttpServerResponse => {
const headers = options?.headers ? Headers.fromInput(options.headers) : Headers.empty
return new ServerResponseImpl(
options?.status ?? 200,
options?.statusText,
options?.headers ?? Headers.empty,
headers,
options?.cookies ?? Cookies.empty,
internalBody.stream(body, getContentType(options), options?.contentLength)
internalBody.stream(body, getContentType(options, headers), options?.contentLength)
)
}

/** @internal */
export const getContentType = (options?: ServerResponse.Options | undefined): string | undefined => {
export const getContentType = (
options: ServerResponse.Options | undefined,
headers: Headers.Headers
): string | undefined => {
if (options?.contentType) {
return options.contentType
} else if (options?.headers) {
return options.headers["content-type"]
return headers["content-type"]
} else {
return
}
Expand Down

0 comments on commit 909181a

Please sign in to comment.