File tree Expand file tree Collapse file tree 4 files changed +84
-0
lines changed Expand file tree Collapse file tree 4 files changed +84
-0
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ ' gitbook-v2 ' : minor
3
+ ---
4
+
5
+ Add route to revalidate cached data
Original file line number Diff line number Diff line change
1
+ import { type NextRequest , NextResponse } from 'next/server' ;
2
+
3
+ import { withVerifySignature } from '@v2/lib/routes' ;
4
+ import { revalidateTag } from 'next/cache' ;
5
+
6
+ interface JsonBody {
7
+ tags : string [ ] ;
8
+ }
9
+
10
+ /**
11
+ * Revalidate cached data based on tags.
12
+ * The body should be a JSON with { tags: string[] }
13
+ */
14
+ export async function POST ( req : NextRequest ) {
15
+ return withVerifySignature < JsonBody > ( req , async ( body ) => {
16
+ if ( ! body . tags || ! Array . isArray ( body . tags ) ) {
17
+ return NextResponse . json (
18
+ {
19
+ error : 'tags must be an array' ,
20
+ } ,
21
+ { status : 400 }
22
+ ) ;
23
+ }
24
+
25
+ body . tags . forEach ( ( tag ) => {
26
+ revalidateTag ( tag ) ;
27
+ } ) ;
28
+
29
+ return NextResponse . json ( {
30
+ success : true ,
31
+ } ) ;
32
+ } ) ;
33
+ }
Original file line number Diff line number Diff line change @@ -58,3 +58,8 @@ export const GITBOOK_INTEGRATIONS_HOST =
58
58
export const GITBOOK_IMAGE_RESIZE_URL = process . env . GITBOOK_IMAGE_RESIZE_URL ?? null ;
59
59
export const GITBOOK_IMAGE_RESIZE_SIGNING_KEY =
60
60
process . env . GITBOOK_IMAGE_RESIZE_SIGNING_KEY ?? null ;
61
+
62
+ /**
63
+ * Secret used to validate requests from the GitBook app.
64
+ */
65
+ export const GITBOOK_SECRET = process . env . GITBOOK_SECRET ?? null ;
Original file line number Diff line number Diff line change
1
+ import crypto from 'node:crypto' ;
2
+ import { NextResponse } from 'next/server' ;
3
+ import { GITBOOK_SECRET } from './env' ;
4
+
5
+ /**
6
+ * Verify the signature of the request and call the function with the body.
7
+ */
8
+ export async function withVerifySignature < T > (
9
+ request : Request ,
10
+ fn : ( body : T ) => Promise < NextResponse >
11
+ ) {
12
+ try {
13
+ const rawBody = await request . text ( ) ;
14
+ const body = JSON . parse ( rawBody ) as T ;
15
+
16
+ if ( GITBOOK_SECRET ) {
17
+ // Retrieve the signature header from the request
18
+ const incomingSignature = request . headers . get ( 'x-gitbook-signature' ) ;
19
+ if ( ! incomingSignature ) {
20
+ return NextResponse . json ( { error : 'Missing signature header' } , { status : 400 } ) ;
21
+ }
22
+
23
+ const computedSignature = crypto
24
+ . createHmac ( 'sha256' , GITBOOK_SECRET )
25
+ . update ( rawBody )
26
+ . digest ( 'hex' ) ;
27
+
28
+ // Compare incoming signature to computed signature
29
+ if ( incomingSignature !== computedSignature ) {
30
+ return NextResponse . json ( { error : 'Invalid signature' } , { status : 401 } ) ;
31
+ }
32
+ }
33
+
34
+ return await fn ( body ) ;
35
+ } catch ( _error ) {
36
+ return NextResponse . json (
37
+ { error : 'Invalid request or unable to parse JSON' } ,
38
+ { status : 400 }
39
+ ) ;
40
+ }
41
+ }
You can’t perform that action at this time.
0 commit comments