From 5923dd77c17c80747f9fe746ff8270ad4c820003 Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 18 Oct 2022 15:52:49 +0200 Subject: [PATCH] adding cookies to api route response [simple result] (#5060) * adding cookies to the an api route response, also when returning a simple result * in dev server, convert a simple endpoint result into a response object Co-authored-by: AirBorne04 Co-authored-by: AirBorne04 <> Co-authored-by: Matthew Phillips --- .changeset/silent-cougars-run.md | 5 ++++ examples/ssr/package.json | 2 -- examples/ssr/src/api.ts | 1 + examples/ssr/src/models/user.ts | 7 ----- examples/ssr/src/pages/api/cart.ts | 12 ++++----- examples/ssr/src/pages/cart.astro | 3 +-- examples/ssr/src/pages/login.astro | 27 +++++++++++++++++++ examples/ssr/src/pages/login.form.async.ts | 16 +++++++++++ examples/ssr/src/pages/login.form.js | 9 ------- examples/ssr/src/pages/login.form.ts | 16 +++++++++++ packages/astro/src/core/app/index.ts | 8 ++++-- packages/astro/src/core/endpoint/index.ts | 2 ++ .../src/vite-plugin-astro-server/index.ts | 12 ++++++--- pnpm-lock.yaml | 6 ----- 14 files changed, 88 insertions(+), 38 deletions(-) create mode 100644 .changeset/silent-cougars-run.md delete mode 100644 examples/ssr/src/models/user.ts create mode 100644 examples/ssr/src/pages/login.form.async.ts delete mode 100644 examples/ssr/src/pages/login.form.js create mode 100644 examples/ssr/src/pages/login.form.ts diff --git a/.changeset/silent-cougars-run.md b/.changeset/silent-cougars-run.md new file mode 100644 index 000000000..b4cfce318 --- /dev/null +++ b/.changeset/silent-cougars-run.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +api routes: adding cookies to the response, also when returning a simple result diff --git a/examples/ssr/package.json b/examples/ssr/package.json index e792eb3ae..21162e0fb 100644 --- a/examples/ssr/package.json +++ b/examples/ssr/package.json @@ -11,14 +11,12 @@ "astro": "astro", "server": "node dist/server/entry.mjs" }, - "devDependencies": {}, "dependencies": { "astro": "^1.5.0", "svelte": "^3.48.0", "@astrojs/svelte": "^1.0.2", "@astrojs/node": "^2.0.0", "concurrently": "^7.2.1", - "lightcookie": "^1.0.25", "unocss": "^0.15.6", "vite-imagetools": "^4.0.4" } diff --git a/examples/ssr/src/api.ts b/examples/ssr/src/api.ts index 32b48e220..1be1f54f0 100644 --- a/examples/ssr/src/api.ts +++ b/examples/ssr/src/api.ts @@ -28,6 +28,7 @@ async function get( ): Promise { const response = await fetch(`${getOrigin(incomingReq)}${endpoint}`, { credentials: 'same-origin', + headers: incomingReq.headers, }); if (!response.ok) { // TODO make this better... diff --git a/examples/ssr/src/models/user.ts b/examples/ssr/src/models/user.ts deleted file mode 100644 index a2812a8ad..000000000 --- a/examples/ssr/src/models/user.ts +++ /dev/null @@ -1,7 +0,0 @@ -import lightcookie from 'lightcookie'; - -export function isLoggedIn(request: Request): boolean { - const cookie = request.headers.get('cookie'); - const parsed = lightcookie.parse(cookie); - return 'user-id' in parsed; -} diff --git a/examples/ssr/src/pages/api/cart.ts b/examples/ssr/src/pages/api/cart.ts index d8bfa31a0..80db01f16 100644 --- a/examples/ssr/src/pages/api/cart.ts +++ b/examples/ssr/src/pages/api/cart.ts @@ -1,10 +1,9 @@ import { APIContext } from 'astro'; -import lightcookie from 'lightcookie'; import { userCartItems } from '../../models/session'; -export function get({ request }: APIContext) { - let cookie = request.headers.get('cookie'); - let userId = cookie ? lightcookie.parse(cookie)['user-id'] : '1'; // default for testing +export function get({ cookies }: APIContext) { + let userId = cookies.get('user-id').value; + if (!userId || !userCartItems.has(userId)) { return { body: JSON.stringify({ items: [] }), @@ -23,11 +22,10 @@ interface AddToCartItem { name: string; } -export async function post({ request }: APIContext) { +export async function post({ cookies, request }: APIContext) { const item: AddToCartItem = await request.json(); - let cookie = request.headers.get('cookie'); - let userId = lightcookie.parse(cookie)['user-id']; + let userId = cookies.get('user-id').value; if (!userCartItems.has(userId)) { userCartItems.set(userId, new Map()); diff --git a/examples/ssr/src/pages/cart.astro b/examples/ssr/src/pages/cart.astro index 68286ac61..d153e3ea9 100644 --- a/examples/ssr/src/pages/cart.astro +++ b/examples/ssr/src/pages/cart.astro @@ -2,9 +2,8 @@ import Header from '../components/Header.astro'; import Container from '../components/Container.astro'; import { getCart } from '../api'; -import { isLoggedIn } from '../models/user'; -if (!isLoggedIn(Astro.request)) { +if (!Astro.cookies.get('user-id').value) { return Astro.redirect('/'); } diff --git a/examples/ssr/src/pages/login.astro b/examples/ssr/src/pages/login.astro index 1b3cb9ede..45643665e 100644 --- a/examples/ssr/src/pages/login.astro +++ b/examples/ssr/src/pages/login.astro @@ -11,6 +11,32 @@ import Container from '../components/Container.astro'; font-size: 36px; } + +
@@ -26,6 +52,7 @@ import Container from '../components/Container.astro'; +
diff --git a/examples/ssr/src/pages/login.form.async.ts b/examples/ssr/src/pages/login.form.async.ts new file mode 100644 index 000000000..f98b11cfe --- /dev/null +++ b/examples/ssr/src/pages/login.form.async.ts @@ -0,0 +1,16 @@ +import { APIContext, APIRoute } from 'astro'; + +export const post: APIRoute = ({ cookies, params, request }: APIContext) => { + // add a new cookie + cookies.set('user-id', '1', { + path: '/', + maxAge: 2592000, + }); + + return { + body: JSON.stringify({ + ok: true, + user: 1, + }), + }; +}; diff --git a/examples/ssr/src/pages/login.form.js b/examples/ssr/src/pages/login.form.js deleted file mode 100644 index 134b0185f..000000000 --- a/examples/ssr/src/pages/login.form.js +++ /dev/null @@ -1,9 +0,0 @@ -export function post(params, request) { - return new Response(null, { - status: 301, - headers: { - Location: '/', - 'Set-Cookie': 'user-id=1; Path=/; Max-Age=2592000', - }, - }); -} diff --git a/examples/ssr/src/pages/login.form.ts b/examples/ssr/src/pages/login.form.ts new file mode 100644 index 000000000..de75c8cb3 --- /dev/null +++ b/examples/ssr/src/pages/login.form.ts @@ -0,0 +1,16 @@ +import { APIContext } from 'astro'; + +export function post({ cookies, params, request }: APIContext) { + // add a new cookie + cookies.set('user-id', '1', { + path: '/', + maxAge: 2592000, + }); + + return new Response(null, { + status: 301, + headers: { + Location: '/', + }, + }); +} diff --git a/packages/astro/src/core/app/index.ts b/packages/astro/src/core/app/index.ts index f443ffeac..e3d2bbe11 100644 --- a/packages/astro/src/core/app/index.ts +++ b/packages/astro/src/core/app/index.ts @@ -9,7 +9,7 @@ import type { LogOptions } from '../logger/core.js'; import type { RouteInfo, SSRManifest as Manifest } from './types'; import mime from 'mime'; -import { getSetCookiesFromResponse } from '../cookies/index.js'; +import { attachToResponse, getSetCookiesFromResponse } from '../cookies/index.js'; import { call as callEndpoint } from '../endpoint/index.js'; import { consoleLogDestination } from '../logger/console.js'; import { error } from '../logger/core.js'; @@ -236,10 +236,14 @@ export class App { } const bytes = this.#encoder.encode(body); headers.set('Content-Length', bytes.byteLength.toString()); - return new Response(bytes, { + + const response = new Response(bytes, { status: 200, headers, }); + + attachToResponse(response, result.cookies); + return response; } } } diff --git a/packages/astro/src/core/endpoint/index.ts b/packages/astro/src/core/endpoint/index.ts index f5407d7c5..79102f8b1 100644 --- a/packages/astro/src/core/endpoint/index.ts +++ b/packages/astro/src/core/endpoint/index.ts @@ -13,6 +13,7 @@ type EndpointCallResult = type: 'simple'; body: string; encoding?: BufferEncoding; + cookies: AstroCookies; } | { type: 'response'; @@ -109,5 +110,6 @@ export async function call( type: 'simple', body: response.body, encoding: response.encoding, + cookies: context.cookies, }; } diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index 2039c0a86..049dc4615 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -5,7 +5,7 @@ import type { AstroSettings, ManifestData } from '../@types/astro'; import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index'; import { Readable } from 'stream'; -import { getSetCookiesFromResponse } from '../core/cookies/index.js'; +import { attachToResponse, getSetCookiesFromResponse } from '../core/cookies/index.js'; import { call as callEndpoint } from '../core/endpoint/dev/index.js'; import { collectErrorMetadata, @@ -378,8 +378,14 @@ async function handleRoute( if (computedMimeType) { contentType = computedMimeType; } - res.writeHead(200, { 'Content-Type': `${contentType};charset=utf-8` }); - res.end(result.body); + const response = new Response(result.body, { + status: 200, + headers: { + 'Content-Type': `${contentType};charset=utf-8`, + }, + }); + attachToResponse(response, result.cookies); + await writeWebResponse(res, response); } } else { const result = await renderPage(options); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cca1d9229..74acb6114 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -260,7 +260,6 @@ importers: '@astrojs/svelte': ^1.0.2 astro: ^1.5.0 concurrently: ^7.2.1 - lightcookie: ^1.0.25 svelte: ^3.48.0 unocss: ^0.15.6 vite-imagetools: ^4.0.4 @@ -269,7 +268,6 @@ importers: '@astrojs/svelte': link:../../packages/integrations/svelte astro: link:../../packages/astro concurrently: 7.4.0 - lightcookie: 1.0.25 svelte: 3.52.0 unocss: 0.15.6 vite-imagetools: 4.0.11 @@ -13805,10 +13803,6 @@ packages: type-check: 0.4.0 dev: true - /lightcookie/1.0.25: - resolution: {integrity: sha512-SrY/+eBPaKAMnsn7mCsoOMZzoQyCyHHHZlFCu2fjo28XxSyCLjlooKiTxyrXTg8NPaHp1YzWi0lcGG1gDi6KHw==} - dev: false - /lilconfig/2.0.6: resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==} engines: {node: '>=10'}