Angular Resource POST Request adding extra quote in JSON request - angularjs

Let me start off by saying that this issue is not happening in Chrome. I have been really only testing in Chrome but then I decided to try it out in Firefox only to find I can't log in because my JSON request is not right.
Here's my call:
self.user = $resource('http://my-site.com/a/account/login', {}, {
login : {
method: 'POST'
},
.
.
.
self.user.login({username: username, password: password}).$promise.then(function(response) {
self.model.loggedInUser = response;
deferred.resolve(self.model.loggedInUser);
}).catch(function(err) {
self.model.loggedInUser = undefined;
deferred.reject(err);
});
I'll also mention that I have an Interceptor set up, but for this specific call all it does is the following:
'request' : function(config) {
var deferred = $q.defer();
deferred.resolve(config);
return deferred.promise;
}
So if I look in the Chrome network tab I see something like this:
{"username":"myName","password":"173A9F67AB4399D34561D96BFDB0E3B009C39232"}
Nothing out of the ordinary there.
However, this is what I see in Firefox:
{"username":""myName","password":"173A9F67AB4399D34561D96BFDB0E3B009C39232"}"
Notice the extra quotation mark after the colon and after the ending curly brace. This is not right. I can't seem to figure out what is causing this though. Espeically why it only seems to be happening in Firefox (only 2 browsers I've tried are Chrome and Firefox).
Edit: Thinking this could be useful, the Content-Type of my request is the same in both browsers:
application/json; charset=utf-8

Related

405 method not allowed using $http service AngularJS

I'm getting a 405 error making a request from localhost, this is the full error:
OPTIONS http://www.myurl.com 405 (Method Not Allowed)
XMLHttpRequest cannot load http://www.myurl.com. Response for preflight has invalid HTTP status code 405
I understand the problem but the quirk is that I get this error just when I use the angular $http service:
var req = {
method: 'POST',
url: 'http://www.myurl.com',
headers: {
'Content-Type': 'application/json'
},
data: {
}
}
$http(req)
.then(function(res) {},
function(error) {});
Using XMLHttpRequest works perfectly:
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(xhttp.responseText);
}
};
xhttp.open("POST", 'http://www.myurl.com', true);
xhttp.send();
I have a chrome extension to add CORS headers and it is working. I also notice that if I remove the third parameter in xhttp.open the error appears again.
¿Does anyone know the reason? ¿How can I use the angular services without get the error?
You can write like this. Because you are not sending any parameter to the url. So I think this is a good way to do this. just try it may work for you.
$http.post('http://www.myurl.com').
success(function(data) {
//success Response here
});
You need to allow OPTIONS method on your server side. Before every GET, POST, PUT, DELETE... requests an OPTIONS request is launched.
I advise you to disable your "chrome extension to add CORS", to have the same configuration of your final users.

Issues with calling uber-api products with angularJS

I am trying to test out the uber-api products rest endpoint and can't get a successful response using angular. If I paste the $http.get url in the browser it works. However I always get an error response through angularjs. The jsfiddle below is a stripped example of what I'm trying to accomplish.
http://jsfiddle.net/t3kcwc7y/630/
function UberCtrl($scope, $http) {
$http.get('https://sandbox-api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823&server_token=<token_here>')
.success(function(data) {
console.log('success');
$scope.uberData = data;
})
.error(function(data) {
console.log('error');
$scope.uberData = 'Error: ' + data;
});
}
I was unable to find a existing jsfiddle/plunker example so sorry if this has already been covered. Thanks in advance.
Some side notes, when testing in chrome I get "No 'Access-Control-Allow-Origin' header is present on the requested resource" which appears to be chrome specific CORS error. It works in firefox. My ultimate goal is to execute this from salesforce/force.com and support on any browser. I'm not sure if the CORS error is due to jsfiddle or not.
Please see the example for using the Uber API from the browser with CORS support:
https://developer.uber.com/docs/rides/api-reference
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://api.uber.com/v1/products?latitude=37.7759792&longitude=-122.41823');
xhr.setRequestHeader("Authorization", "Token YOUR_SERVER_TOKEN");
xhr.send();

can't access cookies on a rest response in angular

I have an angular front end with a webapi back end. I have implemented OAuth v2 security using OWIN/Identity and JWT tokens (thanks to Taiseer Joudeh's blogs). My burden is that we still have legacy pages that require a specific cookie. I have augmented the Http Response from WebApi to include that cookie when the JWT token is returned from a login request. I have verified the cookie is in the response header.
My problem is that I am unable to see the cookie inside my angular response handler where I will push it to the browser. I have tried each of the following based on suggestions I found elsewhere within StackOverflow but so far visibility of the cookie within the .js code has eluded me (alternate attempts have been commented out but left in for completeness). I have also made sure I set the appropriate "allow" fields on the server by adding "Access-Control-Allow-Headers" to "set-cookie" and "Access-Control-Allow-Credentials" to "true" at the end of my ValidateClientAuthenticationContext(..) method.
What do I need to do to see the attached cookie on my webapi response? Is this a problem on the server or client? both?
in my authService.js file:
var _login = function (loginData) {
// this makes the data "form data"
var data = "grant_type=password&client_id=ngAuthApp&username=" + loginData.userName + "&password=" + loginData.password;
var deferred = $q.defer();
$http.post(serviceBase + 'oauth/token', data, { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } })
.success(function (response) {
localStorageService.set('authorizationData', { token: response.access_token, userName: loginData.userName });
_authentication.isAuth = true;
_authentication.userName = loginData.userName;
console.log($cookies);
//var xxx = $http.defaults.headers;
//var headers = $http.response.headers;
var ddc = $http.response.cookies;
$cookies.DDC = ddc;
deferred.resolve(response);
})
//.success(function (data, status, headers, config) {
// // any required additional processing here
// var results = [];
// results.data = data;
// results.headers = headers();
// results.status = status;
// results.config = config;
// deferred.resolve(results);
//})
.error(function (err, status) {
_logOut();
deferred.reject(err);
});
return deferred.promise;
};
in my custom OAuthProvider .cs file
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
// skipping over lots of code here
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Credentials", new[] { "true" });
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Headers", new[] { "authorization", "content-type", "set-cookie" });
context.Validated();
return Task.FromResult<object>(null);
}
According to the docs - see here
$http.post() method returns an HttpPromise future object. Your call to .post() returns a promise. Which according to the Deprecation Notice on the above referenced page :
The $http legacy promise methods success and error have been
deprecated. Use the standard then method instead. If
$httpProvider.useLegacyPromiseExtensions is set to false then these
methods will throw $http/legacy error.
So instead of .success() / error(), use this: (Copied from docs)
$http.post()
.then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
Also, if you haven't already tried this (according to the .post() call it doesn't appear to) set the responseType property of your $http configuration object. This sets the datatype of the response object returned. Otherwise the default of a DOM string is returned. It may not fix it but it could be a start.
This could also need the help of withCredentials property set. Test them out and see how it goes. Idea comes from the suggestion of bastijn.
Your $http call should also set the withCredentials flag to true to explicitly allow cookie sharing.
$http.post(url, {withCredentials: true, ...})
The withCredentials flag allows javascript to access the authenticated session of the user.
//edit
Now that I read your question again this is probably not your issue. The withCredentials is to,communicate your session to the server on the next request you make that requires the authenticated session. From your question it seems you want to validate in the js code that the cookie you verified is there is also reachable by code.
It turns out the error was in my assumptions. I expected that a cookie sent via a web service directly from embedded js code would be ignored by the browser. However, the response header has the "Set-Cookie" value in the header and the browser IS already pushing it to be with the rest of the cookies. I really didn't expect that.
I must add this has been a very useful question for me because it taught me a lot about web programming and how the browser works with http header values. I appreciate everyone's time!
Marcus

Error when accessing localhost api in chrome net::ERR_INSECURE_RESPONSE

I was trying to access api running in localhost using angular $resourses, chrome console gives me error saying ERR_INSECURE_RESPONSE.
I tried disabling web security in chrome. still same error. here is the angular factory that i used. How can I bypass this error and test my app.
ImpactPortal.factory('apiFactory', function ($resource) {
return $resource('https://localhost:8443/mifosng-provider/api/v1/client_impact_portal', {}, {
query: {
method: 'GET',
params: {},
isArray: true
}
})
});
Enabling CORS in Angular.js
var myApp = angular.module('myApp', [
'myAppApiService']);
myApp.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
]);
A server supporting CORS must respond to requests with several access control headers:
Access-Control-Allow-Origin: "*"
By default, CORS requests are not made with cookies. If the server includes this header, then we
can send cookies along with our request by setting the withCredentials option to true.
Access-Control-Allow-Credentials (optional)
If we set the withCredentials option in our request to true, but the server does not respond
with this header, then the request will fail and vice versa.
Only try this:
Go to https://[your-domain].com and then chrome block you with the famous page:
Your connection is not private
So go down to ADVANVCED and then proceed.
Your certificate is probably self-signed.
Remember to do that for each Chrome session.
You must authenticate first and then send each request along with the auth token.
I am using RestAngular so my settings might look a little different from what you are working on.
This will go in your application config :-
RestangularProvider.setDefaultHeaders({ 'X-Mifos-Platform-TenantId': 'default' });
and something like this will go in your controller/service
var login = Restangular.all('authentication?username=mifos&password=password').post().then(function(user) {
console.log(user);
}, function() {
console.log("There was an error saving");
});
Error 501 (net::ERR_INSECURE_RESPONSE) - 501 Not Implemented
The server either does not recognize the request method, or it lacks the ability to fulfill the request. Usually this implies future availability (e.g., a new feature of a web-service API).
Can you confirm that curl request is working fine
curl -k --user damien#email.com:password https://localhost:8443/mifosng-provider/api/v1/client_impact_portal
If it is working fine:
ImpactPortal.factory('apiFactory', function ($resource) {
return $resource('https://localhost:8443/mifosng-provider/api/v1/client_impact_portal', {}, {
query: {
method: 'JSONP',
params: {},
isArray: true
}
})
});
Try following this tutorial that consume an external API: http://www.toptal.com/angular-js/a-step-by-step-guide-to-your-first-angularjs-app

angularjs $http post not working with Chrome browser

I'm trying to post an object to my rest service using angularjs.
Unfortunately it isn't working with Google's Chrome browser. Firefox and Internet Explorer work perfectly fine!
Does anyone have an idea what could be the problem?
Heres my Frontend -call:
$scope.saveAssignment = function (cap, aId, wId, hId) {
//all the parameters are strings
var postData = {
assignmentId: aId,
status: "CLOSED",
startDate: new Date(),
endDate: new Date(),
captionText: cap,
workerId: wId,
segment_Id: hId
};
var header ={
'Content-Type': 'application/json; charset=utf-8'
};
$http.post("https://localhost:8443/rest/v1/saveAssignment", postData, header)
.success(function (data, status, headers, config) {
console.log("IN SAVE ASSIGNMENTS - SUCCESS");
console.log(status);
})
.error(function (data, status, headers, config) {
console.log("ERROR!");
//As a response I get data = '' and status = 0
})
}
I have the same problem if I deploy it (independent of localhost or not).
On the server-side (JPA), I'm accepting the call with:
#Path("saveAssignment")
public class SaveAssignment{
#POST
#Consumes(MediaType.APPLICATION_JSON)
public Response saveAss(String assJson) {
System.out.println("TEST");
......
......
}
But not even the print statement "TEST" gets executed...
UPDATE
It looks like it has to be a CORS issue...
Chrome is only sending an OPTION request instead of an POST...
Idea how to fix this?
I already tried
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
but without succes... :(
UPDATE 2
Unfortunately I still don't manage to get it working. So I did a workaround by consciously excluding users with a Chrome browser from doing this post on my page (i.e. seeing the entire page)... (I used it for Amazon's Mechanical Turk, so it's not that severe). But it's not a solution for the origin problem... :-(
To exclude users with Google's Chrome browser I added the following:
$scope.chrome;
$scope.setIsChrome = function(){
var chromium = window.chrome;
var vendorName = window.navigator.vendor;
if(chromium !== null && vendorName === "Google Inc.") {
$scope.chrome = true;
} else {
$scope.chrome = false;
}
}
You have to check additionaly for the vendor name, since the Opera browser return true for "window.chrome" as well...
Is your angular app served via same HTTPS server? If localhost:8433 has self-signed or not matching certificate then that may be your problem as Chrome usually displays security exception page in such case.
Just open any URL starting with https://localhost:8443/ as normal page an then confirm security exceptions. That should help.
Update:
If you use iframe then the embedded page may be restricted by sandbox: http://msdn.microsoft.com/en-us/hh563496.aspx

Resources