Steps to activating CORS in AngularJS

I've put together a demonstration using JavaScript to interact with the Flickr photo search API. Now, I'm in the process of transitioning it to AngularJs, and after some research online, I have come across the following 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);
    });
});

Despite implementing these changes, I'm still encountering the same error message. In my attempts to solve this issue, I explored some helpful resources:

XMLHttpRequest cannot load URL. Origin not allowed by Access-Control-Allow-Origin

http://samurails.com/tutorial/cors-with-angular-js-and-sinatra/

Answer №1

When it comes to accessing data from another website, the server you are sending the request to must implement CORS in order for JavaScript on your website to gain access. Your JavaScript alone cannot give itself permission to interact with external sites.

Answer №2

After facing a similar issue, I discovered that the solution lies in including specific HTTP headers in the response of the receiving entity:

Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *

It is advisable to use the domain name of the sender instead of *. For example, *.example.com

Implementing this approach requires access to the server configuration.

Answer №3

Utilize the resource service for consuming flickr JSONP data:

var MyApplication = angular.module('MyApplication', ['ng', 'ngResource']);

MyApplication.factory('flickrImages', function ($resource) {
    return $resource('http://api.flickr.com/services/feeds/photos_public.gne', { format: 'json', jsoncallback: 'JSON_CALLBACK' }, { 'load': { 'method': 'JSONP' } });
});

MyApplication.directive('masonryLayout', function ($parse) {
    return {
        restrict: 'AC',
        link: function (scope, elem, attrs) {
            elem.masonry({ itemSelector: '.masonry-item', columnWidth: $parse(attrs.masonry)(scope) });
        }
    };        
});

MyApplication.directive('masonryItemElement', function () {
    return {
        restrict: 'AC',
        link: function (scope, elem, attrs) {
            elem.imagesLoaded(function () {
               elem.parents('.masonry').masonry('reload');
            });
        }
    };        
});

MyApplication.controller('GalleryController', function ($scope, flickrImages) {
    $scope.galleryItems = flickrImages.load({ tags: 'cats' });
});

Template:

<div class="masonry-layout: 240;" ng-controller="GalleryController">
    <div class="masonry-item" ng-repeat="item in galleryItems.items">
        <img ng-src="{{ item.media.m }}" />
    </div>
</div>

Answer №4

The reason for this problem is due to the security measure implemented by web applications known as the Same Origin Policy. This policy allows scripts from one website to access information on another website only if both websites share the same origin, including host, protocol, and port.

To address the CORS header issue, there are several solutions available:

  1. Using a Proxy - One solution is to set up a proxy that makes requests appear as if they are coming from the same origin. For example, if using nodeJS, the cors-anywhere package can be used for this purpose. More information can be found at 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);
    });
    
  2. JSONP - JSON with Padding (JSONP) is a technique for sending JSON data without encountering cross-domain issues. Instead of using XMLHttpRequest, it utilizes the <script> tag. More details can be found at https://www.w3schools.com/js/js_json_jsonp.asp.

  3. Server-Side Changes - On the server side, cross-origin requests need to be enabled. Preflighted requests, which send an HTTP OPTIONS request header to the target resource, determine whether the actual request is safe to send. Custom headers may need to be set in the request, such as X-PINGOTHER.

    If utilizing Spring, the following code snippet can help resolve the issue by allowing all origins:

    @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("*");
                }
            };
        }
    }
    

    For Spring Security users, the following configuration can be added along with the previous code snippet:

    @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();
        }
    
    }
    

Answer №5

Responding to my own query.

Resolving CORS issue with angular js + restEasy on POST

After exploring various options, I stumbled upon a workaround: Interestingly, Internet Explorer behaves differently by sending a direct POST request instead of initiating a preflight request for permission. I am still puzzled by why the filter failed to handle an OPTIONS request and sent default headers not specified in the filter (it appears to be an override specific to that scenario...perhaps a restEasy quirk).

To address this, I implemented an OPTIONS route in my rest service that manipulates the response to include the necessary headers using response header manipulation.

I am actively seeking a more elegant solution if anyone has encountered a similar challenge.

Answer №6

Encountering a similar issue, I found the problem to be with the backend setup. In my case, I was using a Node server with Express. The frontend (Angular) was sending a GET request like this:

   onGetUser(){
        return this.http.get("http://localhost:3000/user").pipe(map(
            (response:Response)=>{
                const user =response.json();
                return user;
            }
        )) 
    }

This resulted in an error, which you can see here.

The backend code using Express without headers initially looked like this:

app.get('/user',async(req,res)=>{
     const user=await getuser();
     res.send(user);
 })

The issue was resolved by adding a header to the method:

app.get('/user',async(req,res)=>{
    res.header("Access-Control-Allow-Origin", "*");
    const user=await getuser();
    res.send(user);
})

More information on enabling CORS for Node JS can be found here.

Answer №7

This response provides insight into two creative solutions for working around APIs that do not support CORS:

  • Utilize a CORS Proxy
  • If the API allows, employ JSONP

One method involves using 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 additional details, visit:


Alternatively, leverage JSONP if supported by the API:

 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

Answer №8

Apache/HTTPD is a common presence in many enterprises and homes using CentOS, making it easy to set up a proxy for adding necessary CORS headers.

If you're struggling with this process, I have written a blog post on the topic here. The key step involves adding the following code snippet to your /etc/httpd/conf/httpd.conf file:

<VirtualHost *:80>
    <LocationMatch "/SomePath">
       ProxyPass http://target-ip:8080/SomePath
       Header add "Access-Control-Allow-Origin" "*"
    </LocationMatch>
</VirtualHost>

This configuration ensures that requests to URLs under your-server-ip:80/SomePath are routed to , which lacks CORS support. By including the correct Access-Control-Allow-Origin header, these requests can interact effectively with your web application.

You also have the flexibility to adjust ports and target the entire server instead of just SomePath if needed.

Answer №9

        var result=[];
        var app = angular.module('app', []);
        app.controller('myCtrl', function ($scope, $http) {
             var url="";// insert your request URL here    
             var request={};// insert your request parameters here
             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 include the following code in your WebApiConfig file:            
        var cors = new EnableCorsAttribute("*", "*", "*");
        config.EnableCors(cors);

Answer №10

To implement CORS in the frontend, one can utilize the ngResource module for AngularJS. It is crucial to include the following code snippet when sending AJAX requests from the controller:

$scope.weatherAPI = $resource(YOUR API,
     {callback: "JSON_CALLBACK"}, {get: {method: 'JSONP'}});
 $scope.weatherResult = $scope.weatherAPI.get(YOUR REQUEST DATA, if needed);

Additionally, remember to include the ngResource CDN in the scripts section and specify it as a dependency in the app module.

<script src="https://code.angularjs.org/1.2.16/angular-resource.js"></script>

Lastly, ensure to add "ngResource" in the dependencies list of the app module

var routerApp = angular.module("routerApp", ["ui.router", 'ngResource']);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

JavaScript form validation problem: Warning for identical responses in the MOST and LEAST sections

I've encountered a challenge while working on an HTML and JavaScript form for a personality test. The issue revolves around validation, particularly when the form includes multiple questions with both "MOST" and "LEAST" radio button options. One spec ...

Adding an element within an ngFor iteration loop

I'm currently working on a code snippet that displays items in a list format: <ul> <li *ngFor="#item of items">{{item}}</li> </ul> These items are fetched from an API through an HTTP call. Here's the code snippet for tha ...

Tricks for disabling _blank behavior in jquery?

I'm currently integrating a widget into a webpage using PHP. The widget contains jQuery code that causes all links to open in an external page. Is there a way to override or disable this code so it doesn't impact every link on the page? My prefe ...

Passing a null value to a SQL field using JavaScript

I am facing an issue where sending null from AngularJS/JavaScript to my C# controller does not actually set the field as null. How can I properly set a field as null from JavaScript? $scope.formData.currentTempDocument = null return $http({ method: ...

Tips for integrating Grails ${createLink} into your javascript code

Below is a JavaScript function that I have: function GetSelectedItem() { var e = document.getElementById("country"); var strSel = e.options[e.selectedIndex].value; alert(strSel); var url = "${createLink(controller:'country', act ...

Retrieve the contents of a script using JavaScript

I have a script on my webpage that looks like this: <script> window.__INITIAL_STATE__ = {"meReducer":{"me":{"id":1234,"groupId":789,"},},//more code removed}; </script> I am looking to trigger a ...

verified firebase/firestore requests

I've been struggling with the process of sending authenticated firebase/firestore calls. I set up firestore in my web app using Next.js as shown below: import { initializeApp } from "firebase/app"; import { getFirestore } from 'firebase ...

Is using selectors a more effective way to retrieve computed data compared to using class methods?

When using react, redux, and reselect in a project, is it preferable to move all computable data from class methods to selectors and avoid mixing the use of both? Are there different concepts behind these approaches? class DocsListView { getOutdatedDocs ...

Algorithm to identify the highest sum of two numbers in a disorganized array of whole numbers

I am looking to create a function that can identify the largest pair sum in an unordered sequence of numbers. largestPairSum([10, 14, 2, 23, 19]) --> 42 (sum of 23 and 19) largestPairSum([99, 2, 2, 23, 19]) --> 122 (sum of 99 and 23) largestPairSum ...

Introducing a delay in an observable causes incomplete data to be received in Angular using rxjs

Currently, I am facing an issue in my code where I am trying to introduce a delay using timer(500). However, the problem is that it is only returning partial data. Instead of the expected 17 fields, it is only returning 2 fields. Below is my code snippet f ...

Creating dynamic animations for your elements with AJAX

How can I apply animation to an element as soon as it appears? I want others with the same properties to remain unaffected. Here is my approach: $.each(data, function(i, obj) { if(obj['Ping'] == "FALSE"){ ...

Sending data to a MySQL database using AJAX with PHP

While attempting to use ajax to insert a value in PHP, I am encountering an issue where the data is not getting inserted into the database. The code snippet I am using was sourced from answers provided on this site. Can someone please point out where I m ...

Adjust the hue of a specific node

Is there a way to customize the color of an individual node in an eChart treemap? I attempted to set a color property for the node, but it didn't seem to work. While I was able to change the label's color, I'm interested in changing the back ...

Development is hindered due to Cors policy restricting access to the localhost webapp

Currently, I am working on developing a web application and an API simultaneously, but I'm facing some issues with CORS blocking. This concept is relatively new to me, and I'm eager to improve my understanding. Firstly, I have set up an Express ...

When attempting to change the text in the textarea by selecting a different option from the dropdown list, the text is not updating

I am facing an issue with three multi-select dropdown lists. When a user selects options from these lists and then presses the submit button, the selected text should display in a textarea. However, if the user manually changes some text in the textarea ...

Using the @ Symbol in Javascript ES6 Module Imports

One of the folders in my node_modules directory is called @mymodule, and within it, there is another folder named 'insidefolder'. The path to this folder looks like this: node_modules/@mymodule/insidefolder When trying to import insidefolder us ...

Integrating DHTMLX Scheduler with Node JS for seamless scheduling solutions

Having diligently followed the DTHMLX Scheduler guide, I've encountered an issue with the db.event.insert() function not working, as the associated route fails to trigger. Interestingly, data from my MongoDB displays correctly when inserted via the sh ...

Achieving asynchronous results in the parent function with TypeScript: a guide

The code structure provided is as follows: import {socket} from './socket'; class A{ Execute(...args[]){ //logic with Promises SomeAsyncMethod1().then(fulfilled1); function fulfilled1(){ SomeAsyncMethod2(args).then(fulfilled2); ...

What is the best way to synchronize the state of a single React component across various pages?

I am currently working on a React Component that includes a toggle feature (on or off) with the state being managed by the component's own state (this.state). My dilemma is ensuring that this state remains when the user navigates from one page to ano ...

Is there a way to view the contents of a file uploaded from <input type="file" /> without the need to send it to a server?

Having trouble uploading a JSON file from my local disk to Chrome storage. Whenever I use the <input type="file"> tag and useRef on the current value, it only returns the filename prefixed with 'C:\fakepath...' ImportExport Component: ...