13

Is it possible to add a custom HTTP response header to the development server that runs with ng serve? I'd like to add this custom header specially in the response of the main html file request, although it'd fine if it was added for every resource (js files, etc.).

I found these two recent Angular issues:

But it's still unclear to me if it's even possible to do it, and if it's possible how to accomplish it.

I have added a proxy.config.js file (referenced from angular.json, section projects -> my-app -> architect -> serve -> options -> proxyConfig) and tried several configs, like the following one, with no luck:

module.exports = {
    "/": {
        'headers': {
            'X-Custom-Foo': 'bar'
        },
        onProxyRes: (proxyRes, req, res) => {
            proxyRes.headers['x-added'] = 'foobar';
        }
    },
    'headers': {
        'X-Custom-Foo': 'bar'
    },
    onProxyRes: (proxyRes, req, res) => {
        proxyRes.headers['x-added'] = 'foobar';
    }
};

Is it possible to do so without having to use a third-party server?

7
  • What do you mean if you can? a header can be anything you want, the important part is how you handle and use it on the server side. Commented Dec 10, 2019 at 11:37
  • I'm not sure why you expected setting the headers key to have that effect, following the docs from Angular via Webpack to NPM doesn't suggest that option would do anything. Commented Dec 10, 2019 at 11:41
  • @Bargros I'm not talking about HTTP request headers. I'm talking about HTTP response headers. I want the angular dev server to send a custom header to me. Commented Dec 10, 2019 at 11:44
  • @jonrsharpe I'm not only setting headers (a desperate try), I'm also setting onProxyRes which should work. Any clue what is the right way to accomplish it? Thanks! Commented Dec 10, 2019 at 11:49
  • Have you done any debugging - does that function get called for the requests you're trying to add headers to? I don't think the proxy is used for the actual assets, the idea is to use it for e.g. backend API calls (and it isn't designed for production use either). I'd recommend giving more context on why you're trying to set these headers. Commented Dec 10, 2019 at 11:55

4 Answers 4

19

The solution through the proxy configuration didn't work for me (Angular 12). Turns out however that headers can be specified under the options for the @angular-devkit/build-angular:dev-server in your angular.json file, like so:

{
    ...
    "serve": {
        "builder": "@angular-devkit/build-angular:dev-server",
        "options": {
            "browserTarget": "project:build",
            "headers": {
                "Referrer-Policy": "no-referrer-when-downgrade"
            }
        }
    }
    ...
}
Sign up to request clarification or add additional context in comments.

6 Comments

i am using angular 7. For me too proxy is not working. I tried adding header in angular.json file at your specified location but it gives me error saying extra attributes are not allowed. Any suggestion?
the excat words of the error is Schema validation failed with the following errors: Data path "" should NOT have additional properties(headers).
Well my solution is for Angular 12 and beyond, so for Angular 7 you should probably use any of the older responses to this question.
well, nothing seemed working. I finally resorted to tomcat valve a webserver level change.
awesome works perfectly on Angular 12
|
12

Assuming you're trying to simulate the production environment setting the same response header values: you could use bypass in the proxy configuration instead of onProxyRes. You are not trying to redirect the calls to another server (target value) and handle the answer in onProxyRes, so avoid using it and try with bypass. It should work fine ;)

The proxy.conf.js would look something like this:

module.exports = {
  "/": {
    "secure": false,
    "bypass": (req, res, proxyOptions) => {
      res.setHeader('X-Header-Test', 'bacon');
    }
  }
};

8 Comments

OMG, it works! Thanks a lot, man. It'd have never occurred to me to do the trick with the bypass function. Awesome 😀
I used this but it seems to be working only for 1st call ,for other request calls it doesn't work.
@NamdeoKarande Try changing the path from / to *, it should be applied to any call instead of just the the first one.
I spent quite a while on this with angular 8 -- I could not get it to work. But also, my proxy config is more complex, with more routes. I need ng-serve to insert the headers for static content but continue to pass some routes to my backend. I gave up.
With the forceful requirement to add specific headers to server response in order to get SharedArrayBuffer working makes this solution even more useful in 2021 onwards. Saved me! Now developers need to, on their local machines, at localhost, 1) enable https 2) add custom header responses, all BEFORE they can even use ShareArrayBuffer in 2021, on their LOCAL machines. Woow!
|
2

noga's answer is correct for what the proxy.conf.js needs to look like. In Angular versions 8+ (I'm guessing because of the stabilization of the new builder API and updates to webpack) more needs to be done.

This is all built on webpack-dev-server and http-proxy-middleware, and if you check out the info on webpack's site https://webpack.js.org/configuration/dev-server/#devserverproxy it says:

Note that requests to root won't be proxied by default. To enable root proxying, the devServer.index option should be specified as a falsy value

Unfortunately, ng serve does not expose this property directly and it is a sibling property of proxy which receives the output of proxy.conf.js. You can either make your own builder or you can dig deep into node_modules > @angular-devkit > build-angular > src > dev-server > index.js and insert webpackDevServerConfig.index = ''; after webpackDevServerConfig is defined.

That works for me running Angular 9.

UPDATE: Angular 11

A commenter noted that this approach doesn't work for Angular 11. Now that I have bit the bullet and upgraded, I have a working solution.

The principle is still the same: the configuration of the dev server needs to have the index property set to the empty string.

After config is defined on line 87 of the same file as above, insert config.devServer.index = "".

UPDATE: Angular 15+ using a builder

The builder below takes care of it as part of the build process so you don't have to go back through and manually change files in node_modules. Note: this is only the builder; you still have to go through the process of hooking this into your build process, but the Angular documentation does a decent job of running through this.

https://angular.io/guide/cli-builder#builder-input

const architect = require('@angular-devkit/architect');
const devServer = require('@angular-devkit/build-angular/src/builders/dev-server');

function myBuilder(options, context) {
    const transforms = {
        webpackConfiguration: (webpackConfig) => {
            const newConfig = {...webpackConfig};
            newConfig.devServer.devMiddleware.index = "";
            return newConfig
        }
    }
    return devServer.executeDevServer(options, context, transforms)
}

exports.default = architect.createBuilder(myBuilder)```

2 Comments

This did not work for me in Angular 11. webpackDevServerConfig does not even exist (its been renamed, and using the renamed version didn't work either).
Thanks for pointing that out! I updated my answer to reflect how to do it in Angular 11
1

In Angular 11, the above solutions do not work.

Since the context above is Development Server (which is my use case), what I ended up doing was simply start up Chrome by disabling CROS checking.

The benefits of this approach are: (i) avoid Angular or Node changes breaking you (ii) no changes needed to get local dev on different ports to work.

For example, on a Mac:

open -n -a /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --args --user-data-dir="/tmp/chrome_dev_test" --disable-web-security

Some more information below:

https://alfilatov.com/posts/run-chrome-without-cors/

https://medium.com/@siddhartha.ng/disable-cross-origin-on-chrome-for-localhost-c644b131db19

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.