Post request works in postman but not in javascript fetch function - javascript

I thought I had solved this issue before and was able to make succesful post request to my local hosted apache server with fetch, but today I tried to make a post and I've gotten 'cors preflight request fail' error again. I'm not sure why it was working before and why it's suddenly not working again.
this is my php file headers which worked 3 days ago -
header('Access-Control-Allow-Origin: *');
header('Content-Type: application/json');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Headers: Access-Control-Allow-Headers,Content-Type,Access-Control-Allow-Methods,
Authorization, X-Requested-With');
and this is the fetch request I'm using on it -
fetch("http://menu.com/menu/api/post/create.php", {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
'title' : 'qweqweqw',
'body' : '1111w',
'author' : '2222r',
'category_id' : '2'
})
})
.then( (response) => {
console.log(response);
});
here is the Postman code that is working :
POST /menu/api/post/create.php HTTP/1.1
Host: menu.com
Content-Type: application/json
cache-control: no-cache
Postman-Token: 83a8e0d1-f45a-4184-92f6-f0be2f8fcf5f
{
"title" : "new new title",
"body" : "new neqwsadasssssssssseqweqwew jew",
"author" : "new newzxxxxxxxxxxxxwq author",
"category_id" : "1"
}------WebKitFormBoundary7MA4YWxkTrZu0gW--
I'd appreciate any help with this.
edit-
These are the cors errors :
Access to fetch at 'http://menu.com/menu/api/post/create.php' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
In my apache server error log I get this ' PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column 'category_id' at row 1 in /home/orphe$' But I'm not sure why it's getting this for category_id since I copy/pasted the working request from postman and it still doesn't work.

There's a preflight request (with OPTIONS), but the server doesn't return HTTP 200 OK.
Try adding the following to create.php:
header("HTTP/1.1 200 OK");
If this doesn't work please also include the request and response headers.

Changing my fetch requests headers to headers: new Headers() fixed everything.

Related

React JS - CORS Missing Allow Header when sending POST request

I have some problems with sending a POST request to my REST-API.
The problem is, when I send it from a react application, it shows me this error in the debug console of firefox.
The funny thing is, that it works perfectly fine when sending the request with postman.
This is the code i use to make the request:
let apiURL = API_URL_BASE + "/api/authenticate"
let requestBody = JSON.stringify(
{
"username": this.getEnteredLoginUsername(),
"password": this.getEnteredLoginPassword()
}
);
let headerData = new Headers();
headerData.append('Accept', '*');
headerData.append("Access-Control-Allow", "*");
headerData.append('Content-Type', 'application/json');
headerData.append('Access-Control-Allow-Origin', '*');
headerData.append("Access-Control-Allow-Methods", "GET,HEAD,OPTIONS,POST,PUT");
headerData.append("Access-Control-Allow-Headers", "*");
let requestOptions = {
method: 'POST',
mode: 'cors',
redirect: 'follow',
body: requestBody,
headers: headerData
}
this.setState({loadingData: true});
fetch(apiURL, requestOptions).then( response => {
let responseStatus = response.status;
response.json().then( responseJSON => {
});
});
I hope someone can help me with this.
This is the error shown by firefox console: Image
You do seem to have a correct request header from the client-side, i.e the browser, but your server that is hosting the API must also send a response to the client back indicating that it allows cross-origin requests, Otherwise browser would not proceed ahead with your request. Setting cors headers from the server would depend on what framework you're using for the backend. In fact you need to add those cors header you've added here to the server code.
A sample response header would look like this :
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: * (Note: * means this will allow all domains to request to your server)
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml
For express, you can follow this link.
More on CORS here

Angular 7 : Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested

