React fetch POST request not working in only safari - reactjs

For some reason trying to do a POST request on safari doesn't work despite it working on chrome for me. https://caniuse.com/#search=fetch suggests that fetch should work on safari, and the GET requests do work just fine.
My code looks like
putData() {
let data = {
title: this.state.tempTitle,
lat: this.state.tempLat,
lng: this.state.tempLng,
insta: this.state.tempInsta,
icon: this.state.tempType,
approved: false,
};
let options = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
mode: 'cors',
body: JSON.stringify(data),
};
fetch("/items/", options);
}
Other similar/same questions on stack overflow suggested adding the mode: 'cors' line as well as changing /items to /items/ but, I have tried without those two changes to my code as well.
Response preview on safari says An error occurred when trying to load resource and the request headers page for items/ shows
Summary
URL: http://localhost:3000/items/
Status: —
Source: —
Initiator:
Suggest.js:62
Request
Content-Type: application/json
Referer: http://localhost:3000/suggest
Accept: */*
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1 Safari/605.1.15
Response
No response headers
Confused as to why this might be happening, didn't even notice till I uploaded the site to AWS and someone using it noticed on their iPhone.

Related

API Gateway - 200 response from Postman, 500 from app

I have an API on AWS API Gateway that takes a POST request and forwards headers and body to a third party API and returns the result. This process works fine when I send the request from Postman, but doesn't work either via cURL or JavaScript.
NB - all URIs, auth tokens etc below are modified so may be inconsistent between screengrabs.
The request in Postman is below
Postman console for this looks like
POST https://dsvdvsdvsdrc.execute-api.eu-west-1.amazonaws.com/Prod/
200
957 ms
Network
Request Headers
Authorization: Basic <myauthtoken>NTAwYTQxNDdmYzcyLWFkZDgtNDZmMy05ZWU0LWQzYWM=
Content-Type: application/x-www-form-urlencoded
User-Agent: PostmanRuntime/7.26.8
Accept: */*
Cache-Control: no-cache
Postman-Token: 9dab6f01-67bf-4611-8d8e-c3d5fe725067
Host: tsfsfsdrc.execute-api.eu-west-1.amazonaws.com
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 82
Request Body
grant_type: "client_credentials"
scope: "https://api.ebay.com/oauth/api_scope"
In my JavaScript app I have the following code:
var data = qs.stringify({
'grant_type': 'client_credentials',
'scope': 'https://api.ebay.com/oauth/api_scope'
});
var config = {
method: 'post',
url: 'https://fddgdgddrc.execute-api.eu-west-1.amazonaws.com/Prod/',
headers: {
'Authorization': 'Basic sssscyLWFkZDgtNDZmMy05ZWU0LWQzYWM=',
'Content-Type': 'application/x-www-form-urlencoded'
},
data : data
};
console.log("******Here is ebayData REQUEST***** "+ JSON.stringify(config));
axios(config)
.then(function (response) {
console.log("******Here is ebayData***** "+ JSON.stringify(response.data));
})
.catch(function (error) {
console.log( "******Here is ebay Error***** "+ error);
});
However when the application runs I get a 500 response. Below are the request headers and body that is being sent in the request
I've enabled cloudwatch logs on the API and below is an example of a successful request via Postman
and here is an example of an unsuccessful request from the browser
Looking further into the response headers for a failed and a successful response I see the headers with comments against them are different
Failed request
(d360923b-eff2-433f-8f76-a9038547dcdf) Endpoint response headers: {rlogid=t6ldssk67%3D9whhldssk67*qc1qr%28rbpv6710-17dd35648ce-0x129,
x-ebay-c-version=1.0.0,
x-frame-options=SAMEORIGIN,
x-content-type-options=nosniff,
x-xss-protection=1; mode=block,
set-cookie=ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/; Secure,dp1=bu1p/QEBfX0BAX19AQA**6581b87b^;Domain=.ebay.com;Expires=Tue, 19-Dec-2023 15:36:27 GMT;Path=/; Secure,
content-encoding=gzip,
cache-control=private, <--- doesn't appear in successful response
pragma=no-cache, <--- doesn't appear in successful response
date=Sun, 19 Dec 2021 15:36:26 GMT,
server=ebay-proxy-server,
x-envoy-upstream-service-time=19,
x-ebay-pop-id=UFES2-RNOAZ03-api,
transfer-encoding=chunked}
Successful request
(fe565553-3283-4593-8b07-b4e2d58dd2a6) Endpoint response headers: {rlogid=t6ldssk67%3D9vjdldssk67*5cddm%28rbpv6775-17dd23fa53c-0x124,
x-ebay-c-version=1.0.0,
x-ebay-client-tls-version=TLSv1.2,<--- doesn't appear in failed response
x-frame-options=SAMEORIGIN,
x-content-type-options=nosniff,
x-xss-protection=1; mode=block,
set-cookie=ebay=%5Esbf%3D%23%5E;Domain=.ebay.com;Path=/; Secure,dp1=bu1p/QEBfX0BAX19AQA**65817126^;Domain=.ebay.com;Expires=Tue, 19-Dec-2023 10:32:06 GMT;Path=/; Secure,
content-encoding=gzip,
content-type=application/json,<--- doesn't appear in failed response
date=Sun, 19 Dec 2021 10:32:06 GMT,
server=ebay-proxy-server,
x-envoy-upstream-service-time=96,
x-ebay-pop-id=UFES2-SLCAZ01-api,
transfer-encoding=chunked}
I think I've been looking at this for too long and am probably missing something obvious, but headers and body etc all seem to be consistent across the app and Postman, so I'm confused why the request from one is successful and the other is failing. Any advice much appreciated.
Add all other headers as in Postman , some application rejects requests without proper user-agent header or some other required headers.

Symfony React Cors issue

I use Symfony 5 and React, with docker.
Both container are on different docker-compose but on the same newtork, so they can see and ping each other.
Now I want to POST something on one of my api route, here is my request:
const handleSubmit = async function (e) {
setError(null)
setLoading(true)
e.preventDefault()
const data = new FormData(e.target)
console.warn(data)
try {
const response = await fetch('https://localhost:8443/authentication_token', {
credentials: 'include',
headers: {
Accept: 'application/json',
},
method: 'POST',
body: data,
})
console.warn(response)
const responseData = await response.json()
console.warn(responseData)
onConnect(responseData)
} catch (e) {
setError(e)
setLoading(false)
}
}
Then I'm getting the following error:
Access to fetch at 'https://localhost:8443/authentication_token' from origin 'http://localhost:3001' has been blocked by CORS policy: 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.
So after some search I installed nelmio package to deal with cors, here is my nelmio_cors.yml file:
nelmio_cors:
defaults:
allow_credentials: true
allow_origin: ['*']
allow_methods: [ 'GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE' ]
allow_headers: [ '*' ]
expose_headers: [ 'Authorization']
max_age: 0
hosts: []
origin_regex: true
forced_allow_origin_value: ~
paths:
'^/':
origin_regex: true
allow_origin: ['*']
allow_headers: [ '*' ]
allow_methods: [ 'POST', 'PUT', 'PATCH', 'GET', 'DELETE' ]
expose_headers: [ 'Link' ]
max_age: 3600
And added the below line in my .env:
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=(.*)
###< nelmio/cors-bundle ###
And yet I get the same error and didn't manage to find an answer online.
Does anyone see what I've done wrong?
UPDATE
I've changed my nelmio_cors.yml config to the one above
And still got issues with cors but a different error message now:
Response {type: "cors", url: "https://localhost:8443/authentication_token", redirected: false, status: 404, ok: false, …}
It seems react don't manage to find the route. Any idea why ?
UPDATE 2
My nelmio_cors.yaml file now looks like that :
nelmio_cors:
paths:
'^/':
origin_regex: true
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
allow_headers: ['*']
allow_methods: ['POST', 'PUT', 'PATCH', 'GET', 'DELETE']
max_age: 3600
.env contains:
CORS_ALLOW_ORIGIN=(.*)
But on the route call I receive the following error :
Access to fetch at 'https://localhost:8443/authentication_token' from origin 'http://localhost:3001' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true' when the request's credentials mode is 'include'.
My response headers
access-control-allow-origin: http://localhost:3001
cache-control: no-cache, private
content-encoding: gzip
content-length: 451
content-type: application/json
date: Thu, 22 Oct 2020 08:12:11 GMT
server: openresty/1.17.8.2
status: 404
vary: Accept-Encoding
vary: Accept
x-debug-exception: Unable%20to%20find%20the%20controller%20for%20path%20%22%2Fauthentication_token%22.%20The%20route%20is%20wrongly%20configured.
x-debug-exception-file: %2Fsrv%2Fapi%2Fvendor%2Fsymfony%2Fhttp-kernel%2FHttpKernel.php:141
x-debug-token: 9b2891
x-debug-token-link: https://localhost:8443/_profiler/9b2891
x-powered-by: PHP/7.4.11
x-previous-debug-token: 486328
x-robots-tag: noindex
request header:
:authority: localhost:8443
:method: POST
:path: /authentication_token
:scheme: https
accept: application/json
accept-encoding: gzip, deflate, br
accept-language: fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7
content-length: 248
content-type: multipart/form-data; boundary=----WebKitFormBoundarywFASHmBarrNFyL7Y
cookie: pma_lang=fr; phpMyAdmin=a18f394d8e7daaefba20691da57c4b58; io=Jh7QElIlIXLDeAYaAAAA
origin: http://localhost:3001
referer: http://localhost:3001/
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.99 Safari/537.36
I would suggest to have a different environmental variable value for local development and for your production or non-production environments.
nelmio_cors:
paths:
'^/':
origin_regex: true
allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
allow_headers: ['*']
allow_methods: ['POST', 'PUT', 'PATCH', 'GET', 'DELETE']
max_age: 3600
For local development you may have the following env.
CORS_ALLOW_ORIGIN=(.*)
For prod/non-prod you may want to list your web applications domains explicitly in order to be on a safe side.
CORS_ALLOW_ORIGIN=^https://(www\.)?(site.domain.com|site2.domain.com)$
For those who have the same issue, the problem came from the frontend
The data I recovered and place in body :
const response = await fetch(
'https://localhost:8443/authentication_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: data
})
were not well formated, and for some reason the backend sent back weird errors.
So I hardcoded them and this final result work :
const data = "{\"email\":\"test#test.com\",\"password\":\"test\"}";
const response = await fetch(
'https://localhost:8443/authentication_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: data
})

AngularJS WebApi Authorization header does not appear to be getting passed

I am trying to create a call with AngularJS v1.3.15 into ASP.NET WebAPI (latest from Nuget) to get a list of customers. I can successfully authenticate and get back a token. I add the token to an Authentication header but when I make the call it gets kicked back saying the Authentication header is missing.
The Angular call after I get the token looks like this
$scope.baseUrl = "http://localhost:7800/";
$http({
method: 'GET',
url: $scope.baseUrl + 'customer',
headers: {
'Authorization': $scope.token
}})
I have also tried to utilize the angularjs $resourse
return $resource($scope.baseUrl + 'customer', { }, { 'get': { method: 'GET', isArray: true, headers: { 'Authorization': $scope.token } } });
In the WebApiConfig Register method I have the following setup
var cors = new EnableCorsAttribute("*","*","*");
config.EnableCors(cors);
in a DelegatingHandler I check for the Authorization header like so
var authHeader = request.Headers.Authorization;
From the Angular app it is always null. If I run a check from Fiddler and PostMan I get the Authorization header just fine.
When I press F12 from Chrome and look at the request header these are the results
OPTIONS /customer HTTP/1.1
Host: localhost:7800
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:63342
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2376.0 Safari/537.36
Access-Control-Request-Headers: accept, authorization
Accept: */*
Referer: http://localhost:63342/Test/index.html
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Fixed my issue, after some searches I found that OPTIONS does not seem to be supported out of the box. I found that if I add NuGet package Microsoft.Owin.Cors and then add
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
to the startup.cs file

AngularJS $http post fails

I am new to AngularJS, I am from SAP background and as part of my PoC I built my REST services using SAP NW Gateway,I am facing an issue to POST data from Angularjs to my REST services.Please find the below detailed error log
***1. Remote Address:
10.xxx.xx.xx:8000
2. Request URL:
//host:port/sap/opu/odata/sap/USERS/Users
3. Request Method:
POST
4. Status Code:
400 Bad Request
5. Request Headersview source
1. Accept:
application/json, text/plain, */*
2. Accept-Encoding:
gzip,deflate
3. Accept-Language:
en,te;q=0.8
4. Authorization:
Basic a2VsYW1yOmoyZDEwMA==
5. Connection:
keep-alive
6. Content-Length:
146
7. Content-Type:
application/json;charset=UTF-8
8. Cookie:
sap-usercontext=sap-client=100; SAP_SESSIONID_J2D_100=R_60WyUyNG2nV1MbhC9QAcKPzyBwwxHkmwsAUFaDBqQ%3d
9. Host:
abcdefgh:8000
10. Origin:
file://
11. User-Agent:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36
12. X-CSRF-Token:
_jXDnt2Cdpplpj5zvK3iPA==
6. Request Payloadview source
{UserID:555, FirstName:rajesh555, LastName:kelam555, Email:rajesh555#gmail.com, Phone:9876554433,…}
1. Country: "UK"
2. Email: "rajesh555#gmail.com"
3. FirstName: "rajesh555"
4. LastName: "kelam555"
5. Phone: 9876554433
6. Postcode: "TW18 4BL"
7. UserID: 555
7. Response Headersview source
1. content-length:
535
2. content-type:
application/json
3. dataserviceversion:
1.0****
Angular Code for Post :
$scope.addRow = function () {
var config = {};
var pushdata = {'UserID':$scope.UserID, 'FirstName':$scope.FirstName, 'LastName':$scope.LastName, 'Email':$scope.Email, 'Phone':$scope.Phone, 'Country':$scope.Country, 'Postcode':$scope.Postcode};
// Sending Notification to User
growl.addSuccessMessage("User Created", config);
/* $http.post(url,pushdata, {'Content-Type':'application/json'}).success(function(pushdata) {
$scope.resultSet = pushdata.d.results;
alret("Data Posted");
}) */
$http.post(url,pushdata, {headers:{'Content-Type':'application/json'}}).success(function(data){alert(data);});
$scope.resultSet.push(pushdata);
$scope.createMessage();
$scope.UserID='';
$scope.FirstName='';
$scope.LastName='';
$scope.Email='';
$scope.Phone='';
$scope.Country='';
};
it would be great if some one help me to sort.
*Note: I am a kid in AngularJS...please ignore me and feel free to thought me.
I request to suggest the best URl/Site to learn Angularjs in a better and consistent way.
I thought, if I share the format(XML/JSON) of payload expecting for the POST to perform by my SAP Gateway service which will helps me to quickly resolve this.Below are the formats of XML/JSON works for POST.
XML Format:
host:port/sap/opu/odata/sap/USERS/Users('123')
Users('123')
2014-11-21T15:21:52Z
123
RAJESH
KELAM
RAJESHKUMAR.KELAM#ABG.CO.UK
123456789
UK
RG4 6SA
JSON Format:
{
d:
{
__metadata:
{
id: "host:port/sap/opu/odata/sap/USERS/Users('123')"
uri: "host:port/sap/opu/odata/sap/USERS/Users('123')"
type: "USERS.User"
}
-
UserID: "123"
FirstName: "RAJESH"
LastName: "KELAM"
Email: "RAJESHKUMAR.KELAM#ABG.CO.UK"
Phone: "123456789"
Country: "UK"
Postcode: "RG4 6SA"
}
-
}
You sure that the url you posting is expecting this data you want to post? You can use POSTMAN extension (in google chrome) and test if you service are ready to receive any data from http.post
Finally I could able to sort out my problem, it is all about formatting the data passing to REST service..
below is the peice of code which works is my case
$scope.addRow = function () {
var StrUId = ($scope.UserID).toString();
var StrPh = ($scope.Phone).toString();
var pushdata = {"UserID":StrUId, "FirstName":$scope.FirstName, "LastName":$scope.LastName, "Email":$scope.Email, "Phone":StrPh, "Country":$scope.Country, "Postcode":$scope.Postcode};
// Posting data
$http({
method: "post",
url:url,
data:pushdata,
headers: {
"X-CSRF-Token": "0XGo8HzpzrhaZxxX83QH9g==",
},
dataType : "json",
async: false,
contentType: 'application/json',
success: function(data){
alert(data);
}
});
Thanks for the support given
Rajesh

Angular POST to Web API doesn't pass data

I've been writing code against ASP.NET Web API for a while now with jQuery and I'm starting something new in Angular (writing against the same Web API backend.)
I'm POSTing to a method that will return some search results for an entity in the system. It looks like this:
public IEnumerable<dynamic> Post(string entity, FormDataCollection parameters)
{
// entity is passed on the route.
// parameters contains all the stuff I'm trying to get here.
}
If I call the method using jQuery.post:
$.post('api/search/child', {where : 'ParentID = 1'}, function(d){ foo = d });
it works just right and returns what I would expect.
I've made a service in my angular application that makes a similar call:
$http.post('api/search/child', { where: 'parentID = ' + parent.ID })
.success(function (data, status, headers, config) {
// etc.
})
But when it hits my "Post" method on the server, "paramters" is null.
After some googling I've tried adding a content-type header to ensure it's passed as JSON, and trying JSON.stringify-ing and $.param()-ing the "data" argument, but that didn't do anything (and from what I've read that shouldn't be necessary.) What am I doing wrong here? Thanks for your help!
UPDATE:
Here's the raw request from the (working) jQuery example:
POST http://localhost:51383/api/search/child HTTP/1.1
Accept: */*
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Host: localhost:51383
Content-Length: 23
DNT: 1
Connection: Keep-Alive
Pragma: no-cache
Cookie: (etc)
Authorization: (etc)
where=ParentID+%3D+1
And the raw request from the (failing) Angular sample:
POST http://localhost:51383/api/search/parent HTTP/1.1
Content-Type: application/json;charset=utf-8
Accept: application/json, text/plain, */*
Referer: http://localhost:51383/mypage.aspx
Accept-Language: en-US
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko
Connection: Keep-Alive
Content-Length: 27
DNT: 1
Host: localhost:51383
Pragma: no-cache
Cookie: (etc)
{"where":"ScorecardID = 1"}
Very weird. Even when I add the 'json' data type parameter to the end of the jQuery call, it still creates the www-form-urlencoded request. And that's the one that works. My Web API application is already set up for JSON (but thank-you Dalorzo).
Check if you have included the JSON Formatter in your configuration. It should be something like :
System.Web.Http.GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
config.Formatters.Insert(0, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
The Content-Type=application/json only will work if you set the proper formatter.
You can also try using [FromBody] next to your parameter type.
Solved! Discovered this question:
AngularJs $http.post() does not send data
Pointing to this lovely article:
http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
Turns out Angular doesn't post data the same way jQuery does but you can override it with some tweaking.
I solved this by below codes:
Client Side:
$http({
url: me.serverPath,
method: 'POST',
data: data,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
}).
success(function (serverData) {
console.log("ServerData:", serverData);
......
Notice that data is an object.
On the server (ASP.NET MVC):
[AllowCrossSiteJson]
public string Api()
{
var data = JsonConvert.DeserializeObject<AgentRequest>(Request.Form[0]);
if (data == null) return "Null Request";
var bl = Page.Bl = new Core(this);
return data.methodName;
}
and 'AllowCrossSiteJsonAttribute' is needed for cross domain requests:
public class AllowCrossSiteJsonAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}

Resources