您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import type { NextRequest } from 'next/server'
  2. import { NextResponse } from 'next/server'
  3. const NECESSARY_DOMAIN = '*.sentry.io http://localhost:* http://127.0.0.1:* https://analytics.google.com googletagmanager.com *.googletagmanager.com https://www.google-analytics.com https://api.github.com'
  4. const wrapResponseWithXFrameOptions = (response: NextResponse, pathname: string) => {
  5. // prevent clickjacking: https://owasp.org/www-community/attacks/Clickjacking
  6. // Chatbot page should be allowed to be embedded in iframe. It's a feature
  7. if (process.env.NEXT_PUBLIC_ALLOW_EMBED !== 'true' && !pathname.startsWith('/chat') && !pathname.startsWith('/workflow') && !pathname.startsWith('/completion') && !pathname.startsWith('/webapp-signin'))
  8. response.headers.set('X-Frame-Options', 'DENY')
  9. return response
  10. }
  11. export function middleware(request: NextRequest) {
  12. const { pathname } = request.nextUrl
  13. const requestHeaders = new Headers(request.headers)
  14. const response = NextResponse.next({
  15. request: {
  16. headers: requestHeaders,
  17. },
  18. })
  19. const isWhiteListEnabled = !!process.env.NEXT_PUBLIC_CSP_WHITELIST && process.env.NODE_ENV === 'production'
  20. if (!isWhiteListEnabled)
  21. return wrapResponseWithXFrameOptions(response, pathname)
  22. const whiteList = `${process.env.NEXT_PUBLIC_CSP_WHITELIST} ${NECESSARY_DOMAIN}`
  23. const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
  24. const csp = `'nonce-${nonce}'`
  25. const scheme_source = 'data: mediastream: blob: filesystem:'
  26. const cspHeader = `
  27. default-src 'self' ${scheme_source} ${csp} ${whiteList};
  28. connect-src 'self' ${scheme_source} ${csp} ${whiteList};
  29. script-src 'self' ${scheme_source} ${csp} ${whiteList};
  30. style-src 'self' 'unsafe-inline' ${scheme_source} ${whiteList};
  31. worker-src 'self' ${scheme_source} ${csp} ${whiteList};
  32. media-src 'self' ${scheme_source} ${csp} ${whiteList};
  33. img-src * data: blob:;
  34. font-src 'self';
  35. object-src 'none';
  36. base-uri 'self';
  37. form-action 'self';
  38. upgrade-insecure-requests;
  39. `
  40. // Replace newline characters and spaces
  41. const contentSecurityPolicyHeaderValue = cspHeader
  42. .replace(/\s{2,}/g, ' ')
  43. .trim()
  44. requestHeaders.set('x-nonce', nonce)
  45. requestHeaders.set(
  46. 'Content-Security-Policy',
  47. contentSecurityPolicyHeaderValue,
  48. )
  49. response.headers.set(
  50. 'Content-Security-Policy',
  51. contentSecurityPolicyHeaderValue,
  52. )
  53. return wrapResponseWithXFrameOptions(response, pathname)
  54. }
  55. export const config = {
  56. matcher: [
  57. /*
  58. * Match all request paths except for the ones starting with:
  59. * - api (API routes)
  60. * - _next/static (static files)
  61. * - _next/image (image optimization files)
  62. * - favicon.ico (favicon file)
  63. */
  64. {
  65. // source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
  66. source: '/((?!_next/static|_next/image|favicon.ico).*)',
  67. // source: '/(.*)',
  68. // missing: [
  69. // { type: 'header', key: 'next-router-prefetch' },
  70. // { type: 'header', key: 'purpose', value: 'prefetch' },
  71. // ],
  72. },
  73. ],
  74. }