I have to implement an angular application with CURD operations. API is already hosted IN AWS, Which is working fine with Postman.
But my angular application getting
Access to XMLHttpRequest at 'https://acp56df5alc.execute-api.us-east-1.amazonaws.com/ams/getmember' from origin 'http://localhost:4200' 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.
My code is like below,
http_GET(actionUrl: string): Observable<any> {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
'key': 'x-api-key',
'value': 'NNctr6Tjrw9794gFXf3fi6zWBZ78j6Gv3UCb3y0x',
})
};
return this.http.get<any>(this.baseUrl + actionUrl, httpOptions).pipe(
(response => {
return response;
}));
}
I have tried hard to solve this.But need some help
I had the same cors issue and tried all the suggested ways of setting Access-Control-Allow-Origin * without success.
Later I found two issues:
The data format I sent via POST request was not properly formatted.
The server could not handle empty parameters received from the post request.
Original request:
return this.http.post(API_URL + 'customer/login',
{email: email, password: password},{ headers: headers}
)
Worked after i wrapped the post data using JSON.stringify()
return this.http.post(API_URL + 'customer/login',
JSON.stringify({email: email, password: password}),{ headers: headers}
)
All/Most of these headers need to be defined on the server-side (whatever hosts the API on AWS)... not client side.
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
'Access-Control-Allow-Headers': 'Content-Type',
'Access-Control-Allow-Methods': 'GET,PUT,POST,DELETE',
'key': 'x-api-key',
'value': 'NNctr6Tjrw9794gFXf3fi6zWBZ78j6Gv3UCb3y0x',
...
The most likely reason that postman works is that it directly sends a GET request. what you are sending is a complex request which is called 'pre-flight' and which causes an 'OPTIONS' request to be sent before the actual GET. this is not allowed by the remote side.
That's a common CORS problem that (if you're using asp .net core on backend) can be solved enabling CORS following this thread

CORS and HTTP authentication

I'm trying make some ajax queries from domain A to domain B which is behind HTTP basic auth
Here is my Jquery (1.9.1) ajax call
jQuery.ajax({
method : "POST",
data: s,
withCredentials: true,
headers: {
"Authorization" : "Basic " + btoa('user:pass')
},
url: "http://domainB/script.php",
success: function(data){
console.log(data);
}
});
And script.php
<?php
header('Access-Control-Allow-Origin: http://domainA');
header('Access-Control-Allow-Methods: POST');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Authorization, Content-Type');
header('Content-Type: application/json');
/**
* Some stuff here
*/
echo json_encode( $json_response );
For some reason I ignore, I got this error in javascript console
Access to XMLHttpRequest at 'http://domainB/script.php' from origin 'http://domainA' 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
I don't understand what the error is, Access-Control-Allow-Origin is set...
I tried many solutions found a little bit everywhere but without success.. May someone have a solution ?
Thanks

Not Receiving Set-Cookie Header with axios post request

