pyramid not work with angular $http post

2k views Asked by At
$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?

6

There are 6 answers

0
Kristian Benoit On

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"]);
0
maow On

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 ...

3
TalentTuner On

Try setting contenttype in $http, something like below.

 $http(
           {
               url: url,
               contentType: "application/json",
               data: data,
               method: method
           })
           .success(function (response) {
               successcb(response);
           }).error(function (data, status, headers, config) { errorcb(data); });
  };
0
luthur On

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

0
DevLounge On

You can simply get the POST data this way:

query = json.loads(request.body)
0
rtxm On

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: