Comments (42)
For anyone trying to use _middleware.js
without next i am going to list some findings that may be useful:
- you must have a
package.json
file on root too or it won't work. - Another cool thing to know is that you can also use
_middleware.ts
(using typescript) without any configuration because vercel bundles the _middleware file with esbuild on deployment - if you are trying to use
NextResponse.rewrite
from nextjs, you can use the following function for the same result
function rewrite(destination) {
return new Response(null, {
headers: {
'x-middleware-rewrite':
typeof destination === 'string'
? destination
: destination.toString(),
},
})
}
- For other cases just replace
NextResponse
withResponse
- To get
req.nextUrl.pathname
you can donew URL(req.url).pathname
from examples.
We're still working on it - apologies for the delay.
from examples.
A bit of progress in the last half an hour from digging around in next/server
at the NextResponse
class - this is just an extension of the Response class in the same way NextRequest
extends the Request class.
NextResponse.next()
which is used to pass control to the next middleware function in the examples in this repo (or will serve your content if there is no more middleware in place) can be replicated by returning the below. Vercel must pick this header up and know to pass this to the next middleware.
return new Response(null, {
headers: {
'x-middleware-next': '1',
},
});
You can do rewrites in a similar fashion, using a x-middleware-rewrite
header and passing a URL as the value. For more info take a look at the NextRequest class in the Next.js repo.
One major issue I'm currently having is that if you write a blank middleware such as below, the middleware successfully runs and your app is 'served', however any assets (.css
, .js
) seem to throw a 404 when requested by your app. I'm not sure if this is something I've misconfigured, but this makes my setup essentially unusable. I can seem to access the file directly and the Vercel cache header reports a 'HIT', so not sure why I'm getting a 404 for these...
Another thing I'm having issues with is that even though Vercel's middleware are run through ESBuild, I cannot seem to use any ES6 functionality and have to write much more primitive JS. I can't use things such as Array.get
or the Buffer
class.
I've managed to convert the basic-auth-password middleware and get it sort of working despite the above, but I hit the issue with CSS/JS assets throwing 404s meaning I can't take it any further at the mo. My demo can be found here and the code for the _middleware.ts
file I used is below.
export default function middleware(req: Request) {
const basicAuth = req.headers['authorization'];
if (basicAuth) {
const auth = basicAuth.split(' ')[1]
const decodedAuth = atob(auth).split(':');
const user = decodedAuth[0];
const pwd = decodedAuth[1];
if (user === '4dmin' && pwd === 'testpwd123') {
return new Response(null, {
headers: {
'x-middleware-next': '1',
},
})
}
}
return new Response('Auth required', {
status: 401,
headers: {
'WWW-Authenticate': 'Basic realm="Secure Area"',
},
})
}
from examples.
Any update on documentation for non-nextjs projects? All the above is helpful, but something a bit more formal would be much appreciated.
from examples.
Hey! We’re working on adding some examples for this. Middleware does indeed work with any framework, or just vanilla HTML, by placing the _middleware file in your root directly (or for framework authors, using the File System API).
from examples.
@brycewray agreed, I've been planning to raise a PR to add something like this for a few basic examples using both the file system API and potentially also fully vanilla (single middleware file?) but struggling to get the time to look at this for now. The main nuisance to work around is how to organise middleware examples in this repo, and then also re-working the plop scripts to support this new structure.
I'd propose edge-functions
would consist of three subdirectories, something like:
nextjs
vanilla
filesystem-api
...and moving all existing examples to the nextjs
dir and starting to recreate some of the existing Next.js examples in the other subdirectories.
from examples.
@brycewray sounds completely sensible - I'll see what I can do.
from examples.
@brycewray here's an example of an add-header
and basic-auth
middleware using create-react-app
. The _middleware.ts
file is compiled by ESBuild at build time within Vercel so having TypeScript does not matter despite being a non-TS project. These two examples are currently deployed here:
These mostly work but I'm coming across the same issue as I mentioned previously where certain assets return a 404 which I believe to be a bug within Vercel somewhere as certain assets load fine whilst others don't. Here's an example from the add-header
example I included, you can see the custom headers in the response headers but the main.XXXX.js/css
files are returning 404 so the React app does not load. @leerob is this something you're aware of at all?
from examples.
For anyone interested, I've made an example on how to deploy to Vercel Edge without Next.js: https://github.com/frandiox/hydrogen-vercel-edge
Demo: https://hydrogen-vercel-edge-frandiox.vercel.app/
As mentioned before, the key was using middleware-manifest.json
instead of functions-manifest.json
.
cc @leerob Perhaps this could be updated in the docs?
from examples.
I see you mentioned Hydrogen - what other frameworks are y'all wanting to use Middleware with? P.S. I'm still following along here 😄
from examples.
I was also trying to deploy the example and now I am even getting the following:
So, I am really wondering what the current status is here?
from examples.
I feel like you guys putting examples of middleware implementations on your site, saying you work with all frameworks, only to not, is blatantly false advertising.
Nowhere on these pages does it say that middleware is only supported by Next.js apps.
https://vercel.com/features/edge-functions
https://vercel.com/docs/concepts/functions/edge-functions
Riiiiiiiight......
from examples.
Alright, looks like it works when using middleware-manifest.json
instead of functions-manifest.json
, which is what `next build creates.
Now my problem is... To use the new ReadableStream() constructor, enable the streams_enable_constructors feature flag.
. How does one enable this in an Edge Function without Wrangler? 🤯
from examples.
Really would appreciate seeing some official docs detailing how to build middleware for a non-Next.js app. Managed to get a basic middleware working adapting @brycewray's snippet above to not use Next.js imports and saving this in my repo as ./_middleware.ts
(copied below), but this prevents the actual app from rendering - I'd like to see an example of a middleware where I can run functionality (such as adding a custom header) but still serving my app, like the examples we have for Next.js apps.
export default function middleware(req: Request) {
// You can add and append headers in multiple ways,
// below we'll explore some common patterns
// 1. Add a header to the `Headers` interface
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
const headers = new Headers({ 'x-custom-1': 'value-1' })
headers.set('x-custom-2', 'value-2')
// 2. Add existing headers to a new `Response`
const res = new Response(null, { headers })
// 3. Add a header to an existing response
res.headers.set('x-custom-3', 'value-3')
// 4. Merge existing headers with new ones in a response
return new Response(
'Open the network tab in devtools to see the response headers',
{
headers: {
...Object.fromEntries(res.headers),
'x-custom-4': 'value-4',
},
}
)
}
from examples.
For anyone interested, I've made an example on how to deploy to Vercel Edge without Next.js: https://github.com/frandiox/hydrogen-vercel-edge Demo: https://hydrogen-vercel-edge-frandiox.vercel.app/
As mentioned before, the key was using
middleware-manifest.json
instead offunctions-manifest.json
. cc @leerob Perhaps this could be updated in the docs?
Thanks @frandiox, nice example using the File System API - that raises a good point that there are really two parts to this issue, I think what we need in this repo is an example of both:
- Middleware using the File System API
- Middleware with just a simple
_middleware.js
, with no need to play with the File System API
It seems like the second point is supported in Vercel, but perhaps not fully working/documented yet. As @brycewray mentions, I think this is what most people would be seeking so that the overhead of setting up Vercel middleware for a non-Nextjs project is as simple as possible.
from examples.
I see you mentioned Hydrogen - what other frameworks are y'all wanting to use Middleware with? P.S. I'm still following along here 😄
Can’t answer for others, @leerob, but I just want as plain-vanilla JS as possible, for converting an existing CF Worker to work on Vercel. Since Edge already uses CF Workers, seems it wouldn’t be that hard, although I readily confess that I’m only guessing about that.
from examples.
@edcrampin That all sounds great! It’ll be tremendously appreciated — but I humbly re-suggest :) that, in the meantime and in view of the team’s absolutely understandable time limitations, the starting effort be something utterly simple, quick, and dirty, even if it’s only a vanilla version of _middleware.js
for a given example but with everything else in that example left as-is.
from examples.
Instead of NextRequest you have to use Request, which is a javascript built in
To migrate to a simple request, you can see how NextRequest
is implemented here
from examples.
@leerob I'm using docusaurus, so I think that means static HTML.
from examples.
I'm encountering the following error on deployment with a _middleware.ts
in the root of my docusaurus, and I'm wondering if anyone else has figured this one out:
TypeError: Unexpected MODIFIER at 1, expected END
at f (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:468718)
at parse (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:469358)
at stringToRegexp (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:471777)
at Object.pathToRegexp (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:472955)
at sourceToRegex (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:175287)
at /vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:173592
at Array.map (<anonymous>)
at convertRedirects (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:173560)
at Object.build (/vercel/b5af1ed6dff7b1bc/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:31:195137)
at async kot (/var/task/sandbox.js:197:12022)
from examples.
Am I correct in assuming this is unlikely to be addressed until 1Q 2022 due to the upcoming year-end holidays? Just curious. TIA for any such info.
from examples.
Any news on this topic?
from examples.
@remorses Although this doesn't eliminate the need for non-Next documentation from Vercel, it nonetheless is interesting and useful. Thanks!
from examples.
@remorses Just as a starter for those of us not all that into Next 😄 , how would you adjust the following _middleware.ts
code from the fairly simple example, https://github.com/vercel/examples/tree/main/edge-functions/add-header ? In particular, the part of each of the examples that throws me is always the import
statement in the top part, since that statement and the subsequent use of NextRequest
both obviously depend on Next. To a Next-savvy person, a non-Next substitution probably seems super-easy, but a non-Next-savvy guy like me wouldn't have a clue where to go from there. Thanks in advance for any related thoughts you might have.
import type { NextRequest } from 'next/server'
export function middleware(req: NextRequest) {
// You can add and append headers in multiple ways,
// below we'll explore some common patterns
// 1. Add a header to the `Headers` interface
// https://developer.mozilla.org/en-US/docs/Web/API/Headers
const headers = new Headers({ 'x-custom-1': 'value-1' })
headers.set('x-custom-2', 'value-2')
// 2. Add existing headers to a new `Response`
const res = new Response(null, { headers })
// 3. Add a header to an existing response
res.headers.set('x-custom-3', 'value-3')
// 4. Merge existing headers with new ones in a response
return new Response(
'Open the network tab in devtools to see the response headers',
{
headers: {
...Object.fromEntries(res.headers),
'x-custom-4': 'value-4',
},
}
)
}
from examples.
@brycewray Would be great if you can share your code once implemented!
from examples.
@ptrhck I haven't yet been able to make anything (i.e., that works). While @remorses provided valuable info, there are just too many other items that I'm not savvy enough to "translate" from Next to non-Next. Sorry!
from examples.
I'm always getting an error like:
TypeError: Cannot read property 'files' of undefined
--
21:41:41.309 | at /vercel/f053a0b194458027/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:26:255215
If I try to put _middleware.js
at the root and run vercel
, it shows that error. If I use the Filesytem API directly and create .output/functions-manifest.json
and .output/server/pages/_middleware.js
instead like you have in your source code and tests, it still throws.
The only way to bypass the error is moving .output/functions-manifest.json
to .output/server/functions-manifest.json
. This deploys but then nothing its returned from the function (404).
The code of the middleware is something like this:
"use strict";
const middleware = {
default: function (request) {
return new Response("hi from the edge!");
},
};
_ENTRIES = typeof _ENTRIES === "undefined" ? {} : _ENTRIES;
_ENTRIES["middleware_pages/_middleware"] = {
default: async function (ev) {
const result = await middleware.default(ev.request, ev);
return {
promise: Promise.resolve(),
waitUntil: Promise.resolve(),
response:
result ||
new Response(null, {
headers: {
"x-middleware-next": 1,
},
}),
};
},
};
I've also added a ENABLE_FILE_SYSTEM_API=1
environment variable to the deployment but no luck.
Any quick pointer, @leerob ? Thanks.
from examples.
For anyone interested, I've made an example on how to deploy to Vercel Edge without Next.js: https://github.com/frandiox/hydrogen-vercel-edge
Nice!
(But requires Shopify, right? I think what most of us are seeking are examples that require no specific platform but, rather, are as vanilla as possible.)
from examples.
@edcrampin could you share the repo you have for converting the basic password auth? That would be a great example to work from. I'm having trouble understanding the various roots in the project, i.e., where the middleware should go.
from examples.
HELP! WE NEED DOCUMENTATION. ffs.....
from examples.
With the understanding that there may not be bandwidth at Vercel to reproduce all the examples in non-Next form, maybe @leerob et al. could take just one of the simpler examples — such as add-header or geolocation — and produce a non-Next form of it. It would be like a Rosetta Stone, showing that “Thing A gets done in Next projects like this (existing example) but in plain-vanilla JS it gets done like this (proposed example).” That could be really helpful and, perhaps, wouldn’t take too much time to convert from whichever Next project you select.
Just a thought. 🙂
from examples.
@edcrampin Thanks very much! Will stand by for @leerob to weigh in on your question before trying.
from examples.
Thanks for the example, @edcrampin ! I feel that I've been able to rule out issues with the _middleware file and package.json thanks to that repo.
However, there appears to be some remaining issue, and I don't understand where to start analyzing this issue. It appears that moving the _middleware file will switch this error between being a simple middleware and a filesystem API issue, but there's something that the edge function deployer just doesn't like about ...something? My repo? My framework? My account?
As an aside, it would be nice to be able to test these things without waiting for a remote deployment and committing.
I'd love to hear input on what could be related to this issue, and I'm interested in helping to make sure that the documentation can help people who are using whatever new technology, and want to add middleware.
TypeError: Unexpected MODIFIER at 1, expected END
at parse (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:539986)
at stringToRegexp (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:542405)
at Object.pathToRegexp (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:543583)
at sourceToRegex (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:224129)
at /vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:222434
at Array.map (<anonymous>)
at convertRedirects (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:1:222402)
at Object.build (/vercel/b8b564fa9bd13b57/.build-utils/.builder/node_modules/@vercelruntimes/file-system-api/dist/index.js:31:90032)
at async qot (/var/task/sandbox.js:197:12762)
from examples.
I'm also using the latest docusaurus and getting the same error TypeError: Unexpected MODIFIER at 1, expected END
.
I tried with a noop middleware and it still fails, most probably related to docusaurus:
export default function middleware(req: Request) {
return new Response(null, {
headers: {
"x-middleware-next": "1",
},
});
}
from examples.
@edcrampin , could you share more about the settings you're using to deploy your example?
I assumed that it would use either the Other or Create React App preset, with the root directory edge-functions/create-react-app/basic-auth
(for the basic auth example), and no other settings changed.
I've tried deploying it and it failed:
Cloning bitbucket.org/Nefino/vercel-examples (Branch: main, Commit: 540430d)
Cloning completed: 1.921s
Installing build runtime...
Build runtime installed: 4.358s
Looking up build cache...
Build Cache not found
Detected package.json
Installing dependencies...
Detected `package-lock.json` generated by npm 7...
npm WARN deprecated [email protected]: This SVGO version is no longer supported. Upgrade to v2.x.x.
added 1369 packages in 45s
169 packages are looking for funding
run `npm fund` for details
Running `vercel build`
Vercel CLI 23.1.3-canary.71 build (beta) — https://vercel.com/feedback
Retrieved Project Settings:
- Framework Preset: Create React App
- Build Command: `npm run build` or `react-scripts build`
- Output Directory: build
Loaded 2 CLI Plugins
Running Build Command: `npm run build`
> [email protected] build
> react-scripts build && cp _middleware.ts ./build/
Creating an optimized production build...
Compiled successfully.
File sizes after gzip:
42.77 kB build/static/js/main.3dba3da1.js
541 B build/static/css/main.073c9b0a.css
The project was built assuming it is hosted at /.
You can control this with the homepage field in your package.json.
The build folder is ready to be deployed.
You may serve it with a static server:
npm install -g serve
serve -s build
Find out more about deployment here:
https://cra.link/deployment
Copying files from "build" to ".output/static"
Copied 14 files from "build" to ".output/static" [38ms]
Running 2 CLI Plugins after Build Command:
> vercel-plugin-middleware.build: Compiling middleware file: "/vercel/path0/edge-functions/create-react-app/basic-auth/_middleware.ts"
Build Completed in .output [12s]
Uploading build outputs...
An unexpected internal error occurred
from examples.
Btw, I got the following response from Vercel support:
Edge Functions (beta) are not ready outside of Next.js at the moment. We are working on making this possible!
So I guess we just have to be patient :)
from examples.
Forgot to swing back here, but with the stable release of Middleware, it can now be used with all frameworks 😄
Will be adding more examples, as well! This is just the start.
https://vercel.com/docs/concepts/functions/edge-middleware/quickstart
from examples.
I did finally get it working on a Hugo repo:
https://github.com/brycewray/hugo-site/blob/main/middleware.js
https://github.com/brycewray/hugo-site/blob/main/.deprecated/middleware.js
While most of its headers-handling could’ve been done in vercel.json
, the Content Security Policy needed dynamically generated nonces scattered throughout the site at appropriate places (scripts, certain links, etc.). This handles that just as its Cloudflare Worker predecessor did in Cloudflare Pages. 👍
@leerob, my compliments to your team for the content of both the Edge Functions and Middleware sections in the documentation — the info is much more comprehensive, and considerably easier to follow, than the last time I checked.
from examples.
@david-morris @charlax did you ever get your docusaurus sites behind authentication?
from examples.
@dmarkbreiter yes, I think we just crammed Docusaurus behind a Next.js shim before this was fixed though.
from examples.
Is there a Nuxt
example out there?
from examples.
Here is my middleware for a docusaurus static site:
const auth = process.env.AUTH
export default function middleware(request) {
const basicAuth = request.headers.get('Authorization')
if (!basicAuth) {
return new Response('Access denied', {
status: 401,
headers: { 'WWW-Authenticate': 'Basic' },
})
}
const authValue = basicAuth.split(' ')[1]
if (authValue !== auth) {
return new Response('Access denied', {
status: 401,
headers: { 'WWW-Authenticate': 'Basic' },
})
}
}
Use
echo -n "username:password" | base64
to generate the AUTH
string.
from examples.
Related Issues (20)
- Microfrontends example: Module not found: Can't resolve './example.module.css'
- feat(storybook): introduce to `/solution/monorepo`
- Bug: Wrong header in `https://app-dir-i18n.vercel.app/` HOT 1
- nextjs-flask: The flask api endpoint is not working. HOT 2
- Your location is undefined HOT 5
- PostgreSQL on docker and Next.js locally Error: connect ECONNREFUSED ::1:443 HOT 1
- Node.js Serverless Function template doesn't work (gives a 404) HOT 2
- Update deployment GitHub workflows
- bug
- Domain API Example broken
- Flask3 example doesn't work with additional dependencies
- Sonic example doesn't work
- https://flask2-python-template.vercel.app/ HOT 2
- postgres-drizzle got slow
- How to run Flask WSGI in Multithreaded Mode
- Micro-frontend example -module not found
- bot-protection-botd example no longer working
- Django deployment - pip3 not supported (?) impossible to install custom dependencies
- Cannot run the FLASK NEXTJS example 😭 HOT 1
- The PDF text bounds are not being retrieved properly when using the Next.js sample on Vercel in the client-side.
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from examples.