backbonejs + cors and save() method - backbone.js

I'm trying to execute a POST throw the save method. Here is my model.
app.Models.Dummy = Backbone.Model.extend({
initialize: function () {
url = 'http://anotherdomain/Hello/';
},
});
When i execute:
dummy.save({text : "greg"}, {
success : function(){
console.log('Ok!');
},
error: function(){
console.log('Error');
}
});
The request is fired with an OPTIONS header (code 200) but the POST request is never fired.
However When i execute:
$.ajax({
type: 'POST',
url: "http://anotherdomain/Hello/",
data: {text:"greg"},
success: function(r) { alert(r.Result) },
dataType: "application/json"
});
it's works!
Does i need to override something in backbone?
EDIT:
The request is:
OPTIONS http://anotherdomain/Hello/ HTTP/1.1
Host: anotherdomain
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:17.0) Gecko/17.0 Firefox/17.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: fr,fr-fr;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive
Origin: http://mydomain
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type
Pragma: no-cache
Cache-Control: no-cache
and the response is:
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 0
Server: Microsoft-IIS/7.5
Set-Cookie: ARRAffinity=611c389e4fd6c5d83202b700ce5627f6e0850faf0604f13c25903b4662919f36;Path=/;Domain=anotherdomain
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
X-Powered-By: ARR/2.5
X-Powered-By: ASP.NET
Date: Wed, 05 Dec 2012 18:44:27 GMT

That's not a valid OPTIONS response for CORS. The response needs to include headers that tell the browser what's allowed. For example (taken from MDN):
Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER
I know you said that the $.ajax worked but based on this CORS response I doubt that is accurate and suggest you double check. Under the covers, backbone is itself just using $.ajax

Related

How to make CORS origin call request from rally sdk (custom html code)?

I'm developing a custom html dashboard using the rally sdk and I want to populate one of the field data from a CORS origin request call.
Can you please provide some examples/links how to make CORS call using rally sdk custom html code?
I tried via ajax call it gives me 403 exception.
var usChangeSets = story.getCollection('Changesets');
console.log('usChangeSets--',usChangeSets);
usChangeSets.load({
fetch : ['Author', 'Message', 'Uri'],
callback: function(records, operation, success){
Ext.Array.each(records, function(changeset){
//Ajax api call to get details from external link
var blink ="https://[sonarqube]/job/Appdev/job/TestProject/api/json";
Ext.Ajax.request({
url: blink,
method :'GET',
crossDomain: true,
withCredentials: true,
headers : {
'Authorization': 'Basic dsasfsfxfhfj',
'Content-Type': 'application/json;charset=UTF-8',
'Access-Control-Allow-Origin' : '*'
},
success: function(response){
var backToJs=JSON.parse(response.responseText);
console.log('resp data-',backToJs);
//console.log(backToJs['QueryResult'].Results);
},
failure: function(response) {
console.log('ajax call failure');
}
});
}
}
}
You need to configure your external server to allow CORS requests. The browser will automatically add the origin header to your request and then your server should respond with the appropriate cors headers (Access-Control-Allow-Origin).
Here's an example of how the rally server responds to a request from a different origin:
% http https://rally1.rallydev.com/slm/webservice/v2.0/testcaseresult/54277371431 zsessionid:_5507Kn8 origin:localhost -v
GET /slm/webservice/v2.0/testcaseresult/54277371431 HTTP/1.1
Accept: */*
Accept-Encoding: gzip, deflate
Connection: keep-alive
Host: rally1.rallydev.com
User-Agent: HTTPie/0.9.9
origin: localhost
zsessionid: _55GAn8
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: localhost
Access-Control-Expose-Headers:
CF-RAY: 38cbe03c4dd45005-DEN
Cache-Control: private,max-age=0,must-revalidate
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 623
Content-Type: application/json; charset=utf-8
Date: Fri, 11 Aug 2017 14:27:29 GMT
ETag: "0b0e0cdae135fc6cd32fa496d7660c756"
Expires: Thu, 01 Jan 1970 00:00:00 GMT
P3P: CP="NON DSP COR CURa PSAa PSDa OUR NOR BUS PUR COM NAV STA"
RallyRequestID: qs-app-103xz471u80pea8opfovz9g8gv.qs-app-1014978663
Server: cloudflare-nginx
Set-Cookie: __cfduid=d604a6a0fa131613b997640ead95cc5171502461649; expires=Sat, 11-Aug-18 14:27:29 GMT; path=/; domain=.rallydev.com; HttpOnly
Set-Cookie: JSESSIONID=qs-a0;Path=/;Secure;HttpOnly
Set-Cookie: SUBBUCKETID=209;Path=/;Domain=rally1.rallydev.com;Secure;HttpOnly
Set-Cookie: SUBSCRIPTIONID=209;Path=/;Domain=rally1.rallydev.com;Secure;HttpOnly
Set-Cookie: SERVERID=319fca23748f5704e88bd8741ae60476b188cf5e; path=/
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload;
Vary: Accept-Encoding
X-XSS-Protection: 1; mode=block

angularjs: $http basic authentication

I tried angular.js and started with a web-ui for a restful api (using http basic auth). It is really nice and all except the authorization works.
Up to now I am using $http.defaults.headers.common.Authorization to set the password, but mostly the browser opens his default login-form for http-basic-auth. Another strange behaviour is that the angular-request does not contain a Authorisation-Header (neither OPTIONS nor the GET-request). I also tried to set this header on each request with the header-config, but this also didn't work.
Are there some special headers I have to set? Or do I have to set $http.defaults.headers.common.Authorization in a special context?
tools.factory('someFactory', function ($http, Base64) {
//...
factory.checkAuth = function (username, password) {
storeCredentials(username, password);
factory.initConnection();
return factory.getData();
};
factory.initConnection = function(){
var credentials = loadCredentials();
factory.authHeader = 'Basic ' + Base64.encode(credentials.username + ':' + credentials.password);
$http.defaults.headers.common.Authorization = factory.authHeader;
};
factory.getData = function () {
return $http({
method: 'GET',
url: urlBase + '/happening',
headers: {
// 'Authorization': factory.authHeader
}
});
};
Request header:
OPTIONS /v8/happening HTTP/1.1
Host: api.gospry.com
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://web.gospry.com
User-Agent: [..]
Access-Control-Request-Headers: accept, authorization
Accept: */*
Referer: http://web.gospry.com/
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
Response header:
The backend was slightly modified to support CORS (Access-Control-headers and preflight-request-support).
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: http://web.gospry.com
Access-Control-Allow-Methods: POST, GET, PUT, PUSH, OPTIONS, DELETE
Access-Control-Max-Age: 3600
Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Authorization
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
Strict-Transport-Security: max-age=31536000 ; includeSubDomains
X-Frame-Options: DENY
Set-Cookie: JSESSIONID=2DDC92A1B0DC57C221CDC3B7A5DC1314; Path=/v8/; Secure; HttpOnly
WWW-Authenticate: Basic realm="Realm"
X-Content-Type-Options: nosniff
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH
Content-Length: 0
Date: Wed, 08 Apr 2015 18:04:04 GMT
I use an interceptor. I can't spot the issue in your code but here is what I am using:
authModule.factory('CeradAuthInterceptor',
['CeradAuthManager', function ( authManager)
{
return {
request: function (config)
{
config.headers = config.headers || {};
if (authManager.authToken)
{
config.headers.Authorization = 'Bearer ' + authManager.authToken;
}
return config;
}
};
}]);
appModule.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push('CeradAuthInterceptor');
}]);
The issue you describe with the login-form is explained in the AngularJS Tips and Tricks Using ngResource with a workaround. See the Basic Authentication section:
A workaround, if appropriate, is to tell your web server to return something other than 401 on an authentication failure, and go from there. In AngularJS, a 500 (for example) will cause the $http promise to be rejected and you can handle it however you’d like. This is not recommended if you actually ever need the login prompt to occur!

AngularJS $http seems to not respond correctly when I am using CORS

I have an AngularJS application. It sends out requests to another server for data and so there's an OPTIONS request goes out with every $HTTP call.
When I check with fiddler there are two calls. The Options that always returns a 200 OK and then the data call.
However when I check the $HTTP it seems that it's getting the first request ( the options request ) and not getting the second request the one with real data.
Can someone point me in the right direction with this?
Here's one example of the code that is not responding correctly:
.factory('isUsernameAvailable', function (appConstant, $q, $http) {
return function (username) {
var deferred = $q.defer();
// if (!angular.isDefined(username) || username == null || username == "" || username.length < 6 ) return deferred.resolve();
var url = appConstant.baseUrl + '/api/user/existsByName';
$http({
url: url,
method: "PUT",
data: {
userName: username
}
}).then(function (data) {
// Found the user, therefore not unique.
deferred.reject("User name is taken");
}, function (data) {
// User not found, therefore unique!
deferred.resolve();
});
return deferred.promise;
}
})
I expect it to be returning as success or failure depending on if it finds the username. But in this case it always responds as a fail/error.
Here are the requests being made:
OPTIONS http://localhost:3048/api/user/existsByName HTTP/1.1
Host: localhost:3048
Connection: keep-alive
Access-Control-Request-Method: PUT
Origin: http://localhost:2757
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Access-Control-Request-Headers: accept, authorization, content-type
Accept: */*
Referer: http://localhost:2757/Auth/register
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
giving:
HTTP/1.1 200 OK
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://localhost:2757
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: PUT
Access-Control-Allow-Headers: content-type
X-SourceFiles: =?UTF-8?B?QzpcR1xhYmlsaXRlc3Qtc2VydmVyXFdlYlJvbGVcYXBpXHVzZXJcZXhpc3RzQnlOYW1l?=
X-Powered-By: ASP.NET
Date: Mon, 12 Jan 2015 17:52:12 GMT
Content-Length: 0
Then:
PUT http://localhost:3048/api/user/existsByName HTTP/1.1
Host: localhost:3048
Connection: keep-alive
Content-Length: 35
Accept: application/json, text/plain, */*
Origin: http://localhost:2757
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Authorization: null
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:2757/Auth/register
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
{"userName":"abdddcdefgg#live.com"}
giving:
HTTP/1.1 404 Not Found
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.0
Access-Control-Allow-Origin: http://localhost:2757
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: X-Custom-Header
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcR1xhYmlsaXRlc3Qtc2VydmVyXFdlYlJvbGVcYXBpXHVzZXJcZXhpc3RzQnlOYW1l?=
X-Powered-By: ASP.NET
Date: Mon, 12 Jan 2015 17:52:12 GMT
Content-Length: 0
The problem is even if the second request returns a 200 when I debug the success and error functions it still goes to the error function all of the time.
You should use JSONP to do cross domain JSON calls. Look at the documentation here: https://docs.angularjs.org/api/ng/service/$http#jsonp. Also, your referring page and the response from the OPTIONS request must have the appropriate CORS headers set or else the browser will refuse to send the request here are the header settings that I use.
Access-Control-Allow-Headers:Content-Type, Authorization, Content-Length, X-Requested-With, Accept, x-csrf-token, origin
Access-Control-Allow-Methods:GET,PUT,POST,DELETE,OPTIONS
Access-Control-Allow-Origin:*
To call $http.jsonp with a PUT request, you would set up a configuration such as
var config = {
method: 'POST',
data: { test: 'test' }
};
and then pass that into the $http.jsonp call
$http.jsonp('http://example.com', config);
Here is more documentation https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS and http://en.wikipedia.org/wiki/JSONP

Required Parameter is missing grant_type Google oauth2.0 AngularJS and Cordova inappbrowser

I am using Cordova's inappbrowser and integrating Google oauth2.0. Once I get the authorization code I make a post request to get my token. NO MATTER what I try I always get a 400 error with "Required Parameter is missing grant_type". I'm encoding uri, I'm setting the right headers but to no avail... can anyone help?
$http({
method: 'POST',
url: 'https://accounts.google.com/o/oauth2/token',
params:{code:authorization_code[0],
client_id:options.client_id,
client_secret:options.client_secret,
redirect_uri:options.redirect_uri,
grant_type:'authorization_code'},
headers:{
'Content-Type':'application/x-www-form-urlencoded',
}
}).success(function(data,status,headers,config){
deferred.resolve(data);
}).error(function(data, status,headers,config){
console.log('data, status, headers,config',data,status,headers,config);
deferred.reject(response.responseJSON);
});
and this is the output from the Chrome dev Console when I try to make the request
Request URL:https://accounts.google.com/o/oauth2/token?client_id=736406995874-oh7o4cmaju3jgprllln97nf0p3pc1f91.apps.googleusercontent.com&client_secret=ysgrIV6mJXxritfXnRcclV_U&code=4%2FnITDK731NhavPePthrVA1eX8LHFC.ojUX9K7DpBYaEnp6UAPFm0HWDS5njgI&grant_type=authorization_code&redirect_uri=http:%2F%2Flocalhost
Request Method:POST
Status Code:400 Bad Request
Request Headers
POST https://accounts.google.com/o/oauth2/token?client_id=xxx-oh7o4cmaju3jgprllln97nf0p3pc1f91.apps.googleusercontent.com&client_secret=xxx&code=4%2FnITDK731NhavPePthrVA1eX8LHFC.ojUX9K7DpBYaEnp6UAPFm0HWDS5njgI&grant_type=authorization_code&redirect_uri=http:%2F%2Flocalhost HTTP/1.1
Accept: application/json, text/plain, /
Origin: file://
testing: testing
User-Agent: Mozilla/5.0 (Linux; Android 4.4.2; SCH-I535 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
Query String Parameters
client_id=xxx-oh7o4cmaju3jgprllln97nf0p3pc1f91.apps.googleusercontent.com&client_secret=xxx&code=4%2FnITDK731NhavPePthrVA1eX8LHFC.ojUX9K7DpBYaEnp6UAPFm0HWDS5njgI&grant_type=authorization_code&redirect_uri=http:%2F%2Flocalhost
Response Headers
HTTP/1.1 400 Bad Request
Pragma: no-cache
Date: Mon, 14 Jul 2014 06:35:22 GMT
Content-Encoding: gzip
X-Content-Type-Options: nosniff
Server: GSE
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Transfer-Encoding: chunked
Alternate-Protocol: 443:quic
X-XSS-Protection: 1; mode=block
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Wrong post request. The params property is used to set any additional request parameters to be appended to the URL query string. The params property is a JavaScript object with one property per request parameter to add.
Here for your reference.
You just need to send data/params in serialized (for angular use $httpParamSerializer)
$http({
method: 'POST',
url: 'https://accounts.google.com/o/oauth2/token',
params:$httpParamSerializer({code:authorization_code[0],
client_id:options.client_id,
client_secret:options.client_secret,
redirect_uri:options.redirect_uri,
grant_type:'authorization_code'}),
headers:{
'Content-Type':'application/x-www-form-urlencoded',
}
}).success(function(data,status,headers,config){
deferred.resolve(data);
}).error(function(data, status,headers,config){
console.log('data, status, headers,config',data,status,headers,config);
deferred.reject(response.responseJSON);
});

Angular $resource doesn't change method

I'm trying to configure a simple service with Angular.js and Couchdb
var App = angular.module('myapp', ['ngResource'], function(){});
App.factory('products', ['$resource', function($resource) {
var Products = $resource(
'http://localhost\\:5984/products/_all_docs',
{},
{ all: { method: 'GET'} }
);
return {
all: function() {
return Products.all();
}
};
}]);
When I call products.all() from my controller always I get
Request headers
OPTIONS /productos/_all_docs HTTP/1.1
Host: localhost:5984
Connection: keep-alive
Access-Control-Request-Method: GET
Pragma: no-cache
Cache-Control: no-cache
Origin: http://localhost:8000
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17
Access-Control-Request-Headers: accept, origin, x-requested-with
Accept: */*
DNT: 1
Referer: http://localhost:8000/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: es-419,es;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Response headers
HTTP/1.1 405 Method Not Allowed
Server: CouchDB/1.2.1 (Erlang OTP/R14B04)
Date: Tue, 29 Jan 2013 22:15:31 GMT
Content-Type: text/plain; charset=utf-8
Content-Length: 69
Cache-Control: must-revalidate
Allow: GET,HEAD,POST
Request URL:http://localhost:5984/productos/_all_docs
Request Method:OPTIONS
Status Code:405 Method Not Allowed
I can not imagine why it sends an OPTIONS method when I haven't declared that!
The OPTIONS method comes from doing a cross origin request. See Why am I getting an OPTIONS request instead of a GET request?. Even though both the host and the request is to localhost, the ports are different (5984, 8000). See Same origin host, different ports in JS.

Resources