How to set headers dynamically

My site is https://shoplook.netlify.app/ and I want to set dynamic headers for each request.

If a request comes from abc.com then my CSP headers should look like

Content-Security-Policy: frame-ancestors https://abc.com https://admin.abc.com

With the _headers file, I could only manage to set static headers that dont change for each requests. Can somebody help me on how to get this?

Hey @frangout

Suggest having a look at this thread which deals with exactly the same thing you are looking to achieve with Shopify

@coelmay I went through the thread and it does not mention how to do it with Netlify. Could you please show an example on how to do this?

The method you take will depend in part on what information is provided by Shopify as either a header, or payload.

As I don’t know what information Shopify provides in such as request, I cannot provide an example. If you can provide the information Shopify sends in a request, I could potentially provide an example.

@coelmay Shopify requires you to embed your netlify app in an iframe inside their site and that iframe URL src (which is a netlify app) requires to have the parent windows domain as its CSP header

@coelmay The question is how do I use _headers file or functions to set dynamic CSP headers.

I updated my answer with the relevant changes. The main difference being Netlify doesn’t use await getAssetFromKV(event, options) they have their own function for getting the page.

@philnetlify1 I am still confused about this. From what I know, functions are just cloud API that I could call from a web interface right? How could I use this to set req/res headers? And _headers just allow static headers to be set.

@frangout @srameshr @philnetlify1

A basic return of a Netlify Function is

return {
  statusCode: 200,
  body: "Body text"
}

If you wished to set a CSP headers as well, you add in

headers: {
  "Content-Security-Policy": "..." 
}

In the following (basic) example, the script is blocked from loading because of the CSP

exports.handler = async () => {
  return {
    statusCode: 200,
    headers: {
      "Content-Security-Policy": "script-src 'self'",
      "Content-Type": "text/html",
    },
    body: `<!DOCTYPE html>
    <html lang="en">
      <head>
        <title>No script will run</title>
        <script src="https://unpkg.com/jquery"></script>
      </head>
      <body>
        <h1>This is served from a function.</h1>
        <p>But the script won't load because of the CSP.</p>
      </body>
    </html>`,
  };
};

If you remove the CSP header, the page and the script load fine.

1 Like

@coelmay I get this. i have actually created csp.js file inside my apps root-folder/netlify/functions/csp.js but this function never get called when the first request is made to the app. After I set this, the CSP headers (https://securityheaders.com/) are always empty.

Functions don’t get called automatically unless it is a function triggered on an event. You need to explicitly call the function.

[quote=β€œcoelmay, post:9, topic:52126”]

@coelmay @philnetlify1

Still nothing. I have created app-root-folder/netlify/functions/deploy-succeeded.js

exports.handler = async (request) => {
  return {
    headers: {
      "Content-Security-Policy": "frame-ancestors https://*.myshopify.com https://admin.shopify.com",
    },
  };
};

Now, after its deployed, I visit https://securityheaders.com/ and put it my site domain to find still there are no CSP headers set

That’s not going to add the CSP header to the front end app.

The basic example I showed previously needs calling directly. For example, if the function is called my-function.js you would need to browse to (or use fetch, etc.) directly you would need to browse to https://mysite.netlify.app/.netlify/functions/my-function at which point the CSP and the content (the body) is returned.

This is not going to add a CSP header to the front-end app.

@coelmay Ok, then adding dynamic headers to the front-end app is what i need. Do you know how to achieve this with Netlfiy?_headers files allows me to add static headers but not dynamic ones. As i was saying earlier functions are an alternate to self hosted API server and has nothing to do with app headers.

As mentioned in the Static Routing Overview

To dynamically affect traffic on your site, you can use Netlify Edge Handlers to run custom JavaScript from CDN edge nodes. Edge Handlers can act as HTTP filters for your incoming traffic and give you full control to manipulate HTTP requests and responses.

Trying to do that. I have created two file

  1. root-folder/netlify/edge-handlers/csp.js
export function onRequest(event) {
  console.log(`Logging from code ${event}`);
}
  1. netlify.toml
[[edge_handlers]]
  path = "/*"
  handler = "csp"

Now, when I try to build it, the build fails with the following errors.

2:06:05 PM: ​
2:06:05 PM: ────────────────────────────────────────────────────────────────
2:06:05 PM:   Plugin "@netlify/plugin-edge-handlers" internal error         
2:06:05 PM: ────────────────────────────────────────────────────────────────
2:06:05 PM: ​
2:06:05 PM:   Error message
2:06:05 PM:   Error: Invalid status: 403
2:06:05 PM: ​
2:06:05 PM:   Plugin details
2:06:05 PM:   Package:        @netlify/plugin-edge-handlers
2:06:05 PM:   Version:        3.0.6
2:06:05 PM:   Repository:     git+https://github.com/netlify/netlify-plugin-edge-handlers.git
2:06:05 PM:   npm link:       https://www.npmjs.com/package/@netlify/plugin-edge-handlers
2:06:05 PM:   Report issues:  https://github.com/netlify/netlify-plugin-edge-handlers/issues
2:06:05 PM: ​
2:06:05 PM:   Error location
2:06:05 PM:   In "onBuild" event in "@netlify/plugin-edge-handlers" from core
2:06:05 PM:       at uploadBundle (file:///opt/buildhome/node-deps/node_modules/@netlify/plugin-edge-handlers/src/upload.js:34:11)
2:06:05 PM:       at processTicksAndRejections (node:internal/process/task_queues:96:5)
2:06:05 PM:       at async publishBundle (file:///opt/buildhome/node-deps/node_modules/@netlify/plugin-edge-handlers/src/lib.js:246:22)
2:06:05 PM:       at async onBuild (file:///opt/buildhome/node-deps/node_modules/@netlify/plugin-edge-handlers/src/index.js:25:20)
2:06:05 PM:       at async Object.run (file:///opt/buildhome/node-deps/node_modules/@netlify/build/src/plugins/child/run.js:21:3)
2:06:05 PM:       at async handleEvent (file:///opt/buildhome/node-deps/node_modules/@netlify/build/src/plugins/child/main.js:41:38)
2:06:05 PM:       at async process.<anonymous> (file:///opt/buildhome/node-deps/node_modules/@netlify/build/src/plugins/ipc.js:112:16)

Edge handlers are in beta, not available for general use.

As mentioned in the Edge Handlers overview

To get started using Edge Handlers, visit our sign-up form to request an early access invitation. Go to our Forums to join the conversation about Edge Handlers.

Ok, I have applied for it. Il go with regular EBS hosting if this does not work out. thank you for taking the time.

A side note, the beta has been closed and we’re not accepting new participants right now.

1 Like