简体   繁体   中英

ReactJS http-proxy-middleware request header not set properly

TL;DR: How to actually change a request header in http-proxy-middleware?

To get around some CORS errors I set up a local proxy using the http-proxy-middleware module. In addition to setting the mode of my request to "no-cors" I need to change an additional header: "Content-Type". However, this seems to be not working. In fact, I cannot even change the response headers on a redirected (through my proxy) request. For local requests (fetching pages etc) I am able to change the response headers but even then I am unable to change the request headers.

This is my setupProxy.js:

const { createProxyMiddleware } = require("http-proxy-middleware");

module.exports = function (app) {
  app.use((req, res, next) => {
    req.header("Content-Type", "application/json");
    res.header("Access-Control-Allow-Origin", "*");
    next();
  });

  function onProxyReq(proxyReq, req, res) {
    console.log("test 1");
    proxyReq.setHeader("Content-Type", "application/json");
    req.header("Content-Type", "application/json");
  }

  app.use(
    "/api",
    createProxyMiddleware({
      target: "https://my-domain.com/",
      changeOrigin: true,
      onProxyReg: { onProxyReq },
      // secure: true,
      // on: {
      //   proxyReq: requestInterceptor(async (buffer, proxyReq, req, res) => {
      //     console.log("test 2");
      //   }),
      // },
      logger: console,
    })
  );
};

And this is the code that sends the request:

try {
  let requestOptions: RequestInit = {
    method: "POST",
    mode: "no-cors",
    headers: {
      accept: "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      email: { username },
      password: { password },
    }),
  };

  fetch("https://localhost:3000/api/path/to/login/api", requestOptions)
    .then(async function (response) {
      console.log(response);
      if (!response.ok) {
        setError("Error code: " + response.status.toString());
      }
      return response.json();
    })
    .then(function (response) {
      console.log(response);
    });
} catch (e) {
  console.log(e);
}

I'm getting an error back from the API itself (the CORS avoidance is working):

Content type 'text/plain;charset=UTF-8' not supported

And indeed, when I use the Chrome inspector to look at the request, the request header is set to "text/plain;charset=UTF-8". I tried setting the response header content type to "text/plain" but even that remains untouched. But how can this be after routing the request through my proxy?

EDIT: Ok so I found out part of the problem. Setting the mode to "no-cors" in my fetch request alters the headers. But this still doesn't explain why my proxy can't edit the request headers. When I remove the "no-cors" mode but copy the headers it produced, the server is giving me error 400 (bad request). This means it is not receiving the same request as before, but this baffles me since I copied all the headers manually.

EDIT2: Actually, I found out that when I remove mode: "no-cors" and set the "Sec-Fetch-Mode" header to "no-cors" manually, it is still set to "cors" in the actual request!

EDIT3: I tried sending my request through ReqBin and it works there:). So at least we know my request is correct.

I found out that changing the "content-type" header in cors mode is simply not allowed. The solution is to first send a preflight request with the options. When this has been accepted, you can send the actual request.

You can send the request through ReqBin, it will take the necessary steps to complete the request succesfully. It will even generate code to reproduce the request for you.

var url = "https://thedomain.com/path/to/api";

var xhr = new XMLHttpRequest();
xhr.open("POST", url);

xhr.setRequestHeader("Content-Type", "application/json");

xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    console.log(xhr.status);
    console.log(xhr.responseText);
  }
};

var data_ = '{"email": "*************", "password": "******"}';

xhr.send(data_);

And this works: :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM