mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
1 Commits
next-auth@
...
@next-auth
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5dd901b03 |
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "next-auth",
|
"name": "next-auth",
|
||||||
"version": "4.18.6",
|
"version": "4.18.5",
|
||||||
"description": "Authentication for Next.js",
|
"description": "Authentication for Next.js",
|
||||||
"homepage": "https://next-auth.js.org",
|
"homepage": "https://next-auth.js.org",
|
||||||
"repository": "https://github.com/nextauthjs/next-auth.git",
|
"repository": "https://github.com/nextauthjs/next-auth.git",
|
||||||
|
|||||||
@@ -6,17 +6,7 @@ import { NextResponse, NextRequest } from "next/server"
|
|||||||
|
|
||||||
import { getToken } from "../jwt"
|
import { getToken } from "../jwt"
|
||||||
import parseUrl from "../utils/parse-url"
|
import parseUrl from "../utils/parse-url"
|
||||||
|
import { detectHost } from "../utils/web"
|
||||||
// // TODO: Remove
|
|
||||||
/** Extract the host from the environment */
|
|
||||||
export function detectHost(
|
|
||||||
trusted: boolean,
|
|
||||||
forwardedValue: string | null,
|
|
||||||
defaultValue: string | false
|
|
||||||
): string | undefined {
|
|
||||||
if (trusted && forwardedValue) return forwardedValue
|
|
||||||
return defaultValue || undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
type AuthorizedCallback = (params: {
|
type AuthorizedCallback = (params: {
|
||||||
token: JWT | null
|
token: JWT | null
|
||||||
|
|||||||
@@ -142,14 +142,8 @@ function getSetCookies(cookiesString: string) {
|
|||||||
|
|
||||||
export function setHeaders(headers: Headers, res: ServerResponse) {
|
export function setHeaders(headers: Headers, res: ServerResponse) {
|
||||||
for (const [key, val] of headers.entries()) {
|
for (const [key, val] of headers.entries()) {
|
||||||
let value: string | string[] = val
|
|
||||||
// See: https://github.com/whatwg/fetch/issues/973
|
// See: https://github.com/whatwg/fetch/issues/973
|
||||||
if (key === "set-cookie") {
|
const value = key === "set-cookie" ? getSetCookies(val) : val
|
||||||
const cookies = getSetCookies(value)
|
|
||||||
let original = res.getHeader("set-cookie") as string[] | string
|
|
||||||
original = Array.isArray(original) ? original : [original]
|
|
||||||
value = original.concat(cookies).filter(Boolean)
|
|
||||||
}
|
|
||||||
res.setHeader(key, value)
|
res.setHeader(key, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export async function toInternalRequest(
|
|||||||
req: Request
|
req: Request
|
||||||
): Promise<RequestInternal | Error> {
|
): Promise<RequestInternal | Error> {
|
||||||
try {
|
try {
|
||||||
// TODO: url.toString() should not include action and providerId
|
// TODO: .toString() should not inclide action and providerId
|
||||||
// see init.ts
|
// see init.ts
|
||||||
const url = new URL(req.url.replace(/\/$/, ""))
|
const url = new URL(req.url.replace(/\/$/, ""))
|
||||||
const { pathname } = url
|
const { pathname } = url
|
||||||
@@ -69,6 +69,8 @@ export async function toInternalRequest(
|
|||||||
providerId = providerIdOrAction
|
providerId = providerIdOrAction
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cookieHeader = req.headers.get("cookie") ?? ""
|
||||||
|
|
||||||
return {
|
return {
|
||||||
url,
|
url,
|
||||||
action,
|
action,
|
||||||
@@ -76,7 +78,10 @@ export async function toInternalRequest(
|
|||||||
method: req.method ?? "GET",
|
method: req.method ?? "GET",
|
||||||
headers: Object.fromEntries(req.headers),
|
headers: Object.fromEntries(req.headers),
|
||||||
body: req.body ? await readJSONBody(req.body) : undefined,
|
body: req.body ? await readJSONBody(req.body) : undefined,
|
||||||
cookies: parseCookie(req.headers.get("cookie") ?? "") ?? {},
|
cookies:
|
||||||
|
parseCookie(
|
||||||
|
Array.isArray(cookieHeader) ? cookieHeader.join(";") : cookieHeader
|
||||||
|
) ?? {},
|
||||||
error: url.searchParams.get("error") ?? undefined,
|
error: url.searchParams.get("error") ?? undefined,
|
||||||
query: Object.fromEntries(url.searchParams),
|
query: Object.fromEntries(url.searchParams),
|
||||||
}
|
}
|
||||||
@@ -114,3 +119,17 @@ export function toResponse(res: ResponseInternal): Response {
|
|||||||
|
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove
|
||||||
|
/** Extract the host from the environment */
|
||||||
|
export function detectHost(
|
||||||
|
trusted: boolean,
|
||||||
|
forwardedValue: string | string[] | undefined | null,
|
||||||
|
defaultValue: string | false
|
||||||
|
): string | undefined {
|
||||||
|
if (trusted && forwardedValue) {
|
||||||
|
return Array.isArray(forwardedValue) ? forwardedValue[0] : forwardedValue
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultValue || undefined
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { mockReqRes, nextHandler } from "./utils"
|
import { nodeHandler } from "./utils"
|
||||||
|
|
||||||
it("Missing req.url throws in dev", async () => {
|
it("Missing req.url throws in dev", async () => {
|
||||||
await expect(nextHandler).rejects.toThrow(new Error("Missing url"))
|
await expect(nodeHandler).rejects.toThrow(new Error("Missing url"))
|
||||||
})
|
})
|
||||||
|
|
||||||
const configErrorMessage =
|
const configErrorMessage =
|
||||||
@@ -10,7 +10,7 @@ const configErrorMessage =
|
|||||||
it("Missing req.url returns config error in prod", async () => {
|
it("Missing req.url returns config error in prod", async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "production"
|
process.env.NODE_ENV = "production"
|
||||||
const { res, logger } = await nextHandler()
|
const { res, logger } = await nodeHandler()
|
||||||
|
|
||||||
expect(logger.error).toBeCalledTimes(1)
|
expect(logger.error).toBeCalledTimes(1)
|
||||||
const error = new Error("Missing url")
|
const error = new Error("Missing url")
|
||||||
@@ -26,7 +26,7 @@ it("Missing req.url returns config error in prod", async () => {
|
|||||||
it("Missing host throws in dev", async () => {
|
it("Missing host throws in dev", async () => {
|
||||||
await expect(
|
await expect(
|
||||||
async () =>
|
async () =>
|
||||||
await nextHandler({
|
await nodeHandler({
|
||||||
req: { query: { nextauth: ["session"] } },
|
req: { query: { nextauth: ["session"] } },
|
||||||
})
|
})
|
||||||
).rejects.toThrow(Error)
|
).rejects.toThrow(Error)
|
||||||
@@ -35,7 +35,7 @@ it("Missing host throws in dev", async () => {
|
|||||||
it("Missing host config error in prod", async () => {
|
it("Missing host config error in prod", async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "production"
|
process.env.NODE_ENV = "production"
|
||||||
const { res, logger } = await nextHandler({
|
const { res, logger } = await nodeHandler({
|
||||||
req: { query: { nextauth: ["session"] } },
|
req: { query: { nextauth: ["session"] } },
|
||||||
})
|
})
|
||||||
expect(res.status).toBeCalledWith(400)
|
expect(res.status).toBeCalledWith(400)
|
||||||
@@ -49,7 +49,7 @@ it("Missing host config error in prod", async () => {
|
|||||||
it("Defined host throws 400 in production if not trusted", async () => {
|
it("Defined host throws 400 in production if not trusted", async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "production"
|
process.env.NODE_ENV = "production"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: { headers: { host: "http://localhost" } },
|
req: { headers: { host: "http://localhost" } },
|
||||||
})
|
})
|
||||||
expect(res.status).toBeCalledWith(400)
|
expect(res.status).toBeCalledWith(400)
|
||||||
@@ -60,7 +60,7 @@ it("Defined host throws 400 in production if not trusted", async () => {
|
|||||||
it("Defined host throws 400 in production if trusted but invalid URL", async () => {
|
it("Defined host throws 400 in production if trusted but invalid URL", async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "production"
|
process.env.NODE_ENV = "production"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: { headers: { host: "localhost" } },
|
req: { headers: { host: "localhost" } },
|
||||||
options: { trustHost: true },
|
options: { trustHost: true },
|
||||||
})
|
})
|
||||||
@@ -72,7 +72,7 @@ it("Defined host throws 400 in production if trusted but invalid URL", async ()
|
|||||||
it("Defined host does not throw in production if trusted and valid URL", async () => {
|
it("Defined host does not throw in production if trusted and valid URL", async () => {
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "production"
|
process.env.NODE_ENV = "production"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: {
|
req: {
|
||||||
url: "/api/auth/session",
|
url: "/api/auth/session",
|
||||||
headers: { host: "http://localhost" },
|
headers: { host: "http://localhost" },
|
||||||
@@ -80,7 +80,6 @@ it("Defined host does not throw in production if trusted and valid URL", async (
|
|||||||
options: { trustHost: true },
|
options: { trustHost: true },
|
||||||
})
|
})
|
||||||
expect(res.status).toBeCalledWith(200)
|
expect(res.status).toBeCalledWith(200)
|
||||||
// @ts-expect-error
|
|
||||||
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
||||||
// @ts-expect-error
|
// @ts-expect-error
|
||||||
process.env.NODE_ENV = "test"
|
process.env.NODE_ENV = "test"
|
||||||
@@ -88,41 +87,37 @@ it("Defined host does not throw in production if trusted and valid URL", async (
|
|||||||
|
|
||||||
it("Use process.env.NEXTAUTH_URL for host if present", async () => {
|
it("Use process.env.NEXTAUTH_URL for host if present", async () => {
|
||||||
process.env.NEXTAUTH_URL = "http://localhost"
|
process.env.NEXTAUTH_URL = "http://localhost"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: { url: "/api/auth/session" },
|
req: { url: "/api/auth/session" },
|
||||||
})
|
})
|
||||||
expect(res.status).toBeCalledWith(200)
|
expect(res.status).toBeCalledWith(200)
|
||||||
// @ts-expect-error
|
|
||||||
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
expect(JSON.parse(res.send.mock.calls[0][0])).toEqual({})
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Redirects if necessary", async () => {
|
it("Redirects if necessary", async () => {
|
||||||
process.env.NEXTAUTH_URL = "http://localhost"
|
process.env.NEXTAUTH_URL = "http://localhost"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: {
|
req: {
|
||||||
method: "post",
|
method: "post",
|
||||||
url: "/api/auth/signin/github",
|
url: "/api/auth/signin/github",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
expect(res.status).toBeCalledWith(302)
|
expect(res.status).toBeCalledWith(302)
|
||||||
expect(res.getHeaders()).toEqual({
|
expect(res.setHeader).toBeCalledWith("set-cookie", [
|
||||||
location: "http://localhost/api/auth/signin?csrf=true",
|
expect.stringMatching(
|
||||||
"set-cookie": [
|
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
||||||
expect.stringMatching(
|
),
|
||||||
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
`next-auth.callback-url=${encodeURIComponent(
|
||||||
),
|
process.env.NEXTAUTH_URL
|
||||||
`next-auth.callback-url=${encodeURIComponent(
|
)}; Path=/; HttpOnly; SameSite=Lax`,
|
||||||
process.env.NEXTAUTH_URL
|
])
|
||||||
)}; Path=/; HttpOnly; SameSite=Lax`,
|
expect(res.setHeader).toBeCalledTimes(2)
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.send).toBeCalledWith("")
|
expect(res.send).toBeCalledWith("")
|
||||||
})
|
})
|
||||||
|
|
||||||
it("Returns redirect if `X-Auth-Return-Redirect` header is present", async () => {
|
it("Returns redirect if `X-Auth-Return-Redirect` header is present", async () => {
|
||||||
process.env.NEXTAUTH_URL = "http://localhost"
|
process.env.NEXTAUTH_URL = "http://localhost"
|
||||||
const { res } = await nextHandler({
|
const { res } = await nodeHandler({
|
||||||
req: {
|
req: {
|
||||||
method: "post",
|
method: "post",
|
||||||
url: "/api/auth/signin/github",
|
url: "/api/auth/signin/github",
|
||||||
@@ -131,48 +126,16 @@ it("Returns redirect if `X-Auth-Return-Redirect` header is present", async () =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(res.status).toBeCalledWith(200)
|
expect(res.status).toBeCalledWith(200)
|
||||||
|
expect(res.setHeader).toBeCalledWith("content-type", "application/json")
|
||||||
expect(res.getHeaders()).toEqual({
|
expect(res.setHeader).toBeCalledWith("set-cookie", [
|
||||||
"content-type": "application/json",
|
expect.stringMatching(
|
||||||
"set-cookie": [
|
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
||||||
expect.stringMatching(
|
),
|
||||||
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
`next-auth.callback-url=${encodeURIComponent(
|
||||||
),
|
process.env.NEXTAUTH_URL
|
||||||
`next-auth.callback-url=${encodeURIComponent(
|
)}; Path=/; HttpOnly; SameSite=Lax`,
|
||||||
process.env.NEXTAUTH_URL
|
])
|
||||||
)}; Path=/; HttpOnly; SameSite=Lax`,
|
expect(res.setHeader).toBeCalledTimes(2)
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.send).toBeCalledWith(
|
|
||||||
JSON.stringify({ url: "http://localhost/api/auth/signin?csrf=true" })
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it("Should preserve user's `set-cookie` headers", async () => {
|
|
||||||
const { req, res } = mockReqRes({
|
|
||||||
method: "post",
|
|
||||||
url: "/api/auth/signin/credentials",
|
|
||||||
headers: { host: "localhost", "X-Auth-Return-Redirect": "1" },
|
|
||||||
})
|
|
||||||
res.setHeader("set-cookie", ["foo=bar", "bar=baz"])
|
|
||||||
|
|
||||||
await nextHandler({ req, res })
|
|
||||||
|
|
||||||
expect(res.getHeaders()).toEqual({
|
|
||||||
"content-type": "application/json",
|
|
||||||
"set-cookie": [
|
|
||||||
"foo=bar",
|
|
||||||
"bar=baz",
|
|
||||||
expect.stringMatching(
|
|
||||||
/next-auth.csrf-token=.*; Path=\/; HttpOnly; SameSite=Lax/
|
|
||||||
),
|
|
||||||
`next-auth.callback-url=${encodeURIComponent(
|
|
||||||
"http://localhost"
|
|
||||||
)}; Path=/; HttpOnly; SameSite=Lax`,
|
|
||||||
],
|
|
||||||
})
|
|
||||||
|
|
||||||
expect(res.send).toBeCalledWith(
|
expect(res.send).toBeCalledWith(
|
||||||
JSON.stringify({ url: "http://localhost/api/auth/signin?csrf=true" })
|
JSON.stringify({ url: "http://localhost/api/auth/signin?csrf=true" })
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
import { createHash } from "node:crypto"
|
import { createHash } from "crypto"
|
||||||
import { IncomingMessage, ServerResponse } from "node:http"
|
|
||||||
import { Socket } from "node:net"
|
|
||||||
import type { AuthOptions, LoggerInstance } from "../src"
|
|
||||||
import type { Adapter } from "../src/adapters"
|
|
||||||
import { AuthHandler } from "../src/core"
|
import { AuthHandler } from "../src/core"
|
||||||
|
import type { LoggerInstance, AuthOptions } from "../src"
|
||||||
|
import type { Adapter } from "../src/adapters"
|
||||||
|
|
||||||
import NextAuth from "../src/next"
|
import NextAuth from "../src/next"
|
||||||
|
|
||||||
import type { NextApiRequest, NextApiResponse } from "next"
|
import type { NextApiRequest, NextApiResponse } from "next"
|
||||||
import { Stream } from "node:stream"
|
|
||||||
|
|
||||||
export function mockLogger(): Record<keyof LoggerInstance, jest.Mock> {
|
export function mockLogger(): Record<keyof LoggerInstance, jest.Mock> {
|
||||||
return {
|
return {
|
||||||
@@ -82,143 +79,38 @@ export function mockAdapter(): Adapter {
|
|||||||
return adapter
|
return adapter
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function nextHandler(
|
export async function nodeHandler(
|
||||||
params: {
|
params: {
|
||||||
req?: Partial<NextApiRequest>
|
req?: Partial<NextApiRequest>
|
||||||
res?: Partial<NextApiResponse>
|
res?: Partial<NextApiResponse>
|
||||||
options?: Partial<AuthOptions>
|
options?: Partial<AuthOptions>
|
||||||
} = {}
|
} = {}
|
||||||
) {
|
) {
|
||||||
let req = params.req
|
const req = {
|
||||||
// @ts-expect-error
|
body: {},
|
||||||
let res: NextApiResponse = params.res
|
cookies: {},
|
||||||
if (!params.res) {
|
headers: {},
|
||||||
;({ req, res } = mockReqRes(params.req))
|
method: "GET",
|
||||||
|
...params.req,
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = {
|
||||||
|
...params.res,
|
||||||
|
end: jest.fn(),
|
||||||
|
json: jest.fn(),
|
||||||
|
status: jest.fn().mockReturnValue({ end: jest.fn() }),
|
||||||
|
setHeader: jest.fn(),
|
||||||
|
removeHeader: jest.fn(),
|
||||||
|
send: jest.fn(),
|
||||||
}
|
}
|
||||||
|
|
||||||
const logger = mockLogger()
|
const logger = mockLogger()
|
||||||
// @ts-expect-error
|
|
||||||
await NextAuth(req, res, {
|
await NextAuth(req as any, res as any, {
|
||||||
providers: [],
|
providers: [],
|
||||||
secret: "secret",
|
secret: "secret",
|
||||||
logger,
|
logger,
|
||||||
...params.options,
|
...params.options,
|
||||||
})
|
})
|
||||||
|
|
||||||
return { req, res, logger }
|
return { req, res, logger }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function mockReqRes(req?: Partial<NextApiRequest>): {
|
|
||||||
req: NextApiRequest
|
|
||||||
res: NextApiResponse
|
|
||||||
} {
|
|
||||||
const request = new IncomingMessage(new Socket())
|
|
||||||
request.headers = req?.headers ?? {}
|
|
||||||
request.method = req?.method
|
|
||||||
request.url = req?.url
|
|
||||||
|
|
||||||
const response = new ServerResponse(request)
|
|
||||||
// @ts-expect-error
|
|
||||||
response.status = (code) => (response.statusCode = code)
|
|
||||||
// @ts-expect-error
|
|
||||||
response.send = (data) => sendData(request, response, data)
|
|
||||||
// @ts-expect-error
|
|
||||||
response.json = (data) => sendJson(response, data)
|
|
||||||
|
|
||||||
const res: NextApiResponse = {
|
|
||||||
...response,
|
|
||||||
// @ts-expect-error
|
|
||||||
setHeader: jest.spyOn(response, "setHeader"),
|
|
||||||
// @ts-expect-error
|
|
||||||
getHeader: jest.spyOn(response, "getHeader"),
|
|
||||||
// @ts-expect-error
|
|
||||||
removeHeader: jest.spyOn(response, "removeHeader"),
|
|
||||||
// @ts-expect-error
|
|
||||||
status: jest.spyOn(response, "status"),
|
|
||||||
// @ts-expect-error
|
|
||||||
send: jest.spyOn(response, "send"),
|
|
||||||
// @ts-expect-error
|
|
||||||
json: jest.spyOn(response, "json"),
|
|
||||||
// @ts-expect-error
|
|
||||||
end: jest.spyOn(response, "end"),
|
|
||||||
// @ts-expect-error
|
|
||||||
getHeaders: jest.spyOn(response, "getHeaders"),
|
|
||||||
}
|
|
||||||
|
|
||||||
return { req: request as any, res }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Code below is copied from Next.js
|
|
||||||
// https://github.com/vercel/next.js/tree/canary/packages/next/server/api-utils
|
|
||||||
// TODO: Remove
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send `any` body to response
|
|
||||||
* @param req request object
|
|
||||||
* @param res response object
|
|
||||||
* @param body of response
|
|
||||||
*/
|
|
||||||
function sendData(req: NextApiRequest, res: NextApiResponse, body: any): void {
|
|
||||||
if (body === null || body === undefined) {
|
|
||||||
res.end()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip irrelevant headers/body
|
|
||||||
if (res.statusCode === 204 || res.statusCode === 304) {
|
|
||||||
res.removeHeader("Content-Type")
|
|
||||||
res.removeHeader("Content-Length")
|
|
||||||
res.removeHeader("Transfer-Encoding")
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development" && body) {
|
|
||||||
console.warn(
|
|
||||||
`A body was attempted to be set with a 204 statusCode for ${req.url}, this is invalid and the body was ignored.\n` +
|
|
||||||
`See more info here https://nextjs.org/docs/messages/invalid-api-status-body`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
res.end()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const contentType = res.getHeader("Content-Type")
|
|
||||||
|
|
||||||
if (body instanceof Stream) {
|
|
||||||
if (!contentType) {
|
|
||||||
res.setHeader("Content-Type", "application/octet-stream")
|
|
||||||
}
|
|
||||||
body.pipe(res)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
const isJSONLike = ["object", "number", "boolean"].includes(typeof body)
|
|
||||||
const stringifiedBody = isJSONLike ? JSON.stringify(body) : body
|
|
||||||
|
|
||||||
if (Buffer.isBuffer(body)) {
|
|
||||||
if (!contentType) {
|
|
||||||
res.setHeader("Content-Type", "application/octet-stream")
|
|
||||||
}
|
|
||||||
res.setHeader("Content-Length", body.length)
|
|
||||||
res.end(body)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isJSONLike) {
|
|
||||||
res.setHeader("Content-Type", "application/json; charset=utf-8")
|
|
||||||
}
|
|
||||||
|
|
||||||
res.setHeader("Content-Length", Buffer.byteLength(stringifiedBody))
|
|
||||||
res.end(stringifiedBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send `JSON` object
|
|
||||||
* @param res response object
|
|
||||||
* @param jsonBody of data
|
|
||||||
*/
|
|
||||||
function sendJson(res: NextApiResponse, jsonBody: any): void {
|
|
||||||
// Set header to application/json
|
|
||||||
res.setHeader("Content-Type", "application/json; charset=utf-8")
|
|
||||||
|
|
||||||
// Use send to handle request
|
|
||||||
res.send(JSON.stringify(jsonBody))
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user