AngularJS $ http POST request with JSON parameter and query string

advertisements

As the title suggests, I am attempting to write an AJAX call using Angular's $http object. I would like to send a post request that submits JSON in the body of the request, but also has a query string appended to the URL. After reading the documentation for $http all the way through, surfing for answers on SO, and attempting several different configurations, I am still not clear on how to pass the parameters correctly. Currently, my API responds with either empty JSON or Bad Request (400).

Code

function inviteStaff (json) {
    authToken = service.getAuthToken();
    return $http({
        method: 'POST',
        url: baseUrl + '/invitations' + '?authToken=' + authToken,
        data: JSON.stringify(json),
        headers: {
            'Content-type': 'application/json'
        }
    });
}

Consuming Function

self.invite = function ($form) {
    self.showLoader = true;
    InvitesService.inviteStaff($scope.inviteModel).then(function () {
        $form.$setPristine();
        $scope.inviteModel.timestamp = new Date();
        $scope.invites.unshift($scope.inviteModel);
        $scope.inviteModel = self.createNewInvite();
        self.showLoader = false;
    },
    function () {
       self.showLoader = false;
    });
};

Request log

data: "authToken=********&t=*****" // this is weird because it adds another "t" parameter to this query string here
headers: Object
    Accept: "application/json"
    Accept-Language: "en"
    Content-type: "application/json"
    authToken: "*********" // just the token here
    __proto__: Object
method: "POST"
params: Object
timeout: Object
transformRequest: Array[1]
transformResponse: Array[1]
url: "http://****.****.com:****/doctors/invitations?authToken=*****"
__proto__: Object

Param JSON object

{
    accountType: "LEAD_DOCTOR",
    firstName: "kraken",
    lastName: "lastName",
    email: "[email protected]"
}

Can anyone shed a little light on how this should work? Do I pass the json object to data or params? Do I need to use JSON.stringify on the data field? In some cases, I also saw people passing an empty string to data.

I also have been running it through Charles Proxy. I can get very close to what I want, but for some reason the JSON is showing under the JSON Text filter as a query string, and not the JSON filter.

Any ideas would be helpful. I will be refactoring and upgrading it all to use the $resource tool, but we are on a tight deadline and I just want to get this working for now. Let me know if you need more info.

UPDATE We're using swagger to document our API, and you can actually hit the endpoint in their UI. It produces the following CURL command. I thought it might help spot the issue.

curl -X POST --header "Content-Type: application/json" --header "Accept: application/json" -d "{
    \"firstName\": \"string\",
    \"lastName\": \"string\",
    \"email\": \"[email protected]\",
    \"accountType\": \"CLIENT\"
}" "http://*****.****.com:****/doctors/invitations?authToken=***obfuscatedAuthToken***"


I would recommend you to take advantage of the header field:

function inviteStaff (json) {
authToken = service.getAuthToken();
return $http({
    method: 'POST',
    url: baseUrl + '/invitations',
    data: JSON.stringify(json),
    headers: {
        'Content-type': 'application/json',
        'authToken': authToken
    }
   });
 }

Then on the server side, ask the current request for the header value of authToken.

Passing Tokens in the URL has some security concerns, for your reading: https URL with token parameter : how secure is it?