111

I am sending POST request like this from browser:

fetch(serverEndpoint, {
    method: 'POST',
    mode: 'no-cors', // this is to prevent browser from sending 'OPTIONS' method request first
    redirect: 'follow',
    headers: new Headers({
            'Content-Type': 'text/plain',
            'X-My-Custom-Header': 'value-v',
            'Authorization': 'Bearer ' + token,
    }),
    body: companyName
})

By the time the request reaches my back-end it does not contain X-My-Custom-Header nor Authorization header.

My back-end is Google Cloud function for Firebase (basically just Node.js endpoint) that looks like this:

exports.createCompany = functions.https.onRequest((req, res) => {
    let headers = ['Headers: ']
    for (let header in req.headers) {
        headers.push(`${header} : ${req.headers[header]}`)
    }
    console.log(headers)
    ...
}

The console log of that Google Cloud for Firebase function does not contain any X-My-Custom-Header nor Authorization header.

What is wrong?


Edit 1

So using dev tools in Chrome a checked that neither X-My-Custom-Header nor Authorization header is send from the browser... The questions now are: Why? How do I fix it?


Edit 2

More information about my app: It's React app. I have disabled service worker. I have tried to create Request and specifically add headers using req.headers.append(). The headers still wouldn't send.

5
  • 1
    Is your browser actually sending the headers? Check your dev tools. Commented Aug 9, 2017 at 13:10
  • @JoeClay I am seasoned developer (mobile, backend) but rather new to web front-end development. Many tools are new for me - especially dev tools in brownser are not very good friend of mine yet. Can you suggest how to I check it on Chrome or Safari? Thanks Commented Aug 9, 2017 at 19:42
  • 2
    In Chrome, press F12 to open your dev tools, and then switch to the Network tab. When your application sends a HTTP request, it'll appear in the list, and you can click on it to view the headers/body of the request and response. See the docs for more info - learning how to use your browser's dev tools will help you loads if you're just starting out with web development :) Commented Aug 10, 2017 at 8:10
  • 1
    @JoeClay So the answer is no the browser does not send X-My-Custom-Header nor Authorization. Now the remaining questions are why? And how to fix it? Commented Aug 10, 2017 at 16:45
  • See stackoverflow.com/questions/42311018/… at Why does Fetch API Send the first PUT request as OPTIONS Commented Aug 12, 2017 at 18:55

5 Answers 5

181
+500

The same-origin policy restricts the kinds of requests that a Web page can send to resources from another origin.

In the no-cors mode, the browser is limited to sending “simple” requests — those with safelisted methods and safelisted headers only.

To send a cross-origin request with headers like Authorization and X-My-Custom-Header, you have to drop the no-cors mode and support preflight requests (OPTIONS).

The distinction between “simple” and “non-simple” requests is for historical reasons. Web pages could always perform some cross-origin requests through various means (such as creating and submitting a form), so when Web browsers introduced a principled means of sending cross-origin requests (cross-origin resource sharing, or CORS), it was decided that such “simple” requests could be exempt from the preflight OPTIONS check.

Sign up to request clarification or add additional context in comments.
60

Firstly : Use an object instead of new Headers(..):

fetch('www.example.net', {
  method: 'POST',
  headers: {
    'Content-Type': 'text/plain',
    'X-My-Custom-Header': 'value-v',
    'Authorization': 'Bearer ' + token,
  }
});

Secondly : Good to know, headers are lowercased by fetch!!

Thirdly : no-cors mode limits the use of headers to this white list :

  • Accept
  • Accept-Language
  • Content-Language
  • Content-Type and whose value is ( application/x-www-form-urlencoded, multipart/form-data, text/plain )

That's why only your Content-Type header is sent and not X-My-Custom-Header or Authorization.

6

Can you try this?

fetch(serverEndpoint, {  
  credentials: 'include'  
})

Ref. https://developers.google.com/web/updates/2015/03/introduction-to-fetch#sending_credentials_with_a_fetch_request

2

I also had this same issue. I resolved it by removing 'no-cors' from javascript and adding the following in server side spring boot.

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        protected void configure(HttpSecurity httpSecurity) throws Exception {
             .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

        }
    }
1

1st: when you call headers in your exports.createCompany function, you have let headers = ['Headers: '] with a capital H instead of lowercase h which might cause errors. you also have a comma after token in the headers which shouldn't be there.

2nd: everytime i have used fetch requests in react native, the header: doesn't need the new Headers on it.

try this:

fetch(serverEndpoint, {
    method: 'POST',
    mode: 'no-cors',
    redirect: 'follow',
    headers:{
      'Content-Type': 'text/plain',
      'X-My-Custom-Header': 'value-v',
      'Authorization': 'Bearer ' + token
    },
    body: companyName
})

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.