Parsing AngularJS http.post data on server side with express & body-parser - javascript

I just recently started learning MEAN stack so forgive me if this seems like a really dumb question. My problem is as follows:
On the client side (controller.js) I have,
$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
data : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
}
})
On the server side I have,
app.post('/root', function(req, res) {
console.log(req.body);
console.log(req.body.username);
});
My console log shows:
17 Nov 21:39:04 - [nodemon] starting `node server/server.js`
{ '{"type":"root","username":"testUserName","password":"testPassword"}': '' }
undefined
I would imagine req.body.username to give me testUserName but I get undefined. The JSON format I am getting is slightly weird. Can anyone help me out this one? I did some reading and tried using body-parser and went through angular js $http.post documentation but didn't find anything that would help me out.
I imagine the problem is at:
{ '{"type":"root","username":"testUserName","password":"testPassword"}': '' }
but I cant seem to figure out how I would pass the data from $http.post in my angular controller so that I would just get my request in identifier:value format.

Nevermind, I figured it out. Seems like I needed a break from coding.
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
to
headers : { 'Content-Type': 'application/json' }
fixed the problem.

Try my source code below:
$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
data : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
},
transformRequest: function(obj) {
var str = [];
for(var p in obj){
str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
}
return str.join('&');
}
})

$http({
method : 'POST',
url : '/root',
// set the headers so angular passing info as form data (not request payload)
headers : { 'Content-Type': 'application/x-www-form-urlencoded' },
params : {
type:'root',
username:$scope.rEmail,
password:$scope.rPassword
}
})
try it with 'params', maybe it won't work but try it :P

I've tried with "params" instead of "data" and worked ok, and doesn't matter if headers are "application/x-www-form-urlencoded" or "application/json"
But using "application/json" works with request.query.param1 on node.

Related

Trouble returning API response leveraging fetch

Been working on a script to execute in Google Apps Scripts to pull some data from an external API and post that information into a Google Sheet. I have a script that works client side (running from the console in chrome) that is able to leverage promises and return HTTP responses correctly to execute more code on.
However, in Apps Scripts I cannot figure out how to return a native JSON object representation from the API. In normal JS, I would return the .json() method of the response and would be good to go. Since Apps Script is essentially executing a .gs file they have different classes and methods that are not specific to JS. This help doc https://developers.google.com/apps-script/guides/services/external provides the below example for working with JSON
var json = response.getContentText();
var data = JSON.parse(json);
Logger.log(data.title);
If I try to leverage that getContextText() method by itself I get a TypeError: Cannot read property '0' of undefined error. If I combine it with JSON.parse like return JSON.parse(response.getContentText()); I get a SyntaxError: Unexpected token M in JSON at position 0. Am I missing something wildly obvious? Any help would be greatly appreciated! Additionally, happy to provide more specifics from my script as well.
EDIT
Below is a snippet of script that works client side.
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': "Basic" + ' ' + gongCreds,
'Accept': "*/*",
'Connection': "keep-alive",
'Content-Type': "application/json"
},
body: gongRequestBody,
});
return response.json();
}
Here is the returned promise object data that I want to leverage for future execution
[[PromiseResult]]: Object
records: {totalRecords: 1, currentPageSize: 1, currentPageNumber: 0}
requestId: "6w83fpcbo5ka2evast7"
usersDetailedActivities: Array(1)
0:
userDailyActivityStats: Array(1)
0:
callsAsHost: []
callsAttended: (6) ["432806286570218902", "1825323793748204011", "3193437184015561879", "4172384470445855263", "5128172192322468435", "5808052479141116583"]
callsCommentsGiven: []
callsCommentsReceived: []
callsGaveFeedback: []
callsMarkedAsFeedbackGiven: []
callsMarkedAsFeedbackReceived: []
callsReceivedFeedback: []
callsRequestedFeedback: []
callsScorecardsFilled: []
callsScorecardsReceived: []
callsSharedExternally: []
callsSharedInternally: []
fromDate: "2021-01-20T05:00:00Z"
othersCallsListenedTo: (2) ["3401282086024720458", "8098199458721511977"]
When your following Javascript is converted to Google Apps Script,
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': "Basic" + ' ' + gongCreds,
'Accept': "*/*",
'Connection': "keep-alive",
'Content-Type': "application/json"
},
body: gongRequestBody,
});
return response.json();
}
it becomes as follows.
const response = UrlFetchApp.fetch(url, {
method: 'POST',
headers: {
'Authorization': "Basic" + ' ' + gongCreds,
'Accept': "*/*",
'Connection': "keep-alive",
},
muteHttpExceptions: true,
contentType: "application/json",
payload: gongRequestBody,
});
console.log(response.getContentText())
// I think that if above request works and the returned value is the correct value you expected, you can use console.log(JSON.parse(response.getContentText()).title)
But, there are several important points.
From your script, I cannot see the value of gongRequestBody. When 'Content-Type': "application/json" is used, JSON.stringify() is required to be used for the JSON object. So if gongRequestBody is the JSON object, please convert it to the string using JSON.stringify().
From your question, I cannot see your script for requesting to the URL. So I cannot point out the modification points of your script even when your script has the modification points.
I asked to show the sample value of response.getContentText() in your Google Apps Script. But unfortunately, I cannot find the sample value of it. So when you use console.log(JSON.parse(response.getContentText()).title) to the above sample script of Google Apps Script and an error occurs, can you provide the sample value of console.log(response.getContentText())? By this, I would like to confirm it.
Note:
In this sample script, it supposes that your Javascript works and the variables of gongCreds, gongCreds and gongRequestBody are the valid values for requesting to your URL. Please be careful this. So when above sample script didn't work as you expected, can you provide the sample value of console.log(response.getContentText())? By this, I would like to confirm your situation.
Reference:
fetch(url, params)

When sending POST request to backend API via fetch(), the body has only key and no value

When I'm sending a POST request to my backend express server, the req.body contains only the key part where the entire body is the key and the value part is empty
This is the frontend fetch request
let data = {
videoUrl: "dummy text"
}
fetch("/api/getinfo", {
method:"POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
},
body: JSON.stringify(data)
})
This is how I handle it in backend (NOTE: I'm using body-parser)
app.post("/api/getinfo", (req,res) => {
console.log(req.body);
}
I expect the output to be
'{ "videoUrl":"dummy text" }'
But what I get is
{ '{"videoUrl":"dummy text"}': '' }
The entire requests body is the key, and the value is empty.
What am I doing wrong?
You are using the wrong Content-Type to send json
Try
"Content-Type": "application/json;charset=UTF-8"
I noticed an issue in your header;
fetch("/api/getinfo", {
method:"POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8" //this very line
},
I guess what you meant is
fetch("/api/getinfo", {
method:"POST",
headers: {
'Content-type': 'application/json; charset=utf-8'
},
Note: Your header denotes what the content is encoded in. It is not necessarily possible to deduce the type of the content from the content itself, i.e. you can't necessarily just look at the content and know what to do with it. So you need to be sure of what you're writing in your header else you will end up with an error.
I will suggest you get to read more about What does “Content-type: application/json; charset=utf-8” really mean?
The problem is that you are stringifying the data:
body: JSON.stringify(data)
should be
body: data
That should fix it

Node JS - Constructing an OAuth2 Request

Im trying to construct an OAuth2 request to the Box API. The example POST request they give as a guideline is a bit ambiguous to me as I am recently learning backend development. The example is as follows:
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=<JWT>&
client_id=<client_id>&
client_secret=<client_secret>
Official Docs:
https://box-content.readme.io/docs/app-auth
The way I attempted to do this is as follows:
var boxHeaders = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var boxOptions = {
url: 'https://api.box.com/oauth2/token',
method: 'POST',
headers: boxHeaders,
form: {
'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
'assertion': boxtoken,
'client_id': 'myclientid',
'client_secret': 'myclientsecret'
}
};
request.post(boxOptions, function(err, response, body) {
console.log(body);
});
I get the following error:
{
"error":"invalid_request",
"error_description":"Invalid grant_type parameter or parameter missing"
}
Obviously the grant type is incorrect but I have no idea how to go about constructing the string based on the Box API example. If anyone can help and even expose me to some good articles or tutorials on how to do this, that would be great!
Thank you.
I just struggled with this myself. I was able to get this to work by moving everything you currently have in boxOptions.form into the request body.
For example:
var boxHeaders = {
'Content-Type': 'application/x-www-form-urlencoded'
};
var boxOptions = {
url: 'https://api.box.com/oauth2/token',
method: 'POST',
headers: boxHeaders
};
var form = {
grant_type:'urn:ietf:params:oauth:grant-type:jwt-bearer',
client_id: 'id',
client_secret: 'secret',
assertion: boxtoken
};
var request = https.request(boxOptions, function(response) {
// do stuff
});
request.write(querystring.stringify(form));
request.end();
Hope this helps. Unfortunately, I'm not familiar enough with the request library to provide an example using it.

Angular js passing values from form to php [duplicate]

In the code below, the AngularJS $http method calls the URL, and submits the xsrf object as a "Request Payload" (as described in the Chrome debugger network tab). The jQuery $.ajax method does the same call, but submits xsrf as "Form Data".
How can I make AngularJS submit xsrf as form data instead of a request payload?
var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};
$http({
method: 'POST',
url: url,
data: xsrf
}).success(function () {});
$.ajax({
type: 'POST',
url: url,
data: xsrf,
dataType: 'json',
success: function() {}
});
The following line needs to be added to the $http object that is passed:
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
And the data passed should be converted to a URL-encoded string:
> $.param({fkey: "key"})
'fkey=key'
So you have something like:
$http({
method: 'POST',
url: url,
data: $.param({fkey: "key"}),
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
From: https://groups.google.com/forum/#!msg/angular/5nAedJ1LyO0/4Vj_72EZcDsJ
UPDATE
To use new services added with AngularJS V1.4, see
URL-encoding variables using only AngularJS services
If you do not want to use jQuery in the solution you could try this. Solution nabbed from here https://stackoverflow.com/a/1714899/1784301
$http({
method: 'POST',
url: url,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: xsrf
}).success(function () {});
I took a few of the other answers and made something a bit cleaner, put this .config() call on the end of your angular.module in your app.js:
.config(['$httpProvider', function ($httpProvider) {
// Intercept POST requests, convert to standard form encoding
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
$httpProvider.defaults.transformRequest.unshift(function (data, headersGetter) {
var key, result = [];
if (typeof data === "string")
return data;
for (key in data) {
if (data.hasOwnProperty(key))
result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
}
return result.join("&");
});
}]);
As of AngularJS v1.4.0, there is a built-in $httpParamSerializer service that converts any object to a part of a HTTP request according to the rules that are listed on the docs page.
It can be used like this:
$http.post('http://example.com', $httpParamSerializer(formDataObj)).
success(function(data){/* response status 200-299 */}).
error(function(data){/* response status 400-999 */});
Remember that for a correct form post, the Content-Type header must be changed. To do this globally for all POST requests, this code (taken from Albireo's half-answer) can be used:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
To do this only for the current post, the headers property of the request-object needs to be modified:
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $httpParamSerializer(formDataObj)
};
$http(req);
You can define the behavior globally:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
So you don't have to redefine it every time:
$http.post("/handle/post", {
foo: "FOO",
bar: "BAR"
}).success(function (data, status, headers, config) {
// TODO
}).error(function (data, status, headers, config) {
// TODO
});
As a workaround you can simply make the code receiving the POST respond to application/json data. For PHP I added the code below, allowing me to POST to it in either form-encoded or JSON.
//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
$_POST = json_decode(file_get_contents('php://input'),true);
//now continue to reference $_POST vars as usual
These answers look like insane overkill, sometimes, simple is just better:
$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
"&password=" + encodeURIComponent(password) +
"&grant_type=password"
).success(function (data) {
//...
You can try with below solution
$http({
method: 'POST',
url: url-post,
data: data-post-object-json,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for (var key in obj) {
if (obj[key] instanceof Array) {
for(var idx in obj[key]){
var subObj = obj[key][idx];
for(var subKey in subObj){
str.push(encodeURIComponent(key) + "[" + idx + "][" + encodeURIComponent(subKey) + "]=" + encodeURIComponent(subObj[subKey]));
}
}
}
else {
str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
}
}
return str.join("&");
}
}).success(function(response) {
/* Do something */
});
Create an adapter service for post:
services.service('Http', function ($http) {
var self = this
this.post = function (url, data) {
return $http({
method: 'POST',
url: url,
data: $.param(data),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
}
})
Use it in your controllers or whatever:
ctrls.controller('PersonCtrl', function (Http /* our service */) {
var self = this
self.user = {name: "Ozgur", eMail: null}
self.register = function () {
Http.post('/user/register', self.user).then(function (r) {
//response
console.log(r)
})
}
})
There is a really nice tutorial that goes over this and other related stuff - Submitting AJAX Forms: The AngularJS Way.
Basically, you need to set the header of the POST request to indicate that you are sending form data as a URL encoded string, and set the data to be sent the same format
$http({
method : 'POST',
url : 'url',
data : $.param(xsrf), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
});
Note that jQuery's param() helper function is used here for serialising the data into a string, but you can do this manually as well if not using jQuery.
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
Please checkout!
https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
For Symfony2 users:
If you don't want to change anything in your javascript for this to work you can do these modifications in you symfony app:
Create a class that extends Symfony\Component\HttpFoundation\Request class:
<?php
namespace Acme\Test\MyRequest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;
class MyRequest extends Request{
/**
* Override and extend the createFromGlobals function.
*
*
*
* #return Request A new request
*
* #api
*/
public static function createFromGlobals()
{
// Get what we would get from the parent
$request = parent::createFromGlobals();
// Add the handling for 'application/json' content type.
if(0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')){
// The json is in the content
$cont = $request->getContent();
$json = json_decode($cont);
// ParameterBag must be an Array.
if(is_object($json)) {
$json = (array) $json;
}
$request->request = new ParameterBag($json);
}
return $request;
}
}
Now use you class in app_dev.php (or any index file that you use)
// web/app_dev.php
$kernel = new AppKernel('dev', true);
// $kernel->loadClassCache();
$request = ForumBundleRequest::createFromGlobals();
// use your class instead
// $request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Just set Content-Type is not enough, url encode form data before send.
$http.post(url, jQuery.param(data))
I'm currently using the following solution I found in the AngularJS google group.
$http
.post('/echo/json/', 'json=' + encodeURIComponent(angular.toJson(data)), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).success(function(data) {
$scope.data = data;
});
Note that if you're using PHP, you'll need to use something like Symfony 2 HTTP component's Request::createFromGlobals() to read this, as $_POST won't automatically loaded with it.
AngularJS is doing it right as it doing the following content-type inside the http-request header:
Content-Type: application/json
If you are going with php like me, or even with Symfony2 you can simply extend your server compatibility for the json standard like described here: http://silex.sensiolabs.org/doc/cookbook/json_request_body.html
The Symfony2 way (e.g. inside your DefaultController):
$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());
The advantage would be, that you dont need to use jQuery param and you could use AngularJS its native way of doing such requests.
Complete answer (since angular 1.4). You need to include de dependency $httpParamSerializer
var res = $resource(serverUrl + 'Token', { }, {
save: { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
});
res.save({ }, $httpParamSerializer({ param1: 'sdsd', param2: 'sdsd' }), function (response) {
}, function (error) {
});
In your app config -
$httpProvider.defaults.transformRequest = function (data) {
if (data === undefined)
return data;
var clonedData = $.extend(true, {}, data);
for (var property in clonedData)
if (property.substr(0, 1) == '$')
delete clonedData[property];
return $.param(clonedData);
};
With your resource request -
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
This isn't a direct answer, but rather a slightly different design direction:
Do not post the data as a form, but as a JSON object to be directly mapped to server-side object, or use REST style path variable
Now I know neither option might be suitable in your case since you're trying to pass a XSRF key. Mapping it into a path variable like this is a terrible design:
http://www.someexample.com/xsrf/{xsrfKey}
Because by nature you would want to pass xsrf key to other path too, /login, /book-appointment etc. and you don't want to mess your pretty URL
Interestingly adding it as an object field isn't appropriate either, because now on each of json object you pass to server you have to add the field
{
appointmentId : 23,
name : 'Joe Citizen',
xsrf : '...'
}
You certainly don't want to add another field on your server-side class which does not have a direct semantic association with the domain object.
In my opinion the best way to pass your xsrf key is via a HTTP header. Many xsrf protection server-side web framework library support this. For example in Java Spring, you can pass it using X-CSRF-TOKEN header.
Angular's excellent capability of binding JS object to UI object means we can get rid of the practice of posting form all together, and post JSON instead. JSON can be easily de-serialized into server-side object and support complex data structures such as map, arrays, nested objects, etc.
How do you post array in a form payload? Maybe like this:
shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday
or this:
shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday
Both are poor design..
This is what I am doing for my need, Where I need to send the login data to API as form data and the Javascript Object(userData) is getting converted automatically to URL encoded data
var deferred = $q.defer();
$http({
method: 'POST',
url: apiserver + '/authenticate',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: userData
}).success(function (response) {
//logics
deferred.resolve(response);
}).error(function (err, status) {
deferred.reject(err);
});
This how my Userdata is
var userData = {
grant_type: 'password',
username: loginData.userName,
password: loginData.password
}
The only thin you have to change is to use property "params" rather than "data" when you create your $http object:
$http({
method: 'POST',
url: serviceUrl + '/ClientUpdate',
params: { LangUserId: userId, clientJSON: clients[i] },
})
In the example above clients[i] is just JSON object (not serialized in any way). If you use "params" rather than "data" angular will serialize the object for you using $httpParamSerializer: https://docs.angularjs.org/api/ng/service/$httpParamSerializer
Use AngularJS $http service and use its post method or configure $http function.

AngularJS - Any way for $http.post to send request parameters instead of JSON?

I have some old code that is making an AJAX POST request through jQuery's post method and looks something like this:
$.post("/foo/bar", requestData,
function(responseData)
{
//do stuff with response
}
requestData is just a javascript object with some basic string properties.
I'm in the process of moving our stuff over to use Angular, and I want to replace this call with $http.post. I came up with the following:
$http.post("/foo/bar", requestData).success(
function(responseData) {
//do stuff with response
}
});
When I did this, I got a 500 error response from the server. Using Firebug, I found that this sent the request body like this:
{"param1":"value1","param2":"value2","param3":"value3"}
The successful jQuery $.post sends the body like this:
param1=value1&param2=value2&param3=value3
The endpoint I am hitting is expecting request parameters and not JSON. So, my question is is there anyway to tell $http.post to send up the javascript object as request parameters instead of JSON? Yes, I know I could construct the string myself from the object, but I want to know if Angular provides anything for this out of the box.
I think the params config parameter won't work here since it adds the string to the url instead of the body but to add to what Infeligo suggested here is an example of the global override of a default transform (using jQuery param as an example to convert the data to param string).
Set up global transformRequest function:
var app = angular.module('myApp');
app.config(function ($httpProvider) {
$httpProvider.defaults.transformRequest = function(data){
if (data === undefined) {
return data;
}
return $.param(data);
}
});
That way all calls to $http.post will automatically transform the body to the same param format used by the jQuery $.post call.
Note you may also want to set the Content-Type header per call or globally like this:
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
Sample non-global transformRequest per call:
var transform = function(data){
return $.param(data);
}
$http.post("/foo/bar", requestData, {
headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
transformRequest: transform
}).success(function(responseData) {
//do stuff with response
});
If using Angular >= 1.4, here's the cleanest solution I've found that doesn't rely on anything custom or external:
angular.module('yourModule')
.config(function ($httpProvider, $httpParamSerializerJQLikeProvider){
$httpProvider.defaults.transformRequest.unshift($httpParamSerializerJQLikeProvider.$get());
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=utf-8';
});
And then you can do this anywhere in your app:
$http({
method: 'POST',
url: '/requesturl',
data: {
param1: 'value1',
param2: 'value2'
}
});
And it will correctly serialize the data as param1=value1&param2=value2 and send it to /requesturl with the application/x-www-form-urlencoded; charset=utf-8 Content-Type header as it's normally expected with POST requests on endpoints.
From AngularJS documentation:
params – {Object.} – Map of strings or objects which
will be turned to ?key1=value1&key2=value2 after the url. If the
value is not a string, it will be JSONified.
So, provide string as parameters. If you don't want that, then use transformations. Again, from the documentation:
To override these transformation locally, specify transform functions
as transformRequest and/or transformResponse properties of the config
object. To globally override the default transforms, override the
$httpProvider.defaults.transformRequest and
$httpProvider.defaults.transformResponse properties of the
$httpProvider.
Refer to documentation for more details.
Use jQuery's $.param function to serialize the JSON data in requestData.
In short, using similar code as yours:
$http.post("/foo/bar",
$.param(requestData),
{
headers:
{
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}
).success(
function(responseData) {
//do stuff with response
}
});
For using this, you have to include jQuery in your page along with AngularJS.
Note that as of Angular 1.4, you can serialize the form data without using jQuery.
In the app.js:
module.run(function($http, $httpParamSerializerJQLike) {
$http.defaults.transformRequest.unshift($httpParamSerializerJQLike);
});
Then in your controller:
$http({
method: 'POST',
url: myUrl',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: myData
});
This might be a bit of a hack, but I avoided the issue and converted the json into PHP's POST array on the server side:
$_POST = json_decode(file_get_contents('php://input'), true);
I have problems as well with setting custom http authentication because $resource cache the request.
To make it work you have to overwrite the existing headers by doing this
var transformRequest = function(data, headersGetter){
var headers = headersGetter();
headers['Authorization'] = 'WSSE profile="UsernameToken"';
headers['X-WSSE'] = 'UsernameToken ' + nonce
headers['Content-Type'] = 'application/json';
};
return $resource(
url,
{
},
{
query: {
method: 'POST',
url: apiURL + '/profile',
transformRequest: transformRequest,
params: {userId: '#userId'}
},
}
);
I hope I was able to help someone. It took me 3 days to figure this one out.
Modify the default headers:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded;charset=utf-8";
Then use JQuery's $.param method:
var payload = $.param({key: value});
$http.post(targetURL, payload);
.controller('pieChartController', ['$scope', '$http', '$httpParamSerializerJQLike', function($scope, $http, $httpParamSerializerJQLike) {
var data = {
TimeStamp : "2016-04-25 12:50:00"
};
$http({
method: 'POST',
url: 'serverutilizationreport',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
data: $httpParamSerializerJQLike(data),
}).success(function () {});
}
]);
Quick adjustment - for those of you having trouble with the global configuration of the transformRequest function, here's the snippet i'm using to get rid of the Cannot read property 'jquery' of undefined error:
$httpProvider.defaults.transformRequest = function(data) {
return data != undefined ? $.param(data) : null;
}
You can also solve this problem without changing code in server, changing header in $http.post call and use $_POST the regular way. Explained here: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
I found many times problematic behavior of this whole. I used it from express (without typings) and the bodyParser (with the dt~body-parser typings).
I didn't try to upload a file, instead simply to interpret a JSON given in a post string.
The request.body was simply an empty json ({}).
After a lot of investigation finally this worked for me:
import { json } from 'body-parser';
...
app.use(json()); <-- should be defined before the first POST handler!
It may be also important to give the application/json content type in the request string from the client side.
Syntax for AngularJS v1.4.8 + (v1.5.0)
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);
Eg:
var url = "http://example.com";
var data = {
"param1": "value1",
"param2": "value2",
"param3": "value3"
};
var config = {
headers: {
'Content-Type': "application/json"
}
};
$http.post(url, data, config)
.then(
function (response) {
// success callback
},
function (response) {
// failure callback
}
);

Categories

Resources