Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pyramid not work with angular $http post

$http({method: 'POST', url: 'http://localhost:5001/products', data: {token: $scope.product.token}}).success(
    function () {
        alert('success');
    }
);

In the pyramid side, request.POST show that NOVars: Not a form request. Not an HTML form submission( Content-Type: application/json)

I am using cornice to provide my api(/products) and I thinks it is pyramid's problem.

Does anyone have a solution?

like image 766
luthur Avatar asked Jul 22 '13 05:07

luthur


4 Answers

Angular sends the post body (data) as application/json while forms are normally sent as application/x-www-form-urlencoded. Pyramid parses the body and let you access it in request.POST when it's encoded as a normal form.

It is not be possible to represent every data encoded the Angular way (json) as a key/value pair like is provided by pyramid API.

[
  1,
  2,
  3,
  4
]

Solution on Pyramid side

It can be solved per view or globally

Per view

This is the pyramid way and the most flexible way to handle this.

@view_config(renderer='json')
def myview(request):
    data = request.json_body
    # deal with data.
    return {
        "success" : True
    }

Globally

Pyramid can most likely be set to assume a body encoded as application/json is an object and its properties be put in request.POST.

Solution on Angular side

As with the pyramid side, it can be solved per request and globally.

Per request

You need to send the data the way forms are normally sent:

$http({
  method: 'POST',
  url: url,
  headers: {'Content-Type': 'application/x-www-form-urlencoded'},
  transformRequest: function(obj) {
    var str = [];
    for(var p in obj) {
      if (obj.hasOwnProperty(p)) {
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
      }
    }
    return str.join("&");
  },
  data: xsrf
}).success(function () {});

Globally

To send posts as form by default, configure the $httpProvider to do so.

angular.module('httpPostAsForm', [])
.config(['$httpProvider', function ($httpProvider) {
  $httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
  $httpProvider.defaults.transformRequest.unshift(function (obj) {
     var str = [];
    for(var p in obj) {
      if (obj.hasOwnProperty(p)) {
        str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
      }
    }
    return str.join("&");
  });
}]);

Then include this module in your app:

angular.module("app", ["httpPostAsForm"]);
like image 86
Kristian Benoit Avatar answered Nov 15 '22 06:11

Kristian Benoit


AngularJS $http.post is different from jquery's. The data you pass is not posted as a form but as json in the request body. So your pyramid view can not decode it as usual. You have to either:

  • directly access the request body and decode it in your pyramid view;
  • or modify your angularjs code to post your data as form content : see this other question in stackoverflow
like image 39
rtxm Avatar answered Nov 15 '22 05:11

rtxm


the answer is angular $post do OPTIONS request first and then do the POST request, get data form the request.json_body

like image 37
luthur Avatar answered Nov 15 '22 04:11

luthur


Use req.json_body if you post some json-decoded content. req.GET, req.POST, req.params only cope with from submissions. Btw, $http -> ngResource -> restangular ...

like image 30
maow Avatar answered Nov 15 '22 04:11

maow