Angular post array object - javascript

I am trying to post a object array, I expect the post to post JSON like so
{"campaign":"ben",
"slots":[
{
"base_image": "base64 code here"
}
]
}
When I post I get this in the console
angular.js:9866 POST /ccuploader/Campaign/updateSlots 413 (Payload Too Large)
(anonymous) # angular.js:9866
n # angular.js:9667
f # angular.js:9383
(anonymous) # angular.js:13248
$eval # angular.js:14466
$digest # angular.js:14282
$apply # angular.js:14571
(anonymous) # angular.js:21571
dispatch # jquery.min.js:3
r.handle # jquery.min.js:3
app.js:71 failed
Im not sure why my post is not working. Can someone point out my mistake ?
JavaScript code
$scope.SaveImage = function () {
$http({
url: "http://www.somesite.co.uk/ccuploader/Campaign/updateSlots",
method: "POST",
data: $.param({ 'campaign': "name", 'slots': $scope.slots }),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function (response) {
// success
console.log('success');
console.log("then : " + JSON.stringify(response));
}, function (response) { // optional
// failed
console.log('failed');
console.log(JSON.stringify(response));
});
};

Seems you are sending a base64 string on the POST request.
Most web servers have a max POST limit.
You should configure your server to allow large POST params.
Implementation is different from server to server.
If your server is using PHP refer this.
Increasing the maximum post size
Also it is better if you can upload images by chunking them. There are lot of libraries that does it. Otherwise your browser will hang and the request will eventually timeout. That's called the multipart upload.
You can upload GBs of images without no problem with multipart upload mechanism.
UPDATE
Also without using the $.param function just pass the parameters directly to the data object. Since the payload is heavy the $.param may throw this exception when it's trying to parse the request.
$scope.SaveImage = function () {
$http({
url: "http://www.somesite.co.uk/ccuploader/Campaign/updateSlots",
method: "POST",
data: {
campaign: "name",
slots: $scope.slots
}),
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function (response) {
// success
console.log('success');
console.log("then : " + JSON.stringify(response));
}, function (response) { // optional
// failed
console.log('failed');
console.log(JSON.stringify(response));
});

Related

Request api working with rest client but not with controller and service in angularjs

when i am testing api with rest client postman, its working fine. This is the parameter.
URL: http://localhost/api2/v1/delete_item_in_order
Type : post
Body : order_id:1091, product_id:12, variant_id:20
Same thing i want to with service and controller in angularjs.
Service :
var BASEURL = 'http://localhost/api2/v1/';
sampleApp.factory('Order', function ($resource, $cacheFactory) {
return $resource(BASEURL + 'shop_orders/:id', {id: '#id'}, {
'query': {method: 'GET', cache: true},
'get': {method: 'GET'},
'deleteOrderRow' :{
method : 'POST',
url : BASEURL + 'delete_item_in_order',
params : { order_id : '#order_id', product_id : '#product_id', variant_id : '#variant_id' }
}
});
});
Controller:
Order.deleteOrderRow({order_id: od.order_id, product_id: od.product_id, variant_id: od.varient_id}, function (data) {
alert('success');
});
But this is giving error in console:
angular.js:10765 OPTIONS http://localhost/api2/v1/delete_item_in_order?order_id=1091&product_id=767&variant_id=47 (anonymous function) # angular.js:10765r # angular.js:10558g # angular.js:10268(anonymous function) # angular.js:14792r.$eval # angular.js:16052r.$digest # angular.js:15870r.$apply # angular.js:16160(anonymous function) # angular.js:23618If # angular.js:3346Hf.d # angular.js:3334
/#/GetDetails/1091:1 XMLHttpRequest cannot load http://localhost/api2/v1/delete_item_in_order?order_id=1091&product_id=767&variant_id=47. Response for preflight has invalid HTTP status code 404
Can anyone help me on this? What is wrong and what changes is needed in controller and/or service to make the request successful.

Using Emotion API for Video (Javascript or Ruby)

So I'm working on posting a video to the Emotion API for video and I haven't been able to get a response.
I've been able to get it to work on the Microsoft online console, but when I try to implement it in my Rails app using (1) JavaScript Ajax, or (2) Ruby server-side code, I consistently get various errors.
Here's my code. At first I tried to Ajax way, but I had a suspicion that the API doesn't have CORS enabled. So then I tried Ruby, to no success.
Ruby attempt:
def index
uri = URI('https://api.projectoxford.ai/emotion/v1.0/recognizeinvideo')
uri.query = URI.encode_www_form({
})
data = File.read("./public/mark_zuck.mov")
request = Net::HTTP::Post.new(uri.request_uri)
# Request headers
request['Ocp-Apim-Subscription-Key'] = 'e0ae8aad4c7f4e33b51d776730cff5a9'
# Request body
request.body = data
request.content_type = "video/mov"
response = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
end
Here's my Ajax attempt:
function CallAPI(apiUrl, apiKey){
console.log("API called");
$(".loading").css("display", "inline-block");
$.ajax({
url: apiUrl,
beforeSend: function (xhrObj) {
xhrObj.setRequestHeader("Content-Type", "application/octet-stream");
xhrObj.setRequestHeader("Ocp-Apim-Subscription-Key", apiKey);
},
type: "POST",
data: '{"url": "http://localhost:5000/mark_zuck.mov"}',
processData: false,
success: function(response){
console.log("API success");
ProcessResult(response);
$(".loading").css("display", "none");
console.log(response);
},
error: function(error){
console.log("API failed");
$("#response").text(error.getAllResponseHeaders());
$(".loading").css("display", "none");
console.log(error);
}
})
Yes, I've regenerated my key. This is just to illustrate my point.
So you have to set Content-Type to application/octet-stream if it's a binary file you're sending, like I was.
If you use a url you should set Content-Type to application/json and the url must be publicly available.

AngularJs use object in post

I'm trying to pass a json object to my factory.login method so I can re use it.
This is my code:
Controller function
var data = {email:'test','password':'test'};
vm.login = function() {
employeeFactory.login(vm.url, vm.data)
.then(function(response) {
console.log(response);
}, function(data)
{
console.log(data.status);
});
}
Factory
factory.login = function(url,data) {
return $http({
'method': 'POST',
'url': url,
'data': $.param(
data
),
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
return factory;
But the error is:
angular.js:13294 TypeError: Cannot read property 'jquery' of undefined
at Function.n.param (jquery-2.2.2.min.js:4)
at Object.factory.login (employeeFactory.js:14)
at employeeController.vm.login (employeeController.js:16)
at fn (eval at <anonymous> (angular.js:14138), <anonymous>:4:285)
at b (angular.js:15151)
at e (angular.js:24674)
at m.$eval (angular.js:16895)
at m.$apply (angular.js:16995)
at HTMLButtonElement.<anonymous> (angular.js:24679)
at HTMLButtonElement.n.event.dispatch (jquery-2.2.2.min.js:3)
This should be vm.data
vm.data = {email:'test','password':'test'};
And factory doesn't require jQuery at all, just use below construction
factory.login = function(url,data) {
return $http({
'method': 'POST',
'url': url,
//don't use $.param, as you need jQuery dependency for that
//for x-www-form-urlencoded you have to use this construction
//email=test&password=test
'data': 'email=' + data.email + '&password=' + data.password,
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
}
});
}
return factory;
But consider using JSON type on server request handler, as it's much easier
Your JSON seems incorrect. Should be:
var data = { "email": "test", "password": "test"};
Also the $http.post function is available:
$http.post(url, data, [{headers: { 'Content-Type' : 'application/x-www-form-urlencoded'}]);
JSON is a format to serialize object, so it's a string.
You have your object as data that contains the data to be sent to the server, so just do this:
Just put your data object in it:
factory.login = function(url,data) {
return $http({
'method': 'POST',
'url': url,
'data': data
});
}
return factory;
Angular will send json to the server in the payload. You don't need to do that serialization your self.
Documentation https://docs.angularjs.org/api/ng/service/$http
-> Default Transformations ->
Request transformations ($httpProvider.defaults.transformRequest and
$http.defaults.transformRequest):
If the data property of the request configuration object contains an
object, serialize it into JSON format. Response transformations
($httpProvider.defaults.transformResponse and
$http.defaults.transformResponse):
If XSRF prefix is detected, strip it (see Security Considerations
section below). If JSON response is detected, deserialize it using a
JSON parser.
The stack trace show the following error :
TypeError: Cannot read property 'jquery' of undefined
miss match variable uses declared var data = {} but used vm.data in your controller. should declare as
vm.data= {email:'test','password':'test'}
or
use data in employeeFactory.login(vm.url, data) if declare as var data= {}
and in your factory no need to use $.param can send as argument in post method like
$http.post(url, data, [{headers: { 'Content-Type' : 'application/x-www-form-urlencoded'}]);
Angular Documentation

How to time server responses with Sinon.JS?

I want to test how my web application deals with server responses. That's why I created a test scenario which uses Sinon.JS to fake a server.
My application code makes two requests and in my test scenario I want to force the situation that the response to the first request is sent after the response to my second request.
Sequence:
Request 1
Request 2
Response 2
Response 1
Here is the CoffeeScript code that I wrote for my test case:
# Request 1
server.respondWith 'GET', "http://localhost/endpoint", [200, {"Content-Type": "application/json"}, '{"A":"A"}']
# Request 2
server.respondWith 'GET', "http://localhost/endpoint", [200, {"Content-Type": "application/json"}, '{"B":"B"}']
# My application code
...
# Response 1
server.respond()
# Response 2
server.respond()
Once I start the test all REST calls to http://localhost/endpoint from my application code get the same response ({"B":"B"}). So to me it looks like Sinon.JS takes always the response from the last URL mapping which has been defined using respondWith.
But I want my faked server to return {"B":"B"} to the first hit on http://localhost/endpoint. On the second hit it should return {"A":"A"}.
Is it possible to do something like this?
# Request 1
request_1 = server.respondWith 'GET', "http://localhost/endpoint", [200, {"Content-Type": "application/json"}, '{"A":"A"}']
# Request 2
request_2 = server.respondWith 'GET', "http://localhost/endpoint", [200, {"Content-Type": "application/json"}, '{"B":"B"}']
# My application code (makes multiple requests to the same endpoint)
...
# Response 1
request_2.respond()
# Response 2
request_1.respond()
You can use the Jasmine-AJAX lib made by Pivotal for this.
CoffeeScript:
it 'can handle an unlimited amount of requests and respond to each one individually after all requests have been made', ->
jasmine.Ajax.install() # put this in beforeEach
url = 'http://localhost/test'
$.ajax
dataType: 'json'
url: url
success: (data, textStatus, jqXHR) ->
# Receives {"A":"A"}
console.log "Response: #{JSON.stringify(data)}"
$.ajax
dataType: 'json'
url: url
success: (data, textStatus, jqXHR) ->
# Receives {"B":"B"}
console.log "Response: #{JSON.stringify(data)}"
responses = [
{
contentType: 'application/json'
responseText: '{"A":"A"}'
status: 200
},
{
contentType: 'application/json'
responseText: '{"B":"B"}'
status: 200
}
]
for i in [0...jasmine.Ajax.requests.count()]
request = jasmine.Ajax.requests.at i
request.respondWith responses[i]
expect(jasmine.Ajax.requests.count()).toBe 2
jasmine.Ajax.uninstall() # put this in afterEach
With count() and at() you can get all requests ordered by time and put them in an array where you can for example shift the requests and respond to them.
var count = 0
$.mockjax(
function(requestSettings){
if(requestSettings.url === "path/to/api" && requestSettings.type === "POST"){
return {
response: function(origSettings){
if (count == 0){
this.responseText = {msg:"this is first response" }
this.status = 200
}
else if(count == 1){
//more combos
}
else{
this.responseText = {msg:"this is last response" }
this.status = 200
}
count = (count + 1) % 4
}
}
}
}
})

AngularJS tokenWrapper - wrong callback arguments

AngularJS 1.2.1
ngResource 1.2.1
I got the weirdest problem.
I'm using tokenWrapper by Andy Joslin (AngularJS: How to send auth token with $resource requests?)
I have a resource defined like that:
.factory('someService', ['$resource', 'api_host', 'TokenHandler',
function($resource, api_host, TokenHandler) {
var Resource = $resource(api_host + 'applicant/:command/:xxx', { xxx: '#xxx', command: '#command' }, {
'get': { method: 'GET', isArray: false },
'save': { method: 'POST', isArray: false },
'create': { method: 'put', isArray: false },
'message': { method: 'post', isArray: false }
});
Resource = TokenHandler.wrapActions( Resource,
["query", "get", "save", "remove", "create", "message"] );
return Resource;
}])
its wrapped by tokenHandler and token is sent with every request and thats great.
the problem is with invoking the error callback.
when using the resource like that
var interview = new someService({ command: 'doSomething', xxx: $scope.xxx});
interview.$create({}, function(response) {
console.log(response);
}, function(e) {
alert('error');
});
The Problem
When the resource returns 200 the success function (1st argument) is invoked as it should.
When the resource returns something else, the error callback is not invoked.
I've tried to log the tokenHandler and it seems like the handler is massing up the arguments.
var tokenWrapper = function( resource, action ) {
// copy original action
resource['_' + action] = resource[action];
// create new action wrapping the original and sending token
resource[action] = function( data, success, error){
console.log(success, 'success');
console.log(error, 'error');
return resource['_' + action](
angular.extend({}, data || {}, {token: tokenHandler.get()}),
success,
error
);
};
};
the result of the console.log prints out the data as success and success as error.
how can I fix that?!
angular 1.2.0 changed the way promises are handled. and this look like a promise issue (you are not getting the expected order of suceess``failure```. see this for an example. my guess that insisting on using resource from 1.5 doesn't work we'll with this behavior, so you are not getting the expected data. yes. there are error messages when upgrading. but solving them shouldn't take long.

Categories

Resources