Skip to content

Commit

Permalink
feat: expose locals to render api and from requests in dev mode (#7385)
Browse files Browse the repository at this point in the history
Co-authored-by: Emanuele Stoppa <[email protected]>
Co-authored-by: wrapperup <[email protected]>
  • Loading branch information
ematipico and wrapperup authored Jun 21, 2023
1 parent 7f53156 commit 1244c6e
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 2 deletions.
19 changes: 19 additions & 0 deletions packages/adapters/node/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,25 @@ app.use(ssrHandler);
app.listen({ port: 8080 });
```
Additionally, you can also pass in an object to be accessed with `Astro.locals` or in Astro middleware:
```js
import express from 'express';
import { handler as ssrHandler } from './dist/server/entry.mjs';
const app = express();
app.use(express.static('dist/client/'))
app.use((req, res, next) => {
const locals = {
title: 'New title'
};
ssrHandler(req, res, next, locals);
);
app.listen(8080);
```
Note that middleware mode does not do file serving. You'll need to configure your HTTP framework to do that for you. By default the client assets are written to `./dist/client/`.
### Standalone
Expand Down
5 changes: 3 additions & 2 deletions packages/adapters/node/src/nodeMiddleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ export default function (app: NodeApp, mode: Options['mode']) {
return async function (
req: IncomingMessage,
res: ServerResponse,
next?: (err?: unknown) => void
next?: (err?: unknown) => void,
locals?: object
) {
try {
const route =
mode === 'standalone' ? app.match(req, { matchNotFound: true }) : app.match(req);
if (route) {
try {
const response = await app.render(req);
const response = await app.render(req, route, locals);
await writeWebResponse(app, res, response);
} catch (err: unknown) {
if (next) {
Expand Down
9 changes: 9 additions & 0 deletions packages/adapters/node/test/fixtures/locals/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "@test/locals",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*",
"@astrojs/node": "workspace:*"
}
}
10 changes: 10 additions & 0 deletions packages/adapters/node/test/fixtures/locals/src/pages/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

export async function post({ locals }) {
let out = { ...locals };

return new Response(JSON.stringify(out), {
headers: {
'Content-Type': 'application/json'
}
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
---
const { foo } = Astro.locals;
---
<h1>{foo}</h1>
53 changes: 53 additions & 0 deletions packages/adapters/node/test/locals.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import nodejs from '../dist/index.js';
import { loadFixture, createRequestAndResponse } from './test-utils.js';
import { expect } from 'chai';

describe('API routes', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;

before(async () => {
fixture = await loadFixture({
root: './fixtures/locals/',
output: 'server',
adapter: nodejs({ mode: 'middleware' }),
});
await fixture.build();
});

it('Can render locals in page', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
let { req, res, text } = createRequestAndResponse({
method: 'POST',
url: '/foo',
});

let locals = { foo: 'bar' };

handler(req, res, () => {}, locals);
req.send();

let html = await text();

expect(html).to.contain('<h1>bar</h1>');
});

it('Can access locals in API', async () => {
const { handler } = await import('./fixtures/locals/dist/server/entry.mjs');
let { req, res, done } = createRequestAndResponse({
method: 'POST',
url: '/api',
});

let locals = { foo: 'bar' };

handler(req, res, () => {}, locals);
req.send();

let [buffer] = await done;

let json = JSON.parse(buffer.toString('utf-8'));

expect(json.foo).to.equal('bar');
});
});

0 comments on commit 1244c6e

Please sign in to comment.