I have a PHP Script which successfully returns some simple Headers as well as a set-cookie header if called directly in the browser (or by postman). I can read the response-headers like that from chrome devTools. But as soon as I call it by Axios, the set-cookie header doesn't show up and there's no cookie saved in the browser.
I tried diffrent things like changing the response-headers server-side and using "withCredentials: true" with axios, but nothing worked. I don't even get an error or any cors-related problems.
PHP:
header("Access-Control-Allow-Origin: http://localhost:8080");
header("Content-Type: application/json; charset=UTF-8");
header("Access-Control-Allow-Methods: POST, GET");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With");
header("Access-Control-Max-Age: 99999999");
setcookie("TestCookie", "Testing", time() + 3600, "/", "localhost", 0);
die();
JS:
Vue.prototype.$http = axios.create({
baseURL: XYZ,
withCredentials: true
})
So my first question is why does the header appear when calling the php script directly? And how can I archive to get the header through axios too?
probably cookie is 'httpOnly', which means client side javascript can not read it.
Therefore it is not showing in chrome cookie section.
test the same request in mozilla, header will show up.
This may not apply to your situation, but I had the same problem using axios in this standalone nodejs script.
const config = {
url: 'https://remote.url/login',
method: 'post',
headers: {
'content-type': 'application/x-www-form-urlencoded',
},
data: qs.stringify({
'email': username,
'password': pwd
})
}
axios(config).then(res => {
console.log(res.headers);
}).catch(err => {
console.log(err);
})
This returned http status 200 without set-cookie in the headers. With curl the header was correctly retrieved, but the status code was 302
After adding the following config options to axios:
maxRedirects: 0,
validateStatus: function (status) {
return status <= 302; // Reject only if the status code is greater than 302
},
I received the set-cookie in axios in the response.header.
{
server: 'nginx/1.16.1',
date: 'Fri, 27 Dec 2019 16:03:16 GMT',
'content-length': '74',
connection: 'close',
location: '/',
'set-cookie': [
'cookiename=xxxxxxxxxxxxxxxxxxxxx; path=/; expires=Sat, 26-Dec-2020 16:03:16 GMT'
],
status: '302',
'x-frame-options': 'DENY'
}
Without maxRedirects: 0 I received the html of the homepage of the remote url I used.
Without validateStatus I received the set-cookie header in the err.response.headers object.
In my case, the network panel showed that the response had the 'Set-Cookie' header, but in axios the header wouldn't show up, and the cookie was being set.
For me, the resolution was setting the Access-Control-Expose-Headers header.
Explanation:
From this comment on an issue in the axios repository I was directed to this person's notes which led me to set the Access-Control-Expose-Headers header -- and now the cookie is properly setting in the client.
So, in Express.js, I had to add the exposedHeaders option to my cors middleware:
const corsOptions = {
//To allow requests from client
origin: [
"http://localhost:3001",
"http://127.0.0.1",
"http://104.142.122.231",
],
credentials: true,
exposedHeaders: ["set-cookie"],
};
...
app.use("/", cors(corsOptions), router);
It was also important that on the axios side I use the withCredentials config in following axios requests that I wanted to include the cookies.
ex/
const { data } = await api.get("/workouts", { withCredentials: true });
For me is working adding {withCredentials: true} like this:
axios
.post(url, {
foo: foo,
baz: baz,
}, {withCredentials: true})
.then(.............

AngularJS - CORS Error only with HTTP GET

I am trying to make a http get request from AngularJS. It is only working in the Internet Explorer 11. When I try to make a POST Call in Chrome, Firefox or Edge it is not working.
I get the following error:
CORS Error in Chrome
This is my AngularJS Call:
$http({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
url: URL
}).then(function successCallback(response) {
console.log(response.data);
}, function errorCallback(response) {
console.log(response.status);
console.log(response.headers);
console.log(response.config);
});
As backend I have a Java Spring MVC Application and I have set the following headers:
HttpHeaders responseHeader = new HttpHeaders();
responseHeader.set("Access-Control-Allow-Origin","*");
responseHeader.set("Access-Control-Allow-Headers:","Content-Type");
responseHeader.set("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE");
responseHeader.set("Content-Type","application/json");
But I saw that angular never reaches the backend when I set a breakpoint! This is very confusing, I already searched a lot in the internet and tried to changed the default AngularJS Content-Type header:
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
I tried also to change the Content-Type in the POST-Request to "application/x-www-form-urlencoded" - with no effect.
Note: The backend and the frontend runs on the same dev machine. The only difference is the port, that's why I am confused that I get a CORS Error at all...
I have this problem only with POST-Requests; GET works like a Charm
Edit 1:
I thought that this is a Problem with cors and that i use different ports, but is it possible that I can turn that off?
Edit 2:
Now i try to get it to work with a local tomcat. Now i see in the Tomcat the request will reach the server:
<< Client IP>> - - [28/Jun/2017:13:43:24 +0200] "OPTIONS <<URL>> HTTP/1.1" 403 -
The Response is now HTTP 403. In Browsers network tab i can see the following request header:
Host: <<backend ip>>:8080
User-Agent: <<user agent>>
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de,en-US;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Access-Control-Request-Method: POST
Access-Control-Request-Headers: access-control-allow-origin,content-type
Origin: http://<<Ip of host>>
Connection: keep-alive
The Response of that request header is the following:
Content-Type: text/plain
Content-Length: 0
Date: Wed, 28 Jun 2017 11:43:24 GMT
I have set the cors filter like the example in the tomcat documentation: http://tomcat.apache.org/tomcat-7.0-doc/config/filter.html#CORS_Filter
When i make a get request, it is still working and all CORS headers are present.
I think there is something wrong with the first OPTIONS request. I dont know why the tomcat do not set the CORS header when the OPTIONS request comes.
In your Spring Controller, add #CrossOrigin('http://localhost:8080')
annotation. Of course, substitute out the port of your angular application.
Since you are getting 400 (not authorized) error, the request is not reaching the service itself. Most probably the request domain is blocked, you may see if XHR requests are allowed and check cross origin policy if needed.
I figured it out. I made a completly new angularjs testwebsite. This is my working angularjs Code:
var req = {
method: 'POST',
url: 'myURL',
headers: {
'Content-Type': undefined
},
data: "JSON BODY DATA"
}
$http(req).then(function successCallback(response) {
console.log(response.data);
}, function errorCallback(response) {
console.log(response.data);
});
}]);
I deleted anything that changed the default angularjs headers.
The headers of my Spring MVC Application are the following:
HttpHeaders responseHeader = new HttpHeaders();
responseHeader.set("Access-Control-Allow-Origin","http://<<clientip>>");
responseHeader.set("Access-Control-Allow-Headers:","Content-Type");
responseHeader.set("Access-Control-Allow-Methods","POST, GET, PUT, OPTIONS, DELETE");
responseHeader.set("Content-Type","application/json");
I dont know the exactly cause why it is working now. Maybe it was because i modified the default headers in AngularJS.

Categories