Angular JS POST request not sending JSON data - web-services

I am trying to send an object as JSON to my webservice in Flask that is expecting JSON in the request data.
I have tested the service manually by sending JSON data and it works fine. However, when I try to make a http POST request through angular controller, the web server sends me a message saying it did not receive JSON.
When I inspect the request headers in Chrome it appears that data is not being sent in JSON but regular key/value pairs even through the Content Type is set to application/json
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:application/json, text/plain, */*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:49
Content-Type:application/json;charset=UTF-8
DNT:1
Host:localhost:5000
Origin:http://localhost:5000
Referer:http://localhost:5000/
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
application=AirFare&d1=10-APR-2013&d2=14-APR-2013
If you seen the last line below Request Payload, you can see the data is not in JSON format.
This is the HTTP POST call in my angular controller:
$http({
url: '/user_to_itsr',
method: "POST",
data: {application:app, from:d1, to:d2},
headers: {'Content-Type': 'application/json'}
}).success(function (data, status, headers, config) {
$scope.users = data.users; // assign $scope.persons here as promise is resolved here
}).error(function (data, status, headers, config) {
$scope.status = status + ' ' + headers;
});
};
I am sending the data as an object {} but I have tried to send it after serializing by JSON.stringify however, nothing I do seems to send JSON to the server.
Really appreciate if somebody can help out.

If you are serializing your data object, it will not be a proper json object. Take what you have, and just wrap the data object in a JSON.stringify().
$http({
url: '/user_to_itsr',
method: "POST",
data: JSON.stringify({application:app, from:d1, to:d2}),
headers: {'Content-Type': 'application/json'}
}).success(function (data, status, headers, config) {
$scope.users = data.users; // assign $scope.persons here as promise is resolved here
}).error(function (data, status, headers, config) {
$scope.status = status + ' ' + headers;
});

I have tried your example and it works just fine:
var app = 'AirFare';
var d1 = new Date();
var d2 = new Date();
$http({
url: '/api/test',
method: 'POST',
headers: { 'Content-Type': 'application/json' },
data: {application: app, from: d1, to: d2}
});
Output:
Content-Length:91
Content-Type:application/json
Host:localhost:1234
Origin:http://localhost:1234
Referer:http://localhost:1234/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1547.66 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
{"application":"AirFare","from":"2013-10-10T11:47:50.681Z","to":"2013-10-10T11:47:50.681Z"}
Are you using the latest version of AngularJS?

You can use FormData API https://developer.mozilla.org/en-US/docs/Web/API/FormData
var data = new FormData;
data.append('from', from);
data.append('to', to);
$http({
url: '/path',
method: 'POST',
data: data,
transformRequest: false,
headers: { 'Content-Type': undefined }
})
This solution from http://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs

you can use your method by this way
var app = 'AirFare';
var d1 = new Date();
var d2 = new Date();
$http({
url: '/api/apiControllerName/methodName',
method: 'POST',
params: {application:app, from:d1, to:d2},
headers: { 'Content-Type': 'application/json;charset=utf-8' },
//timeout: 1,
//cache: false,
//transformRequest: false,
//transformResponse: false
}).then(function (results) {
return results;
}).catch(function (e) {
});

try to use absolute url. if it not works, check if service's response has headers:
Access-Control-Allow-Origin and Access-Control-Allow-Headers
for example:
"Access-Control-Allow-Origin": "*"
"Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept"

you can use the following to find the posted data.
data = json.loads(request.raw_post_data)

$http({
url: '/api/user',
method: "POST",
data: angular.toJson(yourData)
}).success(function (data, status, headers, config) {
$scope.users = data.users;
}).error(function (data, status, headers, config) {
$scope.status = status + ' ' + headers;
});

Related

Request always returns unauthorized sent from React-Native to Django

i am trying to send a get request from my react-native app to a django api but i always get the error {"detail":"Authentication credentials were not provided."}.
but when i try this same request on postman everything works, i tried getting the code from postman itself and copied it to my react-native app but its the same unauthorized error
this is the code generated from the above postman request and i copy and pasted directly to my react-native app and it throws the above unauthorized message.
also tried the generated code from postman for curl and it works,
Please let me know what i am missing here
var myHeaders = new Headers();
//you can assume the token is correct
myHeaders.append("Authorization", "Token f38be1f33dbb5d6004108990a0a76");
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
fetch("https://base_url/api/v1/endpoint", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
Did you tried with plain object?
var requestOptions = {
method: 'GET',
headers: {
'Authorization': 'Token f38be1f33dbb5d6004108990a0a76'
'Accept': 'application/json',
'Content-Type': 'application/json',
},
redirect: 'follow'
};

Why is AWS Lambda, API Gateway returning a CORS error

I know this issue has been covered in many posts all over the web and I think I've tried them all, but I'm still getting a 403 CORS error to my local react app.
Here are in part, the Headers from Dev Tools:
#GENERAL:
Request URL: https://<myGatewayApiUrl>.amazonaws.com/dev/api/byid/1/129
Request Method: OPTIONS
Status Code: 403
#RESPONSE HEADERS
access-control-allow-headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
access-control-allow-methods: GET,OPTIONS
access-control-allow-origin: *
content-length: 42
content-type: application/json
I've been working in the API Gateway setting the Enable CORS, but I get an error for one get methods Add Access-Control-Allow-Origin Integration Response Header Mapping to GET method -> invalid response status code specified - But the OPTIONS headers get set and the GET header Access-Control-Allow-Origin is set.
I am using express and cors packages, here's a snippet from my API index.js file:
const app = express();
app.use(cors());
app.options('*', cors());
Here is the request code from React app:
export const getRecordById = async (userId, id, token) => {
try {
const response = await axios.get(
process.env.REACT_APP_API_URL + `/byid/${userId}/${id}`,
{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
},
}
);
return response.data;
} catch (error) {
console.log('ERROR', error);
return error;
}
};
Here is my response code from the Lambda API:
getById: asyncHandler(async (req, res, next) => {
const { user, id } = req.params;
const result = await recordsService.getRecordById(user, id);
res.set({
'content-type': 'application/json',
'Access-Control-Allow-Origin': '*',
});
if (!result) {
res.status(400).json({
error: true,
message: 'get record by ID action failed',
data: {},
});
}
res.status(200).json({
error: false,
message: 'successful record retrieval',
data: {
record: result,
},
});
}),
Also, I have my serverless.yml file http events set as such: (from what I understand cors: true should handle the preflight requests)
- http:
path: /api/records/byid/{user}/{id}
method: GET
cors: true
I've spent way too much time trying to figure this out. It must be something simple and dumb, am I using res.set() properly? Everything looks correct, I know I'm missing something. Thanks
API Gateway will reject the call with a CORS error when a URL is not found by default.
It looks like Axios is missing the /records bit from the request URL.

Postman nested variables not parsed in when get environment variable in Pre-Request script

Imagine following environment variables:
Base-URL => https://my.website.com/api
Cars-URL => {{Base-URL}}/cars
Auth-URL => {{Base-URL}}/login
If I use GET {{Cars-URL}} in postman it works fine and it does a call to https://mu.website.com/api/cars
Same applies for POST {{Auth-URL}} it works perfectly and I retrieve a JWT token.
However I would like to use Pre-Request Scripts of my collection to automatically fetch the JWT token before any call in the collection. Therefore I use the following setup:
var authUrl = pm.environment.get("Auth-URL");
pm.sendRequest({
url: authUrl,
method: "POST",
header: { ... },
body: { ... },
function (err, res) {
pm.environment.set("JWT-token", res)
}
});
I get the following output in my console:
POST http://{{base-url}}/login
Error: getaddrinfo ENOTFOUND {{base-url}}
Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxx
User-Agent: PostmanRuntime/7.26.5
Accept: */*
Postman-Token: xxxxxxxxxxxxxxx
Host: {{base-url}}
Accept-Encoding: gzip, deflate, br
It seems like that pm.environment.get does not parse the nested variable.
How to fix this issue?
Use pm.variables.replaceIn (available since v7.6.0.)
This will do the trick:
var authUrl = pm.variables.replaceIn(pm.environment.get("Auth-URL"));
pm.sendRequest({
....
})

Next.js not persisting cookies

I have a server-side rendered Next.js/express app that communicates with a Django API (cross-origin). I login a user like so:
const response = await fetch('localhost:8000/sign-in', {
method: 'POST',
credentials: 'include',
body: JSON.stringify({ email, password }),
headers: { 'Content-Type': 'application/json' },
});
const result = await response.json();
if (response.status === 200) {
Router.push('/account');
}
Django successfully logs in the user and returns set-cookie headers for the csrftoken and sessionid cookies, however, when I navigate to a different page (like in the above code when I Router.push), the cookies don't persist.
I assume this has something to do with server-side vs. client-side, but when cookies are set in the browser I expect them to persist regardless.
How can I get these cookies, once set, to persist across all pages on the client side?
It turns out that set-cookie is the old way of doing things. It's controlled by the browser, so it's obfuscated.
I ended up sending the csrftoken and sessionid back to the client in the JSON body, and saving them to localStorage using localStorage.setItem('sessionid', 'theSessionId') and localStorage.setItem('csrftoken', 'theCsrftoken').
Then when I need to make an authenticated request, I include them in the fetch headers:
const response = await fetch(`${API_HOST}/logout`, {
method: 'POST',
headers: {
'X-CSRFToken': localStorage.getItem('csrftoken'),
sessionid: localStorage.getItem('sessionid'),
},
});

How to view all response headers in ember with RESTAdapter

My response headers look like this
HTTP/1.1 200 OK
Server: nginx/1.9.7
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
X-On-Trial: 1
Cache-Control: no-cache
Access-Control-Allow-Origin: http://localhost:4200
Vary: Origin
Date: Sun, 29 May 2016 00:37:31 GMT
But when I do a console.log(headers) in the RESTAdapter handleResponse function, all that is included is
EmptyObject {Content-Type: "application/json", Cache-Control: "no-cache"}
How can I access the X-On-Trail header or any other custom headers I may need?
I'm not sure if this matters but I am using ember-simple-auth. Does that strip out headers?
I check sources. .handleResponse is called from .ajax
ajax(url, type, options) {
var adapter = this;
var requestData = {
url: url,
method: type
};
return new Ember.RSVP.Promise(function(resolve, reject) {
var hash = adapter.ajaxOptions(url, type, options);
hash.success = function(payload, textStatus, jqXHR) {
let response = adapter.handleResponse(
jqXHR.status,
parseResponseHeaders(jqXHR.getAllResponseHeaders()), // try to check both in debugger
payload,
requestData
);
So just try to stop at parseResponseHeaders(jqXHR.getAllResponseHeaders()) line and check jqXHR.getAllResponseHeaders(). If it's ok - check parseResponseHeaders()
I'll be glad to help with debug, if you have public link for your project or if you can give link for any public project with REstAdapter
About striping - it skips headers which doesn't contains colons
P.S> Thx to #Vlad
xmlHttp.getResponseHeader + Not working for CORS
"Access-Control-Expose-Headers"
Used in response to a preflight request to indicate which HTTP headers can be > used when making the actual request.
Access-Control-Allow-Headers: <field-name>[, <field-name>]*