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 <unknown> Co-authored-by: AirBorne04 <> Co-authored-by: Matthew Phillips <matthew@skypack.dev>
This commit is contained in:
parent
04ce7f4e5c
commit
5923dd77c1
14 changed files with 88 additions and 38 deletions
5
.changeset/silent-cougars-run.md
Normal file
5
.changeset/silent-cougars-run.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'astro': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
api routes: adding cookies to the response, also when returning a simple result
|
|
@ -11,14 +11,12 @@
|
||||||
"astro": "astro",
|
"astro": "astro",
|
||||||
"server": "node dist/server/entry.mjs"
|
"server": "node dist/server/entry.mjs"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"astro": "^1.5.0",
|
"astro": "^1.5.0",
|
||||||
"svelte": "^3.48.0",
|
"svelte": "^3.48.0",
|
||||||
"@astrojs/svelte": "^1.0.2",
|
"@astrojs/svelte": "^1.0.2",
|
||||||
"@astrojs/node": "^2.0.0",
|
"@astrojs/node": "^2.0.0",
|
||||||
"concurrently": "^7.2.1",
|
"concurrently": "^7.2.1",
|
||||||
"lightcookie": "^1.0.25",
|
|
||||||
"unocss": "^0.15.6",
|
"unocss": "^0.15.6",
|
||||||
"vite-imagetools": "^4.0.4"
|
"vite-imagetools": "^4.0.4"
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ async function get<T>(
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const response = await fetch(`${getOrigin(incomingReq)}${endpoint}`, {
|
const response = await fetch(`${getOrigin(incomingReq)}${endpoint}`, {
|
||||||
credentials: 'same-origin',
|
credentials: 'same-origin',
|
||||||
|
headers: incomingReq.headers,
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
// TODO make this better...
|
// TODO make this better...
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { APIContext } from 'astro';
|
import { APIContext } from 'astro';
|
||||||
import lightcookie from 'lightcookie';
|
|
||||||
import { userCartItems } from '../../models/session';
|
import { userCartItems } from '../../models/session';
|
||||||
|
|
||||||
export function get({ request }: APIContext) {
|
export function get({ cookies }: APIContext) {
|
||||||
let cookie = request.headers.get('cookie');
|
let userId = cookies.get('user-id').value;
|
||||||
let userId = cookie ? lightcookie.parse(cookie)['user-id'] : '1'; // default for testing
|
|
||||||
if (!userId || !userCartItems.has(userId)) {
|
if (!userId || !userCartItems.has(userId)) {
|
||||||
return {
|
return {
|
||||||
body: JSON.stringify({ items: [] }),
|
body: JSON.stringify({ items: [] }),
|
||||||
|
@ -23,11 +22,10 @@ interface AddToCartItem {
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function post({ request }: APIContext) {
|
export async function post({ cookies, request }: APIContext) {
|
||||||
const item: AddToCartItem = await request.json();
|
const item: AddToCartItem = await request.json();
|
||||||
|
|
||||||
let cookie = request.headers.get('cookie');
|
let userId = cookies.get('user-id').value;
|
||||||
let userId = lightcookie.parse(cookie)['user-id'];
|
|
||||||
|
|
||||||
if (!userCartItems.has(userId)) {
|
if (!userCartItems.has(userId)) {
|
||||||
userCartItems.set(userId, new Map());
|
userCartItems.set(userId, new Map());
|
||||||
|
|
|
@ -2,9 +2,8 @@
|
||||||
import Header from '../components/Header.astro';
|
import Header from '../components/Header.astro';
|
||||||
import Container from '../components/Container.astro';
|
import Container from '../components/Container.astro';
|
||||||
import { getCart } from '../api';
|
import { getCart } from '../api';
|
||||||
import { isLoggedIn } from '../models/user';
|
|
||||||
|
|
||||||
if (!isLoggedIn(Astro.request)) {
|
if (!Astro.cookies.get('user-id').value) {
|
||||||
return Astro.redirect('/');
|
return Astro.redirect('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,32 @@ import Container from '../components/Container.astro';
|
||||||
font-size: 36px;
|
font-size: 36px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<script type="module" is:inline>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
console.log('loaded');
|
||||||
|
document.querySelector('form').addEventListener('submit', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const form = e.target;
|
||||||
|
const formData = new FormData(form);
|
||||||
|
const data = Object.fromEntries(formData);
|
||||||
|
|
||||||
|
fetch('/login.form.async', {
|
||||||
|
method: 'POST',
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.then((data) => {
|
||||||
|
document.querySelector("#result").innerHTML = "Progressive login was successful! you will be redirected to the store in 3 seconds";
|
||||||
|
setTimeout(
|
||||||
|
() => location.href = "/",
|
||||||
|
3000
|
||||||
|
);
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<Header />
|
<Header />
|
||||||
|
@ -26,6 +52,7 @@ import Container from '../components/Container.astro';
|
||||||
|
|
||||||
<input type="submit" value="Submit" />
|
<input type="submit" value="Submit" />
|
||||||
</form>
|
</form>
|
||||||
|
<div id="result"></div>
|
||||||
</Container>
|
</Container>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
16
examples/ssr/src/pages/login.form.async.ts
Normal file
16
examples/ssr/src/pages/login.form.async.ts
Normal file
|
@ -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,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
};
|
|
@ -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',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
16
examples/ssr/src/pages/login.form.ts
Normal file
16
examples/ssr/src/pages/login.form.ts
Normal file
|
@ -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: '/',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
|
@ -9,7 +9,7 @@ import type { LogOptions } from '../logger/core.js';
|
||||||
import type { RouteInfo, SSRManifest as Manifest } from './types';
|
import type { RouteInfo, SSRManifest as Manifest } from './types';
|
||||||
|
|
||||||
import mime from 'mime';
|
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 { call as callEndpoint } from '../endpoint/index.js';
|
||||||
import { consoleLogDestination } from '../logger/console.js';
|
import { consoleLogDestination } from '../logger/console.js';
|
||||||
import { error } from '../logger/core.js';
|
import { error } from '../logger/core.js';
|
||||||
|
@ -236,10 +236,14 @@ export class App {
|
||||||
}
|
}
|
||||||
const bytes = this.#encoder.encode(body);
|
const bytes = this.#encoder.encode(body);
|
||||||
headers.set('Content-Length', bytes.byteLength.toString());
|
headers.set('Content-Length', bytes.byteLength.toString());
|
||||||
return new Response(bytes, {
|
|
||||||
|
const response = new Response(bytes, {
|
||||||
status: 200,
|
status: 200,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
attachToResponse(response, result.cookies);
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ type EndpointCallResult =
|
||||||
type: 'simple';
|
type: 'simple';
|
||||||
body: string;
|
body: string;
|
||||||
encoding?: BufferEncoding;
|
encoding?: BufferEncoding;
|
||||||
|
cookies: AstroCookies;
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'response';
|
type: 'response';
|
||||||
|
@ -109,5 +110,6 @@ export async function call(
|
||||||
type: 'simple',
|
type: 'simple',
|
||||||
body: response.body,
|
body: response.body,
|
||||||
encoding: response.encoding,
|
encoding: response.encoding,
|
||||||
|
cookies: context.cookies,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import type { AstroSettings, ManifestData } from '../@types/astro';
|
||||||
import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
import { DevelopmentEnvironment, SSROptions } from '../core/render/dev/index';
|
||||||
|
|
||||||
import { Readable } from 'stream';
|
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 { call as callEndpoint } from '../core/endpoint/dev/index.js';
|
||||||
import {
|
import {
|
||||||
collectErrorMetadata,
|
collectErrorMetadata,
|
||||||
|
@ -378,8 +378,14 @@ async function handleRoute(
|
||||||
if (computedMimeType) {
|
if (computedMimeType) {
|
||||||
contentType = computedMimeType;
|
contentType = computedMimeType;
|
||||||
}
|
}
|
||||||
res.writeHead(200, { 'Content-Type': `${contentType};charset=utf-8` });
|
const response = new Response(result.body, {
|
||||||
res.end(result.body);
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
'Content-Type': `${contentType};charset=utf-8`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
attachToResponse(response, result.cookies);
|
||||||
|
await writeWebResponse(res, response);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const result = await renderPage(options);
|
const result = await renderPage(options);
|
||||||
|
|
|
@ -260,7 +260,6 @@ importers:
|
||||||
'@astrojs/svelte': ^1.0.2
|
'@astrojs/svelte': ^1.0.2
|
||||||
astro: ^1.5.0
|
astro: ^1.5.0
|
||||||
concurrently: ^7.2.1
|
concurrently: ^7.2.1
|
||||||
lightcookie: ^1.0.25
|
|
||||||
svelte: ^3.48.0
|
svelte: ^3.48.0
|
||||||
unocss: ^0.15.6
|
unocss: ^0.15.6
|
||||||
vite-imagetools: ^4.0.4
|
vite-imagetools: ^4.0.4
|
||||||
|
@ -269,7 +268,6 @@ importers:
|
||||||
'@astrojs/svelte': link:../../packages/integrations/svelte
|
'@astrojs/svelte': link:../../packages/integrations/svelte
|
||||||
astro: link:../../packages/astro
|
astro: link:../../packages/astro
|
||||||
concurrently: 7.4.0
|
concurrently: 7.4.0
|
||||||
lightcookie: 1.0.25
|
|
||||||
svelte: 3.52.0
|
svelte: 3.52.0
|
||||||
unocss: 0.15.6
|
unocss: 0.15.6
|
||||||
vite-imagetools: 4.0.11
|
vite-imagetools: 4.0.11
|
||||||
|
@ -13805,10 +13803,6 @@ packages:
|
||||||
type-check: 0.4.0
|
type-check: 0.4.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/lightcookie/1.0.25:
|
|
||||||
resolution: {integrity: sha512-SrY/+eBPaKAMnsn7mCsoOMZzoQyCyHHHZlFCu2fjo28XxSyCLjlooKiTxyrXTg8NPaHp1YzWi0lcGG1gDi6KHw==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/lilconfig/2.0.6:
|
/lilconfig/2.0.6:
|
||||||
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
|
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|
Loading…
Reference in a new issue