-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(astro): experimental middleware (#6721)
Co-authored-by: Sarah Rainsberger <[email protected]>
- Loading branch information
1 parent
ad90719
commit 831b67c
Showing
67 changed files
with
3,746 additions
and
2,187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
'astro': minor | ||
--- | ||
|
||
New middleware API |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { defineConfig } from 'astro/config'; | ||
import node from '@astrojs/node'; | ||
|
||
// https://astro.build/config | ||
export default defineConfig({ | ||
output: 'server', | ||
adapter: node({ | ||
mode: 'standalone', | ||
}), | ||
experimental: { | ||
middleware: true, | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "@example/middleware", | ||
"type": "module", | ||
"version": "0.0.1", | ||
"private": true, | ||
"scripts": { | ||
"dev": "astro dev", | ||
"start": "astro dev", | ||
"build": "astro build", | ||
"preview": "astro preview", | ||
"astro": "astro", | ||
"server": "node dist/server/entry.mjs" | ||
}, | ||
"dependencies": { | ||
"astro": "workspace:*", | ||
"svelte": "^3.48.0", | ||
"@astrojs/node": "workspace:*", | ||
"concurrently": "^7.2.1", | ||
"unocss": "^0.15.6", | ||
"vite-imagetools": "^4.0.4", | ||
"html-minifier": "^4.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
export interface Props { | ||
title: string; | ||
body: string; | ||
href: string; | ||
} | ||
const { href, title, body } = Astro.props; | ||
--- | ||
|
||
<li class="link-card"> | ||
<a href={href}> | ||
<h2> | ||
{title} | ||
<span>→</span> | ||
</h2> | ||
<p> | ||
{body} | ||
</p> | ||
</a> | ||
</li> | ||
<style> | ||
.link-card { | ||
list-style: none; | ||
display: flex; | ||
padding: 0.25rem; | ||
background-color: white; | ||
background-image: none; | ||
background-size: 400%; | ||
border-radius: 0.6rem; | ||
background-position: 100%; | ||
transition: background-position 0.6s cubic-bezier(0.22, 1, 0.36, 1); | ||
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); | ||
} | ||
|
||
.link-card > a { | ||
width: 100%; | ||
text-decoration: none; | ||
line-height: 1.4; | ||
padding: 1rem 1.3rem; | ||
border-radius: 0.35rem; | ||
color: #111; | ||
background-color: white; | ||
opacity: 0.8; | ||
} | ||
h2 { | ||
margin: 0; | ||
font-size: 1.25rem; | ||
transition: color 0.6s cubic-bezier(0.22, 1, 0.36, 1); | ||
} | ||
p { | ||
margin-top: 0.5rem; | ||
margin-bottom: 0; | ||
color: #444; | ||
} | ||
.link-card:is(:hover, :focus-within) { | ||
background-position: 0; | ||
background-image: var(--accent-gradient); | ||
} | ||
.link-card:is(:hover, :focus-within) h2 { | ||
color: rgb(var(--accent)); | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
/// <reference types="astro/client" /> | ||
declare global { | ||
namespace AstroMiddleware { | ||
interface Locals { | ||
user: { | ||
name: string; | ||
surname: string; | ||
}; | ||
} | ||
} | ||
} | ||
|
||
export {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
--- | ||
export interface Props { | ||
title: string; | ||
} | ||
const { title } = Astro.props; | ||
--- | ||
|
||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width" /> | ||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> | ||
<meta name="generator" content={Astro.generator} /> | ||
<title>{title}</title> | ||
</head> | ||
<body> | ||
<slot /> | ||
</body> | ||
</html> | ||
<style is:global> | ||
:root { | ||
--accent: 124, 58, 237; | ||
--accent-gradient: linear-gradient(45deg, rgb(var(--accent)), #da62c4 30%, white 60%); | ||
} | ||
html { | ||
font-family: system-ui, sans-serif; | ||
background-color: #f6f6f6; | ||
} | ||
code { | ||
font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, | ||
Bitstream Vera Sans Mono, Courier New, monospace; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { defineMiddleware, sequence } from 'astro/middleware'; | ||
import htmlMinifier from 'html-minifier'; | ||
|
||
const limit = 50; | ||
|
||
const loginInfo = { | ||
token: undefined, | ||
currentTime: undefined, | ||
}; | ||
|
||
export const minifier = defineMiddleware(async (context, next) => { | ||
const response = await next(); | ||
// check if the response is returning some HTML | ||
if (response.headers.get('content-type') === 'text/html') { | ||
let headers = response.headers; | ||
let html = await response.text(); | ||
let newHtml = htmlMinifier.minify(html, { | ||
removeAttributeQuotes: true, | ||
collapseWhitespace: true, | ||
}); | ||
return new Response(newHtml, { | ||
status: 200, | ||
headers, | ||
}); | ||
} | ||
return response; | ||
}); | ||
|
||
const validation = defineMiddleware(async (context, next) => { | ||
if (context.request.url.endsWith('/admin')) { | ||
if (loginInfo.currentTime) { | ||
const difference = new Date().getTime() - loginInfo.currentTime; | ||
if (difference > limit) { | ||
console.log('hit threshold'); | ||
loginInfo.token = undefined; | ||
loginInfo.currentTime = undefined; | ||
return context.redirect('/login'); | ||
} | ||
} | ||
// we naively check if we have a token | ||
if (loginInfo.token && loginInfo.token === 'loggedIn') { | ||
// we fill the locals with user-facing information | ||
context.locals.user = { | ||
name: 'AstroUser', | ||
surname: 'AstroSurname', | ||
}; | ||
return await next(); | ||
} else { | ||
loginInfo.token = undefined; | ||
loginInfo.currentTime = undefined; | ||
return context.redirect('/login'); | ||
} | ||
} else if (context.request.url.endsWith('/api/login')) { | ||
const response = await next(); | ||
// the login endpoint will return to us a JSON with username and password | ||
const data = await response.json(); | ||
// we naively check if username and password are equals to some string | ||
if (data.username === 'astro' && data.password === 'astro') { | ||
// we store the token somewhere outside of locals because the `locals` object is attached to the request | ||
// and when doing a redirect, we lose that information | ||
loginInfo.token = 'loggedIn'; | ||
loginInfo.currentTime = new Date().getTime(); | ||
return context.redirect('/admin'); | ||
} | ||
} | ||
// we don't really care about awaiting the response in this case | ||
next(); | ||
return; | ||
}); | ||
|
||
export const onRequest = sequence(validation, minifier); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
--- | ||
import Layout from '../layouts/Layout.astro'; | ||
const user = Astro.locals.user; | ||
--- | ||
|
||
<Layout title="Welcome back!!"> | ||
<main> | ||
<h1>Welcome back <span class="text-gradient">{user.name} {user.surname}</span></h1> | ||
</main> | ||
</Layout> | ||
|
||
<style> | ||
main { | ||
margin: auto; | ||
padding: 1.5rem; | ||
max-width: 60ch; | ||
} | ||
h1 { | ||
font-size: 3rem; | ||
font-weight: 800; | ||
margin: 0; | ||
} | ||
.text-gradient { | ||
background-image: var(--accent-gradient); | ||
-webkit-background-clip: text; | ||
-webkit-text-fill-color: transparent; | ||
background-size: 400%; | ||
background-position: 0%; | ||
} | ||
.instructions { | ||
line-height: 1.6; | ||
margin: 1rem 0; | ||
border: 1px solid rgba(var(--accent), 25%); | ||
background-color: white; | ||
padding: 1rem; | ||
border-radius: 0.4rem; | ||
} | ||
.instructions code { | ||
font-size: 0.875em; | ||
font-weight: bold; | ||
background: rgba(var(--accent), 12%); | ||
color: rgb(var(--accent)); | ||
border-radius: 4px; | ||
padding: 0.3em 0.45em; | ||
} | ||
.instructions strong { | ||
color: rgb(var(--accent)); | ||
} | ||
.link-card-grid { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr)); | ||
gap: 1rem; | ||
padding: 0; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { APIRoute } from 'astro'; | ||
|
||
export const post: APIRoute = async ({ request }) => { | ||
const data = await request.formData(); | ||
const username = data.get('username'); | ||
const password = data.get('password'); | ||
return new Response( | ||
JSON.stringify({ | ||
username, | ||
password, | ||
}), | ||
{ | ||
headers: { | ||
'content-type': 'application/json', | ||
}, | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
import Layout from '../layouts/Layout.astro'; | ||
import Card from '../components/Card.astro'; | ||
--- | ||
|
||
<Layout title="Welcome to Astro."> | ||
<main> | ||
<h1>Welcome to <span class="text-gradient">Astro</span></h1> | ||
<p class="instructions"> | ||
To get started, open the directory <code>src/pages</code> in your project.<br /> | ||
<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above. | ||
</p> | ||
{} | ||
<ul role="list" class="link-card-grid"> | ||
<Card href="/login" title="Login" body="Try the login" /> | ||
</ul> | ||
</main> | ||
</Layout> | ||
|
||
<style> | ||
main { | ||
margin: auto; | ||
padding: 1.5rem; | ||
max-width: 60ch; | ||
} | ||
h1 { | ||
font-size: 3rem; | ||
font-weight: 800; | ||
margin: 0; | ||
} | ||
.text-gradient { | ||
background-image: var(--accent-gradient); | ||
-webkit-background-clip: text; | ||
-webkit-text-fill-color: transparent; | ||
background-size: 400%; | ||
background-position: 0%; | ||
} | ||
.instructions { | ||
line-height: 1.6; | ||
margin: 1rem 0; | ||
border: 1px solid rgba(var(--accent), 25%); | ||
background-color: white; | ||
padding: 1rem; | ||
border-radius: 0.4rem; | ||
} | ||
.instructions code { | ||
font-size: 0.875em; | ||
font-weight: bold; | ||
background: rgba(var(--accent), 12%); | ||
color: rgb(var(--accent)); | ||
border-radius: 4px; | ||
padding: 0.3em 0.45em; | ||
} | ||
.instructions strong { | ||
color: rgb(var(--accent)); | ||
} | ||
.link-card-grid { | ||
display: grid; | ||
grid-template-columns: repeat(auto-fit, minmax(24ch, 1fr)); | ||
gap: 1rem; | ||
padding: 0; | ||
} | ||
</style> |
Oops, something went wrong.