Reputation: 512
I have an api in Sinatra (Mongodb). I am trying to write some data with the POST method from very small application written in Angularjs. data I am trying to send is 'aplication/x-www-form-urlencoded'. For some reason I keep getting the error:
JSON::ParserError - 784: unexpected token at 'id=111&name=Bruce&city=LA&address=City1':
I can see that there is some data encoded in url, but Sinatra does not read it correctly.
Sinatra:
post '/companies' do
company=JSON.parse(request.body.read)
company = Company.new(company)
end
AngularJs script:
var formApp = angular.module('formApp', []);
function formController($scope, $http) {
$scope.formData = {};
$scope.processForm = function() {
$http({
method : 'POST',
url : 'http://localhost:4567/api/v1/companies',
data : $.param($scope.formData), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' }
})
.success(function(data) {
console.log(data);
if (!data.success) {
// if not successful, bind errors to error variables
$scope.errorName = data.errors.name;
$scope.errorSuperhero = data.errors.superheroAlias;
} else {
// if successful, bind success message to message
$scope.message = data.message;
$scope.errorName = '';
$scope.errorSuperhero = '';
}
});
};
}
I am calling the function formData with the button after the form is completed in HTML:
body ng-app="formApp" ng-controller="formController">
<div class="container">
<div class="col-md-6 col-md-offset-3">
<!-- PAGE TITLE -->
<div class="page-header">
<h1><span class="glyphicon glyphicon-tower"></span> Submitting Forms with Angular</h1>
</div>
<!-- SHOW ERROR/SUCCESS MESSAGES -->
<div id="messages" class="well" ng-show="message">{{ message }}</div>
<!-- FORM -->
<form ng-submit="processForm()">
<div id="superhero-group" class="form-group" ng-class="{ 'has-error' : errorSuperhero }">
<label>ID</label>
<input type="text" name="id" class="form-control" placeholder="Caped Crusader" ng-model="formData.id">
<span class="help-block" ng-show="errorSuperhero">{{ errorSuperhero }}</span>
</div>
<div id="name-group" class="form-group" ng-class="{ 'has-error' : errorName }">
<label>Name</label>
<input type="text" name="name" class="form-control" placeholder="Bruce Wayne" ng-model="formData.name">
<span class="help-block" ng-show="errorName">{{ errorName }}</span>
</div>
<!-- SUPERHERO NAME -->
<div id="superhero-group" class="form-group" ng-class="{ 'has-error' : errorSuperhero }">
<label>City</label>
<input type="text" name="city" class="form-control" placeholder="Caped Crusader" ng-model="formData.city">
<span class="help-block" ng-show="errorSuperhero">{{ errorSuperhero }}</span>
</div>
<div id="superhero-group" class="form-group" ng-class="{ 'has-error' : errorSuperhero }">
<label>Address</label>
<input type="text" name="address" class="form-control" placeholder="Caped Crusader" ng-model="formData.address">
<span class="help-block" ng-show="errorSuperhero">{{ errorSuperhero }}</span>
</div>
<!-- SUBMIT BUTTON -->
<button type="submit" class="btn btn-success btn-lg btn-block">
<span class="glyphicon glyphicon-flash"></span> Submit!
</button>
</form>
<!-- SHOW DATA FROM INPUTS AS THEY ARE BEING TYPED -->
<pre>
{{ formData }}
</pre>
</div>
Upvotes: 0
Views: 2605
Reputation: 48968
The error occurs because the AngularJS code is sending data in URL encoded form. To POST data as a JSON string:
var formApp = angular.module('formApp', []);
function formController($scope, $http) {
$scope.formData = {};
$scope.processForm = function() {
$http({
method : 'POST',
url : 'http://localhost:4567/api/v1/companies',
̶d̶a̶t̶a̶ ̶ ̶ ̶ ̶:̶ ̶$̶.̶p̶a̶r̶a̶m̶(̶$̶s̶c̶o̶p̶e̶.̶f̶o̶r̶m̶D̶a̶t̶a̶)̶,̶ ̶ ̶/̶/̶ ̶p̶a̶s̶s̶ ̶i̶n̶ ̶d̶a̶t̶a̶ ̶a̶s̶ ̶s̶t̶r̶i̶n̶g̶s̶
data : $scope.formData, //data automatically coded as JSON string
̶h̶e̶a̶d̶e̶r̶s̶ ̶:̶ ̶{̶ ̶'̶C̶o̶n̶t̶e̶n̶t̶-̶T̶y̶p̶e̶'̶:̶ ̶'̶a̶p̶p̶l̶i̶c̶a̶t̶i̶o̶n̶/̶x̶-̶w̶w̶w̶-̶f̶o̶r̶m̶-̶u̶r̶l̶e̶n̶c̶o̶d̶e̶d̶'̶ ̶}̶
})
̶.̶s̶u̶c̶c̶e̶s̶s̶(̶f̶u̶n̶c̶t̶i̶o̶n̶(̶d̶a̶t̶a̶)̶ ̶{̶
.then(function(response) {
̲v̲a̲r̲ ̲d̲a̲t̲a̲ ̲=̲ ̲r̲e̲s̲p̲o̲n̲s̲e̲.̲d̲a̲t̲a̲;̲
console.log(data);
if (!data.success) {
// if not successful, bind errors to error variables
$scope.errorName = data.errors.name;
$scope.errorSuperhero = data.errors.superheroAlias;
} else {
// if successful, bind success message to message
$scope.message = data.message;
$scope.errorName = '';
$scope.errorSuperhero = '';
}
});
};
}
The $http service automatically encodes JavaScript objects as JSON strings. The content type header is set to application/json
.
The .success
method is obsolete. Use .then
instead. For more information, see Why are angular $http success/error methods deprecated? Removed from v1.6?.
Upvotes: 0
Reputation: 4058
You are attempting to parse URL encoded data by passing it through a JSON parser. This will not work.
Try parsing response.body
as a regular String rather than a JSON String.
Upvotes: 1