$http.get not working in Angular with different URLs [duplicate] - javascript

I have created a demo using JavaScript for Flickr photo search API.
Now I am converting it to the AngularJs.
I have searched on internet and found below configuration.
Configuration:
myApp.config(function($httpProvider) {
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
Service:
myApp.service('dataService', function($http) {
delete $http.defaults.headers.common['X-Requested-With'];
this.flickrPhotoSearch = function() {
return $http({
method: 'GET',
url: 'http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=3f807259749363aaa29c76012fa93945&tags=india&format=json&callback=?',
dataType: 'jsonp',
headers: {'Authorization': 'Token token=xxxxYYYYZzzz'}
});
}
});
Controller:
myApp.controller('flickrController', function($scope, dataService) {
$scope.data = null;
dataService.flickrPhotoSearch().then(function(dataResponse) {
$scope.data = dataResponse;
console.log($scope.data);
});
});
But still I got the same error.
Here are some links I tried:
XMLHttpRequest cannot load URL. Origin not allowed by Access-Control-Allow-Origin
http://goo.gl/JuS5B1

You don't. The server you are making the request to has to implement CORS to grant JavaScript from your website access. Your JavaScript can't grant itself permission to access another website.

I had a similar problem and for me it boiled down to adding the following HTTP headers at the response of the receiving end:
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
You may prefer not to use the * at the end, but only the domainname of the host sending the data. Like *.example.com
But this is only feasible when you have access to the configuration of the server.

Try using the resource service to consume flickr jsonp:
var MyApp = angular.module('MyApp', ['ng', 'ngResource']);
MyApp.factory('flickrPhotos', function ($resource) {
return $resource('http://api.flickr.com/services/feeds/photos_public.gne', { format: 'json', jsoncallback: 'JSON_CALLBACK' }, { 'load': { 'method': 'JSONP' } });
});
MyApp.directive('masonry', function ($parse) {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.masonry({ itemSelector: '.masonry-item', columnWidth: $parse(attrs.masonry)(scope) });
}
};
});
MyApp.directive('masonryItem', function () {
return {
restrict: 'AC',
link: function (scope, elem, attrs) {
elem.imagesLoaded(function () {
elem.parents('.masonry').masonry('reload');
});
}
};
});
MyApp.controller('MasonryCtrl', function ($scope, flickrPhotos) {
$scope.photos = flickrPhotos.load({ tags: 'dogs' });
});
Template:
<div class="masonry: 240;" ng-controller="MasonryCtrl">
<div class="masonry-item" ng-repeat="item in photos.items">
<img ng-src="{{ item.media.m }}" />
</div>
</div>

This issue occurs because of web application security model policy that is Same Origin Policy Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. That means requester must match the exact host, protocol, and port of requesting site.
We have multiple options to over come this CORS header issue.
Using Proxy - In this solution we will run a proxy such that when request goes through the proxy it will appear like it is some same origin.
If you are using the nodeJS you can use cors-anywhere to do the proxy stuff. https://www.npmjs.com/package/cors-anywhere.
Example:-
var host = process.env.HOST || '0.0.0.0';
var port = process.env.PORT || 8080;
var cors_proxy = require('cors-anywhere');
cors_proxy.createServer({
originWhitelist: [], // Allow all origins
requireHeader: ['origin', 'x-requested-with'],
removeHeaders: ['cookie', 'cookie2']
}).listen(port, host, function() {
console.log('Running CORS Anywhere on ' + host + ':' + port);
});
JSONP - JSONP is a method for sending JSON data without worrying about cross-domain issues.It does not use the XMLHttpRequest object.It uses the <script> tag instead. https://www.w3schools.com/js/js_json_jsonp.asp
Server Side - On server side we need to enable cross-origin requests.
First we will get the Preflighted requests (OPTIONS) and we need to allow the request that is status code 200 (ok).
Preflighted requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if it uses methods other than GET or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
If you are using the spring just adding the bellow code will resolves the issue.
Here I have disabled the csrf token that doesn't matter enable/disable according to your requirement.
#SpringBootApplication
public class SupplierServicesApplication {
public static void main(String[] args) {
SpringApplication.run(SupplierServicesApplication.class, args);
}
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
};
}
}
If you are using the spring security use below code along with above code.
#Configuration
#EnableWebSecurity
public class SupplierSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll().antMatchers("/**").authenticated().and()
.httpBasic();
}
}

I encountered a similar problem like this, problem was with the backend . I was using node server(Express). I had a get request from the frontend(angular) as shown below
onGetUser(){
return this.http.get("http://localhost:3000/user").pipe(map(
(response:Response)=>{
const user =response.json();
return user;
}
))
}
But it gave the following error
This is the backend code written using express without the headers
app.get('/user',async(req,res)=>{
const user=await getuser();
res.send(user);
})
After adding a header to the method problem was solved
app.get('/user',async(req,res)=>{
res.header("Access-Control-Allow-Origin", "*");
const user=await getuser();
res.send(user);
})
You can get more details about Enabling CORS on Node JS

This answer outlines two ways to workaround APIs that don't support CORS:
Use a CORS Proxy
Use JSONP if the API Supports it
One workaround is to use a CORS PROXY:
angular.module("app",[])
.run(function($rootScope,$http) {
var proxy = "//cors-anywhere.herokuapp.com";
var url = "http://api.ipify.org/?format=json";
$http.get(proxy +'/'+ url)
.then(function(response) {
$rootScope.response = response.data;
}).catch(function(response) {
$rootScope.response = 'ERROR: ' + response.status;
})
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
Response = {{response}}
</body>
For more information, see
GitHub: CORS Anywhere
Use JSONP if the API supports it:
var url = "//api.ipify.org/";
var trust = $sce.trustAsResourceUrl(url);
$http.jsonp(trust,{params: {format:'jsonp'}})
.then(function(response) {
console.log(response);
$scope.response = response.data;
}).catch(function(response) {
console.log(response);
$scope.response = 'ERROR: ' + response.status;
})
The DEMO on PLNKR
For more information, see
AngularJS $http Service API Reference - $http.jsonp

Answered by myself.
CORS angular js + restEasy on POST
Well finally I came to this workaround:
The reason it worked with IE is because IE sends directly a POST instead of first a preflight request to ask for permission.
But I still don't know why the filter wasn't able to manage an OPTIONS request and sends by default headers that aren't described in the filter (seems like an override for that only case ... maybe a restEasy thing ...)
So I created an OPTIONS path in my rest service that rewrites the reponse and includes the headers in the response using response header
I'm still looking for the clean way to do it if anybody faced this before.

Apache/HTTPD tends to be around in most enterprises or if you're using Centos/etc at home. So, if you have that around, you can do a proxy very easily to add the necessary CORS headers.
I have a blog post on this here as I suffered with it quite a few times recently. But the important bit is just adding this to your /etc/httpd/conf/httpd.conf file and ensuring you are already doing "Listen 80":
<VirtualHost *:80>
<LocationMatch "/SomePath">
ProxyPass http://target-ip:8080/SomePath
Header add "Access-Control-Allow-Origin" "*"
</LocationMatch>
</VirtualHost>
This ensures that all requests to URLs under your-server-ip:80/SomePath route to http://target-ip:8080/SomePath (the API without CORS support) and that they return with the correct Access-Control-Allow-Origin header to allow them to work with your web-app.
Of course you can change the ports and target the whole server rather than SomePath if you like.

var result=[];
var app = angular.module('app', []);
app.controller('myCtrl', function ($scope, $http) {
var url="";// your request url
var request={};// your request parameters
var headers = {
// 'Authorization': 'Basic ' + btoa(username + ":" + password),
'Access-Control-Allow-Origin': true,
'Content-Type': 'application/json; charset=utf-8',
"X-Requested-With": "XMLHttpRequest"
}
$http.post(url, request, {
headers
})
.then(function Success(response) {
result.push(response.data);
$scope.Data = result;
},
function Error(response) {
result.push(response.data);
$scope.Data = result;
console.log(response.statusText + " " + response.status)
});
});
And also add following code in your WebApiConfig file
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);

we can enable CORS in the frontend by using the ngResourse module.
But most importantly, we should have this piece of code while making the ajax
request in the controller,
$scope.weatherAPI = $resource(YOUR API,
{callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
$scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if any);
Also, you must add ngResourse CDN in the script part and add as a dependency
in the app module.
<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>
Then use "ngResourse" in the app module dependency section
var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);

Related

Ionic app CORS No 'Access-Control-Allow-Origin' header is present, using Lumen API with CORS middleware

I am building an app which uses a Lumen API. On the Lumen project I have two files which I found on the internet whilst looking up how to handle CORS in Lumen.
CorsMiddleware.php:
<?php
namespace App\Http\Middleware;
class CorsMiddleware {
public function handle($request, \Closure $next)
{
$response = $next($request);
$response->header('Access-Control-Allow-Methods', 'HEAD, GET, POST, PUT, PATCH, DELETE');
$response->header('Access-Control-Allow-Headers', $request->header('Access-Control-Request-Headers'));
$response->header('Access-Control-Allow-Origin', '*');
return $response;
}
}
CatchAllOptionsRequestsProvider.php:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
/**
* If the incoming request is an OPTIONS request
* we will register a handler for the requested route
*/
class CatchAllOptionsRequestsProvider extends ServiceProvider {
public function register()
{
$request = app('request');
if ($request->isMethod('OPTIONS'))
{
app()->options($request->path(), function() { return response('', 200); });
}
}
}
These two files fixed my initial CORS issue. I am able to perform a GET and receive data from the API. But when I try a POST method to the API I once again get the following error: "No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8100' is therefore not allowed access."
Upon inspecting the network tab in chrome, There are two requests. The first is an OPTIONS request, which I believe is just to get the allowed headers from the server. The second request is my POST request with the correct payload. They both return a status code of 200 OK but I still get the Access-Control error mentioned above.
It works when using POSTMAN to send data to my API, but not when I use Ionic Serve in the browser
For those who are wondering, I am using Ionic's $http method for the call:
MORE CODE.......
var req = {
method: 'POST',
url: APIUrl + 'register',
timeout: timeout.promise,
data: {"name": "Michael"}
}
$http(req).then(function(res) {
.......MORE CODE
Might it be something to do with the server apache config? I have mod_rewrite enabled.
Any help on this would be greatly appreciated. Thanks
If you are in control of the server, you might need to set the required headers there. Depending on which server, this might help:
http://enable-cors.org/server.html

Ajax - "Access-Control-Allow-Origin" error in ember.js

I would like to know your opinion on the issue in this simple code in ajax, which has the problem Access-Control-Allow-Origin, already tried several ways defenir the ember "Access-Control-Allow-Origin": "* " but without success, so I wonder if someone with the same problem found a solution.
I use the url address localhost: 4200 and already tried with a subdomain of firebase in both cases the error was always the same.
The ajax request:
import Ember from 'ember';
import { isAjaxError, isNotFoundError, isForbiddenError } from 'ember-ajax/errors';
export default Ember.Controller.extend({
ajax: Ember.inject.service(),
actions: {
code() {
var cliente = '***';
var redirectUri = 'http://localhost:4200/teste';
var client_secret = '***';
var code = '***';
var grant_type = 'authorization_code';
var data =
"client_id=" + cliente +
"&redirect_uri=" + encodeURIComponent(redirectUri) +
"&client_secret=" + client_secret +
"&code=" + code +
"&grant_type=" + grant_type;
this.send('post', data)
},
post(data) {
this.get('ajax').post("https://login.live.com/oauth20_token.srf", {
method: 'POST',
headers: {
"Access-Control-Allow-Origin": "*",
"Content-Type": "application/x-www-form-urlencoded",
},
data: data,
dataType: 'JSON',
});
},
}});
My content Security Policy:
contentSecurityPolicy: {
'connect-src': "'self' http://localhost:4200 https://*.googleapis.com https://login.live.com/oauth20_token.srf",
'child-src': "'self' http://localhost:4200",
'script-src': "'self' 'unsafe-eval' https://login.live.com",
'img-src': "'self' https://*.bp.blogspot.com https://cdn2.iconfinder.com http://materializecss.com https://upload.wikimedia.org https://www.gstatic.com",
'style-src': "'self' 'unsafe-inline' ",
},
The error is:
XMLHttpRequest cannot load https://login.live.com/oauth20_token.srf. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.
This doesn't actually seem like an Ember related question. The problem you are having is exclusively backend related. For ajax requests to work backend should serve the proper 'Access-Control-Allow-Origin' header in response. Otherwise your browser would not accept such responses and throw an error that you are seeing. It's not Ember related in any way it's just how browsers work.
Now to fix this issue you would have to add the proper client server name to your backend 'Access-Control-Allow-Origin' headers. I.e. if you are going to serve your Ember app from https://example.com that is what you need to add to 'Access-Control-Allow-Origin' header.
So let's assume you just want the ways to bypass this messages.
There are plenty of browser extensions that would disable CORS check in your browser for development. This way would work just fine if you are using localhost but plan to move to real server in the future and have a way to actually set 'Access-Control-Allow-Origin' header on backend.
Let's assume you don't have any way to change the backend header now but desperately want to test how the client app would work on your remote https://example.com. You would have to setup a remote server to proxy all your requests to the target backend modifying the headers that are sent in response so your browser would accept them. This way you don't have to use any chrome extensions to disable CORS.
One of the simplest ways to setup such server would be to use the following package - https://www.npmjs.com/package/express-http-proxy . The configuration for your case would be pretty straightforward.
sample express app:
var proxy = require('express-http-proxy');
var app = require('express')();
app.use('/', proxy('www.example.com', {
intercept: function (rsp, data, req, res, callback) {
res.append('Access-Control-Allow-Origin', '*');
callback(null, data);
}}));
app.listen(3000, function () {
console.log('listening on port 3000');
});

Http request through a proxy server using angular js

Is it possible to call a web service though a proxy server using angular $http?
My webservices is hosted in my server and we have a proxy server is it possible that i can redirect my request through that proxy not by changing device property but by through code?
$http({
method: $scope.method,
url: $scope.url,
params: { "member_id": "998014437" }
})
.then(function (response) {
$scope.status = response.status,
$scope.data = response.data;
}, function (response) {
$scope.data = response.data || "Request failed";
$scope.status = response.status;
}
);
As far as I know there aren't any build in webproxy settings for XMLHttpRequest, so there aren't for angular $http too. The common practice for using a proxy on this matter is that you build a server side proxy page on your domain. Something like:
"/proxy.php?url=http://crossdomain.com/somedata.json"
This page basically make the web requests on server side and return the exactly same response to client with headers and everything. And then you make all your requests via this proxy page. Since the proxy url part is at the beginning of your actual url, you can customize this with a variable like url: proxyPrefix + $scope.url . If proxy prefix variable is empty, then the request will be done over the actual server.

ajaxPrefilter with Backbone

I develop a project using backbone, underscore, require .js and REST API.
I've got error Cross-Origin Request Blocked The Same Origin Policy disallows reading the remote resource at...
NOTE : I've configured Access-Control-Allow in server side already. Still, the error still appear.
I found a solution, using ajaxPrefilter, then here I've tried in my project :
router.js :
start: function() {
Backbone.history.start({pushState: true});
},
initialize: function() {
$.ajaxPrefilter( function( options, originalOptions, jqXHR ) {
options.url = options.url;
});
}
Here is my backbone view :
var _wl = new MyModel();
_wl.save(_item,{
success: function(res) {
console.log(res);
}
});
I still got `Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://example.com/api/MyWebs. This can be fixed by moving the resource to the same domain or enabling CORS.
Could any one tell me what did I wrong here?
Any helps and ideas would be appreciated.
Can you check if the reponse from http://example.com/api/MyWebs carries back correctly configured CORS headers like "Access-Control-Allow-Origin" ,""Access-Control-Allow-Headers",""Access-Control-Allow-Methods" e.t.c. This can be done by having the dev tools open in chrome/firefox and inspecting the response headers.
Here are a couple of things to ensure if CORS has been configured properly:
Response Headers:
Check if you have configured the Access-Control-Allow-Origin header properly. Initially you can set the value of it to "*" for testing purpose and then later on specify the specific host.
If you are using custom headers make sure that you have added them to the allowed list using "Access-Control-Allow-Headers". The custom headers names are specifed as a comma separated list.
If you want to support PUT,DELETE and POST requests with certain media types, then make sure that you add "Access-Control-Allow-Methods".
Server Side:
Check if you have added code to handle the pre-flight request that comes with OPTIONS method.
EG:
if(containerRequestContext.getRequest().getMethod().equalsIgnoreCase("OPTIONS")) {
// code to check if the request is made from a allowed origin and if everything is fine abort with success / forbidden.
}
Check if each response sent from the server is made with the above response headers correctly set.
EG:
Language/Framework: Jersey Framework,Java
Each response will pass thru the below Filter and the following response headers will be added to them.
#PreMatching
#Provider
public class SecurityResponseFilter implements ContainerResponseFilter {
private static final Logger LOGGER = Logger.getLogger(SecurityResponseFilter.class);
#Override
public void filter(ContainerRequestContext containerRequestContext,ContainerResponseContext containerResponseContext) throws IOException {
try {
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", "*");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE");
containerResponseContext.getHeaders().add( "Access-Control-Allow-Headers", "tk_a,tk_r" );
} catch (Exception e) {
LOGGER.error("Error occured while processing request.",e);
throw e;
}
}
}
In the client side if you need to send custom headers, you could do it as follows :
$.ajaxPrefilter(function(options,originalOptions,jqXHR) {
jqXHR.setRequestHeader("tk_a",$.cookie("tk_a"));
jqXHR.setRequestHeader("tk_r",$.cookie("tk_r"));
});

Angular $http.post and No 'Access-Control-Allow-Origin' header

I have two app with nodejs and angularjs.nodejs app has some code like this :
require('http').createServer(function(req, res) {
req.setEncoding('utf8');
var body = '';
var result = '';
req.on('data', function(data) {
// console.log("ONDATA");
//var _data = parseInput( data,req.url.toString());
var _data = parseInputForClient(data, req.url.toString());
switch (req.url.toString()) {
case "/cubes":
{
and this app host on http://localhost:4000.angularjs app host with node http-server module on localhost://www.localhost:3030.in one of my angularjs service i have some thing like this :
fetch:function(){
var data = '{somedata:"somedata"}';
return $http.post('http://localhost:4000/cubes',data).success(function(cubes){
console.log(cubes);
});
}
but when this service send a request to server get this error:
XMLHttpRequest cannot load http://localhost:4000/cubes. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3030' is therefore not allowed access.
so i search the web and stackoverflow to find some topic and i find this and this . according to these topics i change the header of response in the server to something like this :
res.writeHead(200, {
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
});
res.end(JSON.stringify(result));
but this dose'nt work.I try with firefox,chrome and also check the request with Telerik Fiddler Web Debugger but the server still pending and i get the Access Control Allow Origin error.
You do POST request, which generates preflight request according to CORS specification: http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/ and https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Your server should also respond to OPTIONS method (besides POST), and return Access-Control-Allow-Origin there too.
You can see it's the cause, because when your code creates request in Network tab (or in Fiddler proxy debugger) you should see OPTIONS request with ORIGIN header

Categories