Skip to content

Commit

Permalink
Merge pull request #74 from kubetail-org/next15
Browse files Browse the repository at this point in the history
Adds support for Next 15
  • Loading branch information
amorey authored Oct 23, 2024
2 parents 785f622 + cf8cb8f commit f6af7e6
Show file tree
Hide file tree
Showing 108 changed files with 2,408 additions and 85 deletions.
39 changes: 34 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,40 @@ jobs:
- uses: pnpm/action-setup@v3
with:
version: 9
- run: pnpm install
- run: pnpm -r test run -- --environment node
- run: pnpm -r test run -- --environment edge-runtime
- run: pnpm -r build # only necessary for miniflare
- run: pnpm -r test run -- --environment miniflare
- name: Install dependencies
run: pnpm install
- name: Run tests
run: |
pnpm -r build # only necessary for miniflare
pnpm -r test run -- --environment node
pnpm -r test run -- --environment edge-runtime
pnpm -r test run -- --environment miniflare
test-nextjs:
runs-on: ubuntu-latest
strategy:
matrix:
version: [13, 14, 15]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v3
with:
version: 9
- name: Install dependencies
run: pnpm install
- name: Install Next.js version
working-directory: packages/nextjs
run: pnpm install next@${{ matrix.version }}
- name: Run tests
working-directory: packages/nextjs
run: |
pnpm build # only necessary for miniflare
pnpm test run -- --environment node
pnpm test run -- --environment edge-runtime
pnpm test run -- --environment miniflare
build:
runs-on: ubuntu-latest
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,10 @@ Now, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be reject

import { headers } from 'next/headers';

export default function Page() {
const csrfToken = headers().get('X-CSRF-Token') || 'missing';
export default async function Page() {
// NOTE: headers() don't need to be awaited in Next14
const h = await headers();
const csrfToken = h.get('X-CSRF-Token') || 'missing';

return (
<form action="/api/form-handler" method="post">
Expand All @@ -83,6 +85,8 @@ export async function POST() {
}
```

For more Next.js examples see the [package documentation](packages/nextjs).

## Quickstart (SvelteKit)

First, install Edge-CSRF's SvelteKit integration library:
Expand Down Expand Up @@ -231,7 +235,7 @@ app.listen(port, () => {
});
```

With the middleware installed, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.
With the middleware installed, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.

## Quickstart (Node-HTTP)

Expand Down Expand Up @@ -313,7 +317,7 @@ server.listen(3000, () => {
});
```

With the CSRF protection method, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.
With the CSRF protection method, all HTTP submission requests (e.g. POST, PUT, DELETE, PATCH) will be rejected if they do not include a valid CSRF token.

## Development

Expand Down
3 changes: 3 additions & 0 deletions examples/next15-approuter-html-submission/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
26 changes: 26 additions & 0 deletions examples/next15-approuter-html-submission/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, install dependencies:

```bash
npm install
# or
pnpm install
# or
yarn install
```

Next, run the development server:

```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NextResponse } from 'next/server';

export async function POST() {
return NextResponse.json({ status: 'success' });
}
19 changes: 19 additions & 0 deletions examples/next15-approuter-html-submission/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Metadata } from 'next';

export const metadata: Metadata = {
title: 'edge-csrf html form submission example',
};

export default function Layout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}
57 changes: 57 additions & 0 deletions examples/next15-approuter-html-submission/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { headers } from 'next/headers';

import '../styles/globals.css';

export default async function Page() {
const headersList = await headers();
const csrfToken = headersList.get('X-CSRF-Token') || 'missing';

return (
<>
<p>
CSRF token value:
{csrfToken}
</p>
<h2>HTML Form Submission Example:</h2>
<form action="/form-handler" method="post">
<legend>Form without CSRF (should fail):</legend>
<input type="text" name="input1" />
<button type="submit">Submit</button>
</form>
<br />
<form action="/form-handler" method="post">
<legend>Form with incorrect CSRF (should fail):</legend>
<input type="hidden" name="csrf_token" value="notvalid" />
<input type="text" name="input1" />
<button type="submit">Submit</button>
</form>
<br />
<form action="/form-handler" method="post">
<legend>Form with CSRF (should succeed):</legend>
<input type="hidden" name="csrf_token" value={csrfToken} />
<input type="text" name="input1" />
<button type="submit">Submit</button>
</form>
<h2>HTML File Upload Example:</h2>
<form action="/form-handler" method="post" encType="multipart/form-data">
<legend>Form without CSRF (should fail):</legend>
<input type="file" name="file1" />
<button type="submit">Submit</button>
</form>
<br />
<form action="/form-handler" method="post" encType="multipart/form-data">
<legend>Form with incorrect CSRF (should fail):</legend>
<input type="hidden" name="csrf_token" value="notvalid" />
<input type="file" name="file1" />
<button type="submit">Submit</button>
</form>
<br />
<form action="/form-handler" method="post" encType="multipart/form-data">
<legend>Form with CSRF (should succeed):</legend>
<input type="hidden" name="csrf_token" value={csrfToken} />
<input type="file" name="file1" />
<button type="submit">Submit</button>
</form>
</>
);
}
10 changes: 10 additions & 0 deletions examples/next15-approuter-html-submission/middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { createCsrfMiddleware } from '@edge-csrf/nextjs';

// initalize csrf protection middleware
const csrfMiddleware = createCsrfMiddleware({
cookie: {
secure: process.env.NODE_ENV === 'production',
},
});

export const middleware = csrfMiddleware;
5 changes: 5 additions & 0 deletions examples/next15-approuter-html-submission/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
6 changes: 6 additions & 0 deletions examples/next15-approuter-html-submission/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}

module.exports = nextConfig;
23 changes: 23 additions & 0 deletions examples/next15-approuter-html-submission/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "edge-csrf-example",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@edge-csrf/nextjs": "^2.0.0",
"@types/node": "^20.8.9",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.14",
"eslint": "^8.52.0",
"eslint-config-next": "^15.0.0",
"next": "^15.0.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.2.2"
}
}
Binary file not shown.
4 changes: 4 additions & 0 deletions examples/next15-approuter-html-submission/public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions examples/next15-approuter-html-submission/styles/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
html,
body {
padding: 0;
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
}

a {
color: blue;
text-decoration: underline;
}

* {
box-sizing: border-box;
}

@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
body {
color: white;
background: black;
}
}
36 changes: 36 additions & 0 deletions examples/next15-approuter-html-submission/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"compilerOptions": {
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"target": "ES2017",
"plugins": [
{
"name": "next"
}
]
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts"
],
"exclude": [
"node_modules"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
26 changes: 26 additions & 0 deletions examples/next15-approuter-js-submission-dynamic/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).

## Getting Started

First, install dependencies:

```bash
npm install
# or
pnpm install
# or
yarn install
```

Next, run the development server:

```bash
npm run dev
# or
pnpm dev
# or
yarn dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { NextResponse } from 'next/server';

export async function POST() {
return NextResponse.json({ status: 'success' });
}
28 changes: 28 additions & 0 deletions examples/next15-approuter-js-submission-dynamic/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Metadata } from 'next';
import { headers } from 'next/headers';

export async function generateMetadata(): Promise<Metadata> {
const headersList = await headers();
const csrfToken = headersList.get('X-CSRF-Token') || 'missing';

return {
title: 'edge-csrf example',
other: {
'x-csrf-token': csrfToken,
},
};
}

export default function Layout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
{children}
</body>
</html>
);
}
Loading

0 comments on commit f6af7e6

Please sign in to comment.