I am trying to post some json to a sharepoint url, as in this example. The example uses node, but I am trying to do it in the browser.
I tried it with fetch first:
fetch("https://outlook.office365.com/webhook/...",
{
method: 'POST',
headers: {
'Content-Type': 'application/json;'
},
body: JSON.stringify(this.groupCardBody()),
})
From that i got the error:
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'http://localhost:1234' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
But i don't have control over the response, and if i add mode: 'no-cors' into the fetch options as it suggests, it strips the content-type header and returns 415 Unsupported Media Type.
So i tried it with a simple xhttp request and that fails too as it does the preflight and doesn't get the right headers back:
let xhr = new XMLHttpRequest()
xhr.open("POST", "https://outlook.office365.com/webhook/...");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.send(JSON.stringify(this.groupCardBody()));
Response to preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
The request library used in the example was quite difficult to get working in the browser and by no means lightweight (added almost 2MB to my webpacked script), so any suggestions about how to get round this are welcome I am pretty stuck, all my searches turn up answers for fixing the server and i don't have that option.
UPDATE
As suggested in the accepted answer, I solved it by posting the json back to the server and making the post from there, got it working with something as simple as the following:
Client:
fetch("PostGroupCard?json="+
encodeURI(JSON.stringify(this.groupCardBody())),
{credentials: "same-origin"}
)
Server:
Function PostGroupCard(json As String)
Dim wr = WebRequest.Create("https://outlook.office365.com/webhook/...")
wr.ContentType = "application/json"
wr.Method = "POST"
Using sw = New StreamWriter(wr.GetRequestStream())
sw.Write(json)
sw.Flush()
sw.Close()
End Using
Dim r = wr.GetResponse()
Using sr = New StreamReader(r.GetResponseStream())
Dim result = sr.ReadToEnd()
End Using
End Sub
Most of this answer is taken from the comments.
For security reasons, you cannot make an XMLHTTPRequest unless you are on the same origin or CORS header from the other domain says you can. If this were possible, any site could preform malicious actions like hack you accounts.
Two alternatives to consider would be JSONP and having your server act as a proxy to access the other domain.
Related
I've been trying to send a JSON payload through a JS script but my webhooks seem unable to see the payload whatever I write.
Here is the code I put together from various online sources:
let xhr = new XMLHttpRequest();
xhr.open("POST","https://webhook.site/4530328b-fc68-404a-9427-3f2ccd853066/",true);
xhr.setRequestHeader("Content-Type", "application/json");
let data = JSON.stringify({'eventType' : 'test'});
xhr.send(data);
I'm not a JS developer but it seems to me that this should work. However every time I run this snippet the POST URL does not show anything back :/
Any idea why that is over here :) ?
Thank you for your time!
In your example, the webhook.site service you're attempting to connect to with your JavaScript isn't enabled (by default) with the proper CORS headers that modern browsers respect & enforce to improve user security. The developer console in your browser of choice should point this out to you; the error mine gave back was:
Access to XMLHttpRequest at 'https://webhook.site/5c7a5049-9c5e-4bf7-b1cf-0e05f6503bfa' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
As the error states, the requested resource doesn't respond with any valid Access-Control-Allow-Origin header, which will prevent the POST itself from being fully executed. In webhook.site, you can select the CORS Headers tickbox from the top of the user interface to enable the service to send the proper CORS headers to get this working.
let xhr = new XMLHttpRequest();
xhr.open("POST","https://webhook.site/5c7a5049-9c5e-4bf7-b1cf-0e05f6503bfa",true); // configuration interface at https://webhook.site/#!/5c7a5049-9c5e-4bf7-b1cf-0e05f6503bfa/e14fc471-4bc4-410f-b16a-0755a231fb12/1
xhr.setRequestHeader("Content-Type", "application/json");
let data = JSON.stringify({'eventType' : 'test'});
xhr.send(data);
I suggest you to use axios, it gonna be something like this and you will get the response from your post request
const response = await axios.post('https://webhook.site/4530328b-fc68-404a-9427-3f2ccd853066/', {'eventType' : 'test'});
I have a localhost Rest API POST query hosted using Docker at port 8501: http://localhost:8501/v1/models/model:predict. I have an HTML file which runs with a JavaScript script and it is hosted at http://127.0.0.1:8887/ using WebServer for Chrome. I am able to call global Rest API POST queries from my HTML-JS files and my local Rest API works fine from POSTMAN. But I am unable to call my API from my HTML-JS files.
Below is my JS file:
function foo() {
var myHeaders = new Headers();
myHeaders.append("Content-Type", "application/json");
myHeaders.append("Access-Control-Allow-Origin", "*");
myHeaders.append("Access-Control-Allow-Methods", "POST");
var raw = JSON.stringify({"instances":[[0]]});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("http://localhost:8501/v1/models/model:predict", requestOptions)
.then(response => console.log(response.text()))
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
I get the below error:
Access to fetch at
'http://localhost:8501/v1/models/model:predict' from origin
'http://127.0.0.1:8887' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. If an opaque response serves your needs, set the request's
mode to 'no-cors' to fetch the resource with CORS disabled.
Can anyone please help me?
You seem to have understood CORS slightly "backwards" -- the Access-Control-Allow-Origin and Access-Control-Allow-Methods headers are specified on HTTP responses, not requests. This obviously implies that it's the HTTP server that sets them, not the client.
It would make for a terrible cross site security model if a script of arbitrary origin could effectively dictate to the HTTP server what kind of requests and from which origins the latter must accept.
It's the HTTP service that ultimately controls access by specifying appropriate headers in the responses it serves, and the user agent validates the cross origin request where it refuses to proceed if the server didn't indicate it allows requests from the different origin the script was served from -- the response will be discarded and an error will be thrown.
In short, you need to add the headers to the responses your REST service at localhost:8501 generates, instead of specifying them for requests your client side script creates where they don't do anything.
Your server is missing header Access-Control-Allow-Origin in response, as it is responsible what to allow or not. See https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I am trying to display a result from a rest API GET request, for example, "http://ifconfig.co/ip/" on my page. However, I am running into many different errors, and just cannot seem to get it down.
Her is what I have so far:
var req = new XMLHttpRequest();
req.open('GET', 'https://ifconfig.co/ip', true);
req.withCredentials = false;
req.setRequestHeader( 'Access-Control-Allow-Origin', '*' );
req.send();
document.write(req);
document.write(req.responseText);
document.write(req.responseXML);
In the javascript console it says "XMLHttpRequest cannot load https://ifconfig.co/ip. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource."
I am very new to javascript, can anyone point me in the right direction?
The No Access-Control-Allow-Origin message means that the server is configured not to accept requests from the client's domain. Here's a great article on MDN https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
I have a issue by adding some HTTP header key value to a http.post. It should be very simple but I am not getting correctly set. We are using on server side a spring-boot and on client side angular framework.
Our backend request the following header values:
'Content-Type' = 'application/json'
'X-Requested-With' = 'XMLHttpRequest'
'Cache-Control' = 'no-cache'
In angular, I create a header, this header I add a RequestOptions and add this options to the post request.
See code below:
.....
let myHead = new Headers();
myHead.append('Content-Type', 'application/json');
myHead.append('X-Requested-With', 'XMLHttpRequest');
myHead.append('Cache-Control', 'no-cache');
const options = new RequestOptions({ headers: myHead });
return this.http.post(ServerUrl,data, options).map((response: Response) => {..//do Something...}
...
The problem is, if I am checking the post request, I see that the header is not correctly set.
As you can see above it is not correctly set as a key value as I am expecting!?
If I do this with a tool e.g. postman plugin you see how it should be done corretly:
POST /ias-vwa/api/auth/login HTTP/1.1
Host: de00-fm26-l1:9090
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Cache-Control: no-cache
Postman-Token: c9bc0404-bc1e-57eb-fca4-07bba9ee6d93
I tried a lot of different options to set the header but I was always ending up that it will be always set in one line like this:
Access-Control-Request-Headers:access-control-allow-origin,cache-control,content-type,x-requested-with
The error I get on the browser:
XMLHttpRequest cannot load http://t00:9090/ias-vwa/api/auth/login. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 401.
Can any body give me a hint on that?
You are trying to POST to different domain from yours (your app live), and you're running on CORS issue.
You need to add Access-Control-Allow-Origin as a header in your response.
Access-Control-Allow-Origin: *
Okay I solved this issue.
As mention in this article and from Yordan Nikolov it's a CORS issue
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
If in some circumstances (as described in the article) the browser will send a Preflight-Request. In this request the custom value will be only named as in Access-Control-Request-Headers. This request will be HTTP request by the OPTIONS method. The server in our case a spring-boot need to implement a filter to filter this request and evaluate this cutsom header to be allowed. After the preflight request has be responed with a HTTP 200 the client will send the actually request with including the custom headers. This CORS issues is important if a request comes from a other domain.
So, the setting of the client side (angular2) will be set correctly.
Hope it helps anybody
Consider the very simple example of using XMLHttpRequest.
The following posts properly ( you can see it in the network tab or by directing your browser to http://requestb.in/yckncpyc) although it prints a warning to the console
XMLHttpRequest cannot load http://requestb.in/yckncpyc. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
const method = "POST"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
Sure. I get that. What I don't get is why merely changing the verb used to a PUT results in something completely different. The request sent is an OPTIONS preflight request and prints
XMLHttpRequest cannot load http://requestb.in/yckncpyc. Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin 'null' is therefore not allowed access.
const method = "PUT"
const req = new XMLHttpRequest()
req.open(method, 'http://requestb.in/yckncpyc')
req.send("foobar")
console.log("sent")
req.addEventListener('load', function() { console.log(req.status, req.response) })
Why does the browser* treat these differently? It seems like something that would be done for security but that really makes no sense since an attacker can always use a POST instead of a PUT.
So what is the logic here?
Tried this in Chrome 52, Safari 9.1.2
GET, HEAD, and POST requests (with a couple other restrictions) can be made cross-origin with no additional communication. The responses cannot be examined, but the requests are allowed.
Anything else requires a preflight request to check the headers from the target site to see whether the request would be allowed.
The reason for such a setup is that GET, HEAD, and POST were historically allowed from browsers as a natural part of HTML semantics. Tags for scripts and CSS and images do GET requests, and forms do POSTs. When the CORS stuff was introduced, therefore, those were allowed under the assumption that sites were no more vulnerable to simple requests like that in an XHR world then they were in the simpler non-XHR world.
So simple requests are allowed, and the browser looks at the response headers to decide whether the requesting code in the cross-origin page should be allowed to see the response content. For other requests, the browser first sends an OPTIONS request to check the CORS response headers. Only if that looks OK (that is, if the response headers contain the appropriate "yes that's OK" headers) will the XHR be allowed to proceed.