-
Notifications
You must be signed in to change notification settings - Fork 464
Expand file tree
/
Copy pathentry.server.tsx
More file actions
126 lines (110 loc) · 4.08 KB
/
entry.server.tsx
File metadata and controls
126 lines (110 loc) · 4.08 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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
import crypto from 'node:crypto'
import { PassThrough } from 'node:stream'
import { contentSecurity } from '@nichtsam/helmet/content'
import { createReadableStreamFromReadable } from '@react-router/node'
import * as Sentry from '@sentry/react-router'
import { isbot } from 'isbot'
import { renderToPipeableStream } from 'react-dom/server'
import { type HandleDocumentRequestFunction, ServerRouter } from 'react-router'
import { getEnv, init } from './utils/env.server.ts'
import { getInstanceInfo } from './utils/litefs.server.ts'
import { NonceProvider } from './utils/nonce-provider.ts'
import { makeTimings } from './utils/timing.server.ts'
export const streamTimeout = 5000
init()
global.ENV = getEnv()
const MODE = process.env.NODE_ENV ?? 'development'
type DocRequestArgs = Parameters<HandleDocumentRequestFunction>
async function handleRequest(...args: DocRequestArgs) {
const [request, responseStatusCode, responseHeaders, reactRouterContext] =
args
const { currentInstance, primaryInstance } = await getInstanceInfo()
responseHeaders.set('fly-region', process.env.FLY_REGION ?? 'unknown')
responseHeaders.set('fly-app', process.env.FLY_APP_NAME ?? 'unknown')
responseHeaders.set('fly-primary-instance', primaryInstance)
responseHeaders.set('fly-instance', currentInstance)
if (process.env.NODE_ENV === 'production' && process.env.SENTRY_DSN) {
responseHeaders.append('Document-Policy', 'js-profiling')
}
const callbackName = isbot(request.headers.get('user-agent'))
? 'onAllReady'
: 'onShellReady'
const nonce = crypto.randomBytes(16).toString('hex')
return new Promise(async (resolve, reject) => {
let didError = false
// NOTE: this timing will only include things that are rendered in the shell
// and will not include suspended components and deferred loaders
const timings = makeTimings('render', 'renderToPipeableStream')
const { pipe, abort } = renderToPipeableStream(
<NonceProvider value={nonce}>
<ServerRouter
nonce={nonce}
context={reactRouterContext}
url={request.url}
/>
</NonceProvider>,
{
[callbackName]: () => {
const body = new PassThrough()
responseHeaders.set('Content-Type', 'text/html')
responseHeaders.append('Server-Timing', timings.toString())
contentSecurity(responseHeaders, {
crossOriginEmbedderPolicy: false,
contentSecurityPolicy: {
// NOTE: Remove reportOnly when you're ready to enforce this CSP
reportOnly: true,
directives: {
fetch: {
'connect-src': [
MODE === 'development' ? 'ws:' : undefined,
process.env.SENTRY_DSN ? '*.sentry.io' : undefined,
// Spotlight (SSE to the sidecar)
MODE === 'development'
? 'http://localhost:8969'
: undefined,
"'self'",
],
'font-src': ["'self'"],
'frame-src': ["'self'"],
'img-src': ["'self'", 'data:'],
'script-src': [
"'strict-dynamic'",
"'self'",
`'nonce-${nonce}'`,
],
'script-src-attr': [`'nonce-${nonce}'`],
},
},
},
})
resolve(
new Response(createReadableStreamFromReadable(body), {
headers: responseHeaders,
status: didError ? 500 : responseStatusCode,
}),
)
// this enables distributed tracing between client and server!
pipe(Sentry.getMetaTagTransformer(body))
},
onShellError: (err: unknown) => {
reject(err)
},
onError: () => {
didError = true
},
nonce,
},
)
setTimeout(abort, streamTimeout + 5000)
})
}
export async function handleDataRequest(response: Response) {
const { currentInstance, primaryInstance } = await getInstanceInfo()
response.headers.set('fly-region', process.env.FLY_REGION ?? 'unknown')
response.headers.set('fly-app', process.env.FLY_APP_NAME ?? 'unknown')
response.headers.set('fly-primary-instance', primaryInstance)
response.headers.set('fly-instance', currentInstance)
return response
}
export const handleError = Sentry.createSentryHandleError({ logErrors: true })
export default Sentry.wrapSentryHandleRequest(handleRequest)