summaryrefslogtreecommitdiff
path: root/examples/ssr/server
diff options
context:
space:
mode:
authorGravatar Matthew Phillips <matthew@skypack.dev> 2022-02-14 12:48:52 -0500
committerGravatar GitHub <noreply@github.com> 2022-02-14 12:48:52 -0500
commitba5e2b5e6c20207955991775dc4aa8879331542c (patch)
tree28e68347035a534f8b56991ede570dfcf830cb01 /examples/ssr/server
parent61f438fdcbab7163bc3399e623a80d283e018371 (diff)
downloadastro-ba5e2b5e6c20207955991775dc4aa8879331542c.tar.gz
astro-ba5e2b5e6c20207955991775dc4aa8879331542c.tar.zst
astro-ba5e2b5e6c20207955991775dc4aa8879331542c.zip
Flagged SSR support (#2548)
* Checkpoint, basics are working * Add the `--experimental-ssr` flag * Adds the changeset * Fixes population of getStaticPaths results * Pass through the imported module * Route manifest test * Fix remaining tests * Fix remaining tests * Copy server assets over * Fix types * Allowing passing in the request to the Node version of App * Improve the example app * Gets CI to pass
Diffstat (limited to 'examples/ssr/server')
-rw-r--r--examples/ssr/server/api.mjs49
-rw-r--r--examples/ssr/server/db.json28
-rw-r--r--examples/ssr/server/dev-api.mjs17
-rw-r--r--examples/ssr/server/server.mjs55
4 files changed, 149 insertions, 0 deletions
diff --git a/examples/ssr/server/api.mjs b/examples/ssr/server/api.mjs
new file mode 100644
index 000000000..3928d0507
--- /dev/null
+++ b/examples/ssr/server/api.mjs
@@ -0,0 +1,49 @@
+import fs from 'fs';
+const dbJSON = fs.readFileSync(new URL('./db.json', import.meta.url));
+const db = JSON.parse(dbJSON);
+const products = db.products;
+const productMap = new Map(products.map(product => [product.id, product]));
+
+const routes = [
+ {
+ match: /\/api\/products\/([0-9])+/,
+ async handle(_req, res, [,idStr]) {
+ const id = Number(idStr);
+ if(productMap.has(id)) {
+ const product = productMap.get(id);
+ res.writeHead(200, {
+ 'Content-Type': 'application/json'
+ });
+ res.end(JSON.stringify(product));
+ } else {
+ res.writeHead(404, {
+ 'Content-Type': 'text/plain'
+ });
+ res.end('Not found');
+ }
+ }
+ },
+ {
+ match: /\/api\/products/,
+ async handle(_req, res) {
+ res.writeHead(200, {
+ 'Content-Type': 'application/json',
+ });
+ res.end(JSON.stringify(products));
+ }
+ }
+
+]
+
+export async function apiHandler(req, res) {
+ for(const route of routes) {
+ const match = route.match.exec(req.url);
+ if(match) {
+ return route.handle(req, res, match);
+ }
+ }
+ res.writeHead(404, {
+ 'Content-Type': 'text/plain'
+ });
+ res.end('Not found');
+}
diff --git a/examples/ssr/server/db.json b/examples/ssr/server/db.json
new file mode 100644
index 000000000..76f9e4da3
--- /dev/null
+++ b/examples/ssr/server/db.json
@@ -0,0 +1,28 @@
+{
+ "products": [
+ {
+ "id": 1,
+ "name": "Cereal",
+ "price": 3.99,
+ "image": "/images/products/cereal.jpg"
+ },
+ {
+ "id": 2,
+ "name": "Yogurt",
+ "price": 3.97,
+ "image": "/images/products/yogurt.jpg"
+ },
+ {
+ "id": 3,
+ "name": "Rolled Oats",
+ "price": 2.89,
+ "image": "/images/products/oats.jpg"
+ },
+ {
+ "id": 4,
+ "name": "Muffins",
+ "price": 4.39,
+ "image": "/images/products/muffins.jpg"
+ }
+ ]
+}
diff --git a/examples/ssr/server/dev-api.mjs b/examples/ssr/server/dev-api.mjs
new file mode 100644
index 000000000..74e0ef83b
--- /dev/null
+++ b/examples/ssr/server/dev-api.mjs
@@ -0,0 +1,17 @@
+import { createServer } from 'http';
+import { apiHandler } from './api.mjs';
+
+const PORT = process.env.PORT || 8085;
+
+const server = createServer((req, res) => {
+ apiHandler(req, res).catch(err => {
+ console.error(err);
+ res.writeHead(500, {
+ 'Content-Type': 'text/plain'
+ });
+ res.end(err.toString());
+ })
+});
+
+server.listen(PORT);
+console.log(`API running at http://localhost:${PORT}`);
diff --git a/examples/ssr/server/server.mjs b/examples/ssr/server/server.mjs
new file mode 100644
index 000000000..6f0a0dea6
--- /dev/null
+++ b/examples/ssr/server/server.mjs
@@ -0,0 +1,55 @@
+import { createServer } from 'http';
+import fs from 'fs';
+import mime from 'mime';
+import { loadApp } from 'astro/app/node';
+import { polyfill } from '@astropub/webapi'
+import { apiHandler } from './api.mjs';
+
+polyfill(globalThis);
+
+const clientRoot = new URL('../dist/client/', import.meta.url);
+const serverRoot = new URL('../dist/server/', import.meta.url);
+const app = await loadApp(serverRoot);
+
+async function handle(req, res) {
+ const route = app.match(req);
+
+ if(route) {
+ const html = await app.render(req, route);
+
+ res.writeHead(200, {
+ 'Content-Type': 'text/html'
+ });
+ res.end(html)
+ } else if(/^\/api\//.test(req.url)) {
+ return apiHandler(req, res);
+ } else {
+ let local = new URL('.' + req.url, clientRoot);
+ try {
+ const data = await fs.promises.readFile(local);
+ res.writeHead(200, {
+ 'Content-Type': mime.getType(req.url)
+ });
+ res.end(data);
+ } catch {
+ res.writeHead(404);
+ res.end();
+ }
+ }
+}
+
+const server = createServer((req, res) => {
+ handle(req, res).catch(err => {
+ console.error(err);
+ res.writeHead(500, {
+ 'Content-Type': 'text/plain'
+ });
+ res.end(err.toString());
+ })
+});
+
+server.listen(8085);
+console.log('Serving at http://localhost:8085');
+
+// Silence weird <time> warning
+console.error = () => {};