-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathproxy.ts
More file actions
79 lines (67 loc) · 2.37 KB
/
proxy.ts
File metadata and controls
79 lines (67 loc) · 2.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/**
* Next.js proxy/middleware: validates Appwrite session on API routes,
* injects x-appwrite-session header for downstream route handlers.
*
* Public routes pass through without auth.
* When APPWRITE_PROJECT_ID is not set, all requests pass through (demo mode).
*/
import { NextRequest, NextResponse } from 'next/server'
const PUBLIC_API_PREFIXES = [
'/api/markets',
'/api/btc-price',
'/api/python-health',
'/api/auth/',
'/api/orderbook',
'/api/market-quote',
'/api/settings/',
]
export function proxy(req: NextRequest) {
const { pathname } = req.nextUrl
// Basic Auth — protects all routes when BASIC_AUTH_PASSWORD is set
const basicAuthPw = process.env.BASIC_AUTH_PASSWORD
if (basicAuthPw) {
const auth = req.headers.get('authorization')
let authed = false
if (auth?.startsWith('Basic ')) {
const decoded = Buffer.from(auth.slice(6), 'base64').toString('utf-8')
const colonIdx = decoded.indexOf(':')
const pass = colonIdx >= 0 ? decoded.slice(colonIdx + 1) : decoded
authed = pass === basicAuthPw
}
if (!authed) {
return new NextResponse('Unauthorized', {
status: 401,
headers: { 'WWW-Authenticate': 'Basic realm="Sentient"' },
})
}
}
// Only guard /api/ routes for Appwrite auth
if (!pathname.startsWith('/api/')) {
return NextResponse.next()
}
// Demo mode: Appwrite not configured — skip auth entirely
if (!process.env.APPWRITE_PROJECT_ID) {
return NextResponse.next()
}
// Public routes pass through
if (PUBLIC_API_PREFIXES.some(p => pathname.startsWith(p))) {
return NextResponse.next()
}
// Extract session from cookie or Authorization header
const sessionCookie = req.cookies.get('appwrite-session')?.value
const authHeader = req.headers.get('authorization')
const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null
const token = sessionCookie ?? bearerToken
if (!token) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
// Forward session token to route handler via header
const headers = new Headers(req.headers)
headers.set('x-appwrite-session', token)
return NextResponse.next({ request: { headers } })
}
export const config = {
matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}
// Alias so Next.js picks this up as middleware
export { proxy as middleware }