33

having a problem with getting data back from database. I am trying my best to explain the problem.

1.If I leave "mode":"no-cors" inside the code below, then I can get data back from server with Postman, but not with from my own server. Thinking it has to be my client side error

  1. When I remove "mode":"no-cors" then I am getting 2 errors: -Fetch API cannot load http://localhost:3000/. Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response. -Uncaught (in promise) TypeError: Failed to fetch

Quick Browsing suggested to put in the "mode":"no-cors" which fixed this error, but it does not feel right thing to do.

So I thought maybe somebody has a suggestion how to approach this problem.

Really hope I was clear enough, but pretty sure I am not giving clear explanation here :S

function send(){
    var myVar = {"id" : 1};
    console.log("tuleb siia", document.getElementById('saada').value);
    fetch("http://localhost:3000", {
        method: "POST",
        headers: {
            "Access-Control-Allow-Origin": "*",
            "Content-Type": "text/plain"
        },//"mode" : "no-cors",
        body: JSON.stringify(myVar)
        //body: {"id" : document.getElementById('saada').value}
    }).then(function(muutuja){

        document.getElementById('väljund').innerHTML = JSON.stringify(muutuja);
    });
}
OFFLlNE
  • 557
  • 1
  • 5
  • 15
  • 1
    `mode: no-cors` would guarantee no access to response. Also, you're using fetch wrong ... in your code, the argument `muutuja` is a Response object, to get json, you'd need to `return muutuja.json()` and in the **next** then, the argument will be the data you want – Jaromanda X Mar 12 '17 at 23:32
  • 1
    simple answer with CORS ... the server needs to allow access to its resources, so the server needs to issue CORS headers as appropriate - so the `"Access-Control-Allow-Origin": "*"` in the request is pointless (and will trigger a preflight request to add to the complication) - if CORS were able to be "bypassed" by the client, then CORS would be 100% pointless – Jaromanda X Mar 12 '17 at 23:35
  • I will see if I manage to do fetch properly @JaromandaX doing this all locally Having that in my server's js code res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header('Access-Control-Allow-Headers', 'Content-Type'); – OFFLlNE Mar 12 '17 at 23:36
  • 1
    oh, so you do issue CORS response headers ... does your server handle the OPTIONS pre-flight that you trigger by adding a "non standard" header? I think all your problems will go away if you remove the access-control header from the **request** and **don't** add `mode: 'no-cors'` to the request – Jaromanda X Mar 12 '17 at 23:37
  • @JaromandaX IT worked!!! I did remove the access-control from the send() and also removed mode:'no-cors' Seems like this works well now – OFFLlNE Mar 12 '17 at 23:44

5 Answers5

19

Adding mode:'no-cors' to the request header guarantees that no response will be available in the response

Adding a "non standard" header, line 'access-control-allow-origin' will trigger a OPTIONS preflight request, which your server must handle correctly in order for the POST request to even be sent

You're also doing fetch wrong ... fetch returns a "promise" for a Response object which has promise creators for json, text, etc. depending on the content type...

In short, if your server side handles CORS correctly (which from your comment suggests it does) the following should work

function send(){
    var myVar = {"id" : 1};
    console.log("tuleb siia", document.getElementById('saada').value);
    fetch("http://localhost:3000", {
        method: "POST",
        headers: {
            "Content-Type": "text/plain"
        },
        body: JSON.stringify(myVar)
    }).then(function(response) {
        return response.json();
    }).then(function(muutuja){
        document.getElementById('väljund').innerHTML = JSON.stringify(muutuja);
    });
}

however, since your code isn't really interested in JSON (it stringifies the object after all) - it's simpler to do

function send(){
    var myVar = {"id" : 1};
    console.log("tuleb siia", document.getElementById('saada').value);
    fetch("http://localhost:3000", {
        method: "POST",
        headers: {
            "Content-Type": "text/plain"
        },
        body: JSON.stringify(myVar)
    }).then(function(response) {
        return response.text();
    }).then(function(muutuja){
        document.getElementById('väljund').innerHTML = muutuja;
    });
}
Jaromanda X
  • 47,382
  • 4
  • 58
  • 76
  • Thank you so much. Things started working in some direction now!! Maybe you could also help me out with my "db" response from server. I will describe the issue I am having in next comment – OFFLlNE Mar 12 '17 at 23:48
  • why not ask a new question? (after searching SO to see if there's already an answer :p ) – Jaromanda X Mar 12 '17 at 23:48
  • Alright, thank you very much. I will try to fiddle with the current thing a bit and then post a new question if still stuck. – OFFLlNE Mar 12 '17 at 23:51
6

In my case, the problem was the protocol. I was trying to call a script url with http instead of https.

IgniteCoders
  • 3,538
  • 3
  • 34
  • 55
4

See mozilla.org's write-up on how CORS works.

You'll need your server to send back the proper response headers, something like:

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization

Bear in mind you can use "*" for Access-Control-Allow-Origin that will only work if you're trying to pass Authentication data. In that case, you need to explicitly list the origin domains you want to allow. To allow multiple domains, see this post

Kevdog777
  • 810
  • 4
  • 17
  • 36
Dave Cole
  • 2,129
  • 1
  • 16
  • 22
0

you can use solutions without adding "Access-Control-Allow-Origin": "*", if your server is already using Proxy gateway this issue will not happen because the front and backend will be route in the same IP and port in client side but for development, you need one of this three solution if you don't need extra code 1- simulate the real environment by using a proxy server and configure the front and backend in the same port

2- if you using Chrome you can use the extension called Allow-Control-Allow-Origin: * it will help you to avoid this problem

3- you can use the code but some browsers versions may not support that so try to use one of the previous solutions

the best solution is using a proxy like ngnix its easy to configure and it will simulate the real situation of the production deployment

3alaa baiomy
  • 316
  • 3
  • 7
0

try this

 await fetch(url, {
      mode: 'no-cors'
 })
Smaillns
  • 1,330
  • 12
  • 19
  • 2
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – mufazmi May 19 '21 at 21:06
  • This does not provide an answer to the question. To critique or request clarification from an author, leave a comment below their post. - [From Review](/review/low-quality-posts/29011640) – m1k3y3 May 20 '21 at 08:41