methuselah
methuselah

Reputation: 13206

CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource

I keep getting the following error for my AngularJS application hosted on Heroku:

Access to Image at 'https://d15790c7fypqrz.cloudfront.net/attachments/product_template_pictures/images/000/490/265/grid/832816_122.png' from origin 'http://.herokuapp.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://.herokuapp.com' is therefore not allowed access.

How do I resolve it? This is the code which does the base64 conversion:

function createBase64Property(product, callback, outputFormat) {
  var img = new Image();
  img.crossOrigin = 'Anonymous';
  img.onload = function() {
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    var dataURL;
    canvas.height = this.height;
    canvas.width = this.width;
    ctx.drawImage(this, 0, 0);
    dataURL = canvas.toDataURL(outputFormat);
    callback(product, dataURL);
  };
  img.src = product.imageUrl;
  if (img.complete || img.complete === undefined) {
    img.src = 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==';
    img.src = product.imageUrl;
  }
}

My web.js configuration is as follows:

var gzippo = require('gzippo');
var express = require('express');
var morgan = require('morgan');
var cors = require('cors')

var app = express();

app.use(morgan('dev'));
app.use(gzippo.staticGzip(__dirname));
app.use(cors({credentials: true, origin: true}));
app.all('*', function(req, res, next) {
   res.header("Access-Control-Allow-Origin", "*");
   res.header("Access-Control-Allow-Headers", "X-Requested-With");
   res.header('Access-Control-Allow-Headers', 'Content-Type');
   next();
});
app.listen(process.env.PORT || 5000);

Upvotes: 0

Views: 2312

Answers (1)

Pierre R-A
Pierre R-A

Reputation: 529

Ok, there is a tricky way of bypassing CORS in this situation. If your angular code is deployed on a node server, you can proxy your image URL. You define a custom route handled by node which will be local.

Using grunt

You'll need to add grunt-connect-proxy

https://github.com/drewzboto/grunt-connect-proxy

After adding it to your grunt config, you have to write your proxy middleware:

connect: {
      options: {
        port: 9000,
        // Change this to '0.0.0.0' to access the server from outside.
        hostname: 'localhost',
        livereload: 35729
      },
      livereload: {
        options: {
          open: true,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect().use(
                '/app/styles',
                connect.static('./app/styles')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      test: {
        options: {
          port: 9001,
          middleware: function (connect) {
            return [
              connect.static('.tmp'),
              connect.static('test'),
              connect().use(
                '/bower_components',
                connect.static('./bower_components')
              ),
              connect.static(appConfig.app)
            ];
          }
        }
      },
      dist: {
        options: {
          open: true,
          base: '<%= yeoman.dist %>'
        }
      },
      proxies: [
            {
                context: '/outsides-images',
                host: 'd15790c7fypqrz.cloudfront.net/',
                https: true,
            }
        ]
    },

Using gulp

I'll show you an example using gulp for setting up the server (I know it's not a perfect solution, but you can see the pattern):

import proxy from 'http-proxy-middleware';
import gulp-connect from 'gulp-connect';

const imagesServiceProxy = proxy('/outsides-images', {
  target: 'https://d15790c7fypqrz.cloudfront.net/',
  changeOrigin: true,
  logLevel: 'debug',
});

gulp.task('serve', () => {
  connect.server({
    port: 3000,
    root: [ './dest' ],
    livereload: false,
    middleware: (connect, opt) => {
      return [
        imagesServiceProxy,
        historyApiFallback(),
      ];
    },
  });
});

This snippet is in ES6, and I setup the server with gulp-connect.

Now, in your AngularJS/HTML code, when you fetch the image, use the proxy URL, something like that:

/outside-images/attachments/product_template_pictures/images/000/490/265/grid/832816_122.png

I don't know how you setup your server, but I hope this answer will give you a hint about bypassing CORS.

Upvotes: 1

Related Questions