How to enable cors request with angular.js-resource - angularjs

I have an angular.js application and i need to do CORS request.
I want to define my rest services "the angular" using angular resources, described here: http://docs.angularjs.org/tutorial/step_11.
But i haven't found a way to get this working.
On google i found the following sample code: http://jsfiddle.net/ricardohbin/E3YEt/, but this seems not to work with angular-resources.
this is my app.js
'use strict';
angular.module('corsClientAngularApp', ['helloServices'])
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
})
.otherwise({
redirectTo: '/'
});
});
this is my services.js with the rest services
angular.module('helloServices', ['ngResource']).
factory('Hello', function($resource){
return $resource('http://localhost:8080/cors-server/hello/:name', {}, {
query: {method:'GET', params:{name:'name'}, isArray:false}
});
});
This is my main.js with the controller using the $http, this works!:
'use strict';
angular.module('corsClientAngularApp')
.controller('MainCtrl', function ($scope, $http, Hello) {
$http.defaults.useXDomain = true;
$http.get('http://localhost:8080/cors-server/hello/stijn')
.success(function(data) {
$scope.hello = data;
});
});
This is another version of my main.js using angular resources. This does NOT work :(
'use strict';
angular.module('corsClientAngularApp')
.controller('MainCtrl', function ($scope, $http, Hello) {
$http.defaults.useXDomain = true;
$scope.hello = Hello.query({name:'stijn'});
});
This is are the headers from the working request (from chrome devtools):
Request URL:http://localhost:8080/cors-server/hello/stijn
Request Method:OPTIONS
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, origin, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:8080
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Response Headers
Access-Control-Allow-Headers:accept, origin, x-requested-with
Access-Control-Allow-Methods:GET
Access-Control-Allow-Origin:*
Content-Length:0
Date:Thu, 25 Apr 2013 10:42:34 GMT
Server:Apache-Coyote/1.1
And these are the headers from the NOt working request:
Request URL:http://localhost/cors-server/hello/stijn
Request Method:OPTIONS
Status Code:200 OK
Request Headers
Accept:*/*
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding:gzip,deflate,sdch
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, origin, x-requested-with
Access-Control-Request-Method:GET
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Response Headers
Allow:GET,HEAD,POST,OPTIONS,TRACE
Connection:Keep-Alive
Content-Length:0
Content-Type:text/plain
Date:Thu, 25 Apr 2013 10:41:12 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.2.22 (Win32)
It looks like the request url is wrong when using angular-resources. But why?
Thanks!

URL for $resource accepts using colon for parameters. Therefore when using port in url you need to escape the colon for port. This is explained in $resource docs

Related

spring RESTcontroller to accept dataURI

I am running into a issue of using angularjs ng-img-crop and Spring-boot REST web service.I want to upload an image file from ng crop to my backend web service.
I tried writing a spring controller but it failed and I couldnt find a good tutorial for this. help me resolve this basic request.
Thanks !!!
app.js
angular.module('myApp', [
'ngRoute',
'myApp.view1',
'myApp.view2',
'myApp.version',
'ngImgCrop'
])
.controller('Ctrl',['$scope','notify', function($scope,notify) {
$scope.myImage='';
$scope.myCroppedImage='';
var handleFileSelect=function(evt) {
var file=evt.currentTarget.files[0];
var reader = new FileReader();
reader.onload = function (evt) {
$scope.$apply(function($scope){
$scope.myImage=evt.target.result;
});
};
reader.readAsDataURL(file);
};
angular.element(document.querySelector('#fileInput')).on('change',handleFileSelect);
$scope.submit=function() {
notify($scope.myCroppedImage);
};
}]).
factory('notify',['$http', function($http) {
return function(myCroppedImage) {
var name = 'vishnu';
$http.post('http://localhost:8080/imageUpload', myCroppedImage)
.success(function(data, status, headers, config) {
alert("success");
})
.error(function(data, status, headers, config) {
alert("fail");
});
}
}])
controller.java
#RequestMapping(value="/imageUpload",method=RequestMethod.POST)
#ResponseBody
public String imageUpload(#RequestBody MultipartFile data){
return "success";
}
when I run with the following request, I got some exception in the web service.
Remote Address:127.0.0.1:8080
Request URL:http://localhost:8080/imageUpload
Request Method:POST
Status Code:500 Internal Server Error
Request Headersview source
Accept:application/json, text/plain, /
Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8
Connection:keep-alive
Content-Length:1850
Content-Type:application/json;charset=UTF-8
Host:localhost:8080
Origin:file://
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36**
Request payload
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAFIklEQVR4Xu3VsRHAMAzEsHj/pTOBXbB9pFchyLycz0eAwFXgsCF.......
Response header
Connection:close
Content-Type:application/json;charset=UTF-8
Date:Fri, 24 Apr 2015 12:40:35 GMT
Server:Apache-Coyote/1.1
Transfer-Encoding:chunked
Exception in java
org.springframework.web.multipart.MultipartException: The current request is not a multipart request
First of all your controller should looks like:
public ResponseEntity<Response> fileUpload(#RequestParam("file") MultipartFile file) {
Use #RequestParam instead of #RequestBody, and send the file in a parameter with the same name you're using in the annotation.
Moreover, your request should be sent with type multipart/form-data. For example, a common html for would be:
<form method="POST" enctype="multipart/form-data" action="your url">

AngularJS - Can't pass a header on a $http request

I'm trying to do requests to a RestAPI coded with Codeigniter 3. Access-Control-Allow-Origin and Access-Control-Allow-Headers are set to "*". The API has been successfully tested on Postman.
I'm coding a Web App using AngularJS, and trying to do requests to that API. The following code works properly:
api_service.getUsers = function() {
return $http({
method : 'GET',
url : url + '?dd-api-key=' + api_key
});
}
As this other code functions well too:
api_service.getUsers = function() {
return $http.get(url + '?dd-api-key=' + api_key);
}
But I need to send the API key as a header and not in the URL. So I wrote the function this way:
api_service.getUsers = function() {
return $http({
method: 'GET',
url: url,
headers: {
'accept': undefined,
'dd-api-key': api_key
}
});
}
That code doesn't work. Google Chrome console displays me this:
OPTIONS http://www.myweb.com/api/v1/users
XMLHttpRequest cannot load http://www.myweb.com/api/v1/users. Invalid HTTP status code 403
And at the network tab it shows that the request uses a method type 'OPTIONS', not a 'GET' method.
The Response Headers are:
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Connection:keep-alive
Content-Language:es-ES
Content-Length:45
Content-Type:application/json; charset=utf-8
Date:Wed, 25 Mar 2015 01:45:09 GMT
Expires:Thu, 19 Nov 1981 08:52:00 GMT
Pragma:no-cache
Server:nginx/1.6.2
And the Request Headers are:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:es-ES,es;q=0.8,en;q=0.6
Access-Control-Request-Headers:dd-api-key
Access-Control-Request-Method:GET
Connection:keep-alive
Host:www.myweb.com
Origin:http://127.0.0.1:55652
Referer:http://127.0.0.1:55652/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36
Excuse me if my english is not correct.
Many thanks.
you should add header with this:
$http.defaults.headers.common.dd-api-key = api_key;
You can add it in some config as global.

AngularJS Satellizer jwt CORS issue when authenticated

i'v got weird behaviour of my code. I'm using Satellizer to authenticate user and when user is not authenticated when i execute this code:
$http.get('http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX')
.success(function (data) {
console.log(data);
});
my request is ok and i get data
headers:
Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Host:eune.api.pvp.net
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
but when i authenticate user and try to do same request i get:
XMLHttpRequest cannot load http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXX. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. The response had HTTP status code 401.
and headers of this request looks like:
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, authorization
Access-Control-Request-Method:GET
Connection:keep-alive
Host:eune.api.pvp.net
Origin:http://localhost:9000
Referer:http://localhost:9000/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.93 Safari/537.36
my app.config
.config(function ($urlRouterProvider, $stateProvider, $httpProvider, $authProvider, API_URL) {
$urlRouterProvider.otherwise('/');
... some routes ...
$authProvider.loginUrl = API_URL + 'login';
$authProvider.signupUrl = API_URL + 'register';
$authProvider.google({
clientId: 'secret',
url: API_URL + 'auth/google'
});
$authProvider.facebook({
clientId: 'secret',
url: API_URL + 'auth/facebook'
});
// $httpProvider.interceptors.push('authInterceptor');
})
So how should i fix it? I suppose that those headers with Access-Control are the reason, but how should i handle it?
You could try putting the following in the satellizer config:
$authProvider.httpInterceptor = false;
Adding skipAuthorization property in config block might be helpful:
$http.get('http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX', {
skipAuthorization: true
})
.success(function (data) {
console.log(data);
});
I usually work with the config block by preference. This is how it would look.
//configuration block method:
$http({
method: 'GET',
url: 'http://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/somename?api_key=XXXXXXXXXXXXXXXXX',
skipAuthorization: true
});
Good Luck.
Ok i figured it out. As i supposed Satellizer registers new interceptor, which adds some headers and that's why it doesn`t work. This is satellizer code :
.config(['$httpProvider', 'satellizer.config', function($httpProvider, config) {
$httpProvider.interceptors.push(['$q', function($q) {
var tokenName = config.tokenPrefix ? config.tokenPrefix + '_' + config.tokenName : config.tokenName;
return {
request: function(httpConfig) {
var token = localStorage.getItem(tokenName);
if (token && config.httpInterceptor) {
token = config.authHeader === 'Authorization' ? 'Bearer ' + token : token;
httpConfig.headers[config.authHeader] = token;
}
return httpConfig;
},
responseError: function(response) {
return $q.reject(response);
}
};
}]);
}]);
i handled it by changing one lane to this:
if (token && config.httpInterceptor && httpConfig.rawReq !== true) {
and i pass in my httpConfig option rawReq: true
but this is not nice. Is there posibility to disable specific interceptor ?

AngularJS http request doesn't send session cookie for CORS

My script is:
<script>
function eventController($scope, $http) {
$http.get("http://example.com/api/Event", {withCredentials: true})
.success(function (response) {
$scope.events = response;
});
}
</script>
Request header from Fiddler:
GET http://example.com/api/Event HTTP/1.1
Host: example.com
Connection: keep-alive
Cache-Control: max-age=0
Accept: application/json, text/plain, */*
Origin: http://www.example.com
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
Referer: http://www.example.com/Home/Event
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
I need a authentication session cookie to be sent with this request.
It only sends cookie when the url of the webpage has no www in the front.
I have found a similar question in this site and the answer is:
.config(function ($routeProvider, $httpProvider) {
$httpProvider.defaults.withCredentials = true;
//rest of route code
But where do I put this code in my script?
The web application I'm developing is an ASP.NET MVC5 app with Web Api 2.
That configuration needs to be injected into the angular module, like this:
// get an existing module by name
var app = angular.module('app');
// inject $httpProvider configuration
app.config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});
It turns out that my AngularJS script works fine (Just pass {withCredentials: true} as a parameter in the $http.get method). What went wrong was that my MVC application doesn't store session cookie in the subdomain. So I fixed it by adding CookieDomain in the CookieAuthenticationOptions.

$http.post Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers error

I'm working on a app using Ionic Framework.
On the backend i wrote a Flask Application for api which looks like below:
#API.route("/saverez",methods=["POST","OPTIONS"])
#crossdomain(origin='*', headers="*",methods="*")
#render_api
def saver():
.....
I got errors while posting json to api.
var headers = {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS',
'Accept': 'application/json'
};
$http({
method: "POST",
headers: headers,
url: url+ '/api/saverez',
data: $scope.form
}).success(function (result)
console.log(result);
}).error(function (data, status, headers, config) {
console.log(data);
console.log(status);
console.log(headers);
console.log(config);
});
So this gives me the error:
XMLHttpRequest cannot load http://myurl/api/saverez. Request header field Access-Control-Allow-Origin is not allowed by Access-Control-Allow-Headers.
I googled it and then i found this snippet:
http://flask.pocoo.org/snippets/56/
I also added headers to my nginx conf like below:
location ~* \.(eot|ttf|woff)$ {
add_header Access-Control-Allow-Origin *;
}
Tried everything in that documentation and also evertyhing i found on google but sadly it didn't do any good.
How can i set the right headers for all origins ? I also use google pagespeed does it can cause this issue ?
Thanks in advance.
--- EDIT ---
Chrome network output
Remote Address:myip
Request URL:http://myurl/api/saverez
Request Method:OPTIONS
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:access-control-allow-origin, accept, access-control-allow-methods, content-type
Access-Control-Request-Method:POST
Cache-Control:no-cache
Connection:keep-alive
Host:myurl
Origin:http://192.168.1.46:8100
Pragma:no-cache
Referer:http://192.168.1.46:8100/
User-Agent:Mozilla/5.0 (iPhone; CPU iPhone OS 7_0 like Mac OS X; en-us) AppleWebKit/537.51.1 (KHTML, like Gecko) Version/7.0 Mobile/11A465 Safari/9537.53
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:*
Access-Control-Allow-Methods:*
Access-Control-Allow-Origin:*
Access-Control-Max-Age:21600
Allow:POST, OPTIONS
Content-Length:0
Content-Type:text/html; charset=utf-8
Date:Thu, 28 Aug 2014 13:26:11 GMT
Server:nginx/1.6.0
In my app module config section I have the following:
angular.module('starterapp', ['ionic'])
.config(function ($stateProvider, $httpProvider, $urlRouterProvider) {
// We need to setup some parameters for http requests
// These three lines are all you need for CORS support
$httpProvider.defaults.useXDomain = true;
$httpProvider.defaults.withCredentials = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
}
That is all you need to have to make all the HTTP requests work with CORS. This of course assumes you have made your backend.
You adding those additional headers would not be allowed according the w3c specification for XMLHTTPRequest as they may only be added by the host browser.
PaulT's answer got me very close to solving this problem for myself, but I also had to explicitly add the Content-Type for my post operations.
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
Hope this helps.
I got it working by just adding JSONP as the method
$resource(
'http://maps.google.com/maps/api/geocode/json?address=:address&sensor=false',
{},
{
get: {
method: 'JSONP',
}
});

Resources