create Content Security Policy
Create a content security policy to secure your application. The default content security policy includes exclusions for cdn.shopify.com and a script nonce.
- Anchor to directivesdirectivesdirectivesRecord<string, string | boolean | string[]>Record<string, string | boolean | string[]>Default: {}Default: {}
Pass custom content security policy directives. This is important if you load content in your app from third-party domains.
- noncenoncestringstring
A randomly generated nonce string that should be passed to any custom
scriptelement- headerheaderstringstring
The content security policy header
- NonceProviderNonceProviderComponentType<{children: ReactNode}>ComponentType<{children: ReactNode}>
ContentSecurityPolicyContentSecurityPolicy
ContentSecurityPolicy
ContentSecurityPolicy
- nonce
A randomly generated nonce string that should be passed to any custom `script` element
string - header
The content security policy header
string - NonceProvider
ComponentType<{children: ReactNode}>
{
/** A randomly generated nonce string that should be passed to any custom `script` element */
nonce: string;
/** The content security policy header */
header: string;
NonceProvider: ComponentType<{children: ReactNode}>;
}Examples
import {RemixServer} from '@remix-run/react';
import isbot from 'isbot';
import {renderToReadableStream} from 'react-dom/server';
import {createContentSecurityPolicy} from '@shopify/hydrogen';
export default async function handleRequest(
request,
responseStatusCode,
responseHeaders,
remixContext,
) {
const {nonce, header, NonceProvider} = createContentSecurityPolicy({
// pass a custom directive to load content from a third party domain
styleSrc: [
"'self'",
'https://cdn.shopify.com',
'https://some-custom-css.cdn',
],
});
const body = await renderToReadableStream(
<NonceProvider>
<RemixServer context={remixContext} url={request.url} />
</NonceProvider>,
{
nonce,
signal: request.signal,
onError(error) {
// eslint-disable-next-line no-console
console.error(error);
responseStatusCode = 500;
},
},
);
if (isbot(request.headers.get('user-agent'))) {
await body.allReady;
}
responseHeaders.set('Content-Type', 'text/html');
responseHeaders.set('Content-Security-Policy', header);
return new Response(body, {
headers: responseHeaders,
status: responseStatusCode,
});
}
Examples
Example code
Description
I am the default example
JavaScript
import {RemixServer} from '@remix-run/react'; import isbot from 'isbot'; import {renderToReadableStream} from 'react-dom/server'; import {createContentSecurityPolicy} from '@shopify/hydrogen'; export default async function handleRequest( request, responseStatusCode, responseHeaders, remixContext, ) { const {nonce, header, NonceProvider} = createContentSecurityPolicy({ // pass a custom directive to load content from a third party domain styleSrc: [ "'self'", 'https://cdn.shopify.com', 'https://some-custom-css.cdn', ], }); const body = await renderToReadableStream( <NonceProvider> <RemixServer context={remixContext} url={request.url} /> </NonceProvider>, { nonce, signal: request.signal, onError(error) { // eslint-disable-next-line no-console console.error(error); responseStatusCode = 500; }, }, ); if (isbot(request.headers.get('user-agent'))) { await body.allReady; } responseHeaders.set('Content-Type', 'text/html'); responseHeaders.set('Content-Security-Policy', header); return new Response(body, { headers: responseHeaders, status: responseStatusCode, }); }TypeScript
import type {EntryContext} from '@shopify/remix-oxygen'; import {RemixServer} from '@remix-run/react'; import isbot from 'isbot'; import {renderToReadableStream} from 'react-dom/server'; import {createContentSecurityPolicy} from '@shopify/hydrogen'; export default async function handleRequest( request: Request, responseStatusCode: number, responseHeaders: Headers, remixContext: EntryContext, ) { const {nonce, header, NonceProvider} = createContentSecurityPolicy({ // pass a custom directive to load content from a third party domain styleSrc: [ "'self'", 'https://cdn.shopify.com', 'https://some-custom-css.cdn', ], }); const body = await renderToReadableStream( <NonceProvider> <RemixServer context={remixContext} url={request.url} /> </NonceProvider>, { nonce, signal: request.signal, onError(error) { // eslint-disable-next-line no-console console.error(error); responseStatusCode = 500; }, }, ); if (isbot(request.headers.get('user-agent'))) { await body.allReady; } responseHeaders.set('Content-Type', 'text/html'); responseHeaders.set('Content-Security-Policy', header); return new Response(body, { headers: responseHeaders, status: responseStatusCode, }); }
Was this page helpful?