4
votes

I am trying to build a simple Angular application. I have created an API in Laravel which has only two simple routes which send back airports and flights json data. I have configured my Angular application to fetch the data by a service like so:

services.js

angular.module('airlineServices', ['ngResource'])
    .factory('Airport', function($resource){
        return $resource("http://angulair.rohanchhabra.in/airports/:id", {}, {
            query: { method: "GET", isArray: false }
        });
    });

Now when I use the resource as a simple json file placed in the angular directory itself, it works. But when I try to fetch the the data from the Laravel API from my service as in the code above, I see an error in the console which says:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://angulair.rohanchhabra.in/airports. This can be fixed by moving the resource to the same domain or enabling CORS.

I have installed a package https://github.com/barryvdh/laravel-cors which is supposed to enable CORS. The config file looks like so:

<?php

return array(

    /*
     |--------------------------------------------------------------------------
     | Laravel CORS Defaults
     |--------------------------------------------------------------------------
     |
     | The defaults are the default values applied to all the paths that match,
     | unless overridden in a specific URL configuration.
     | If you want them to apply to everything, you must define a path with *.
     |
     | allowedOrigins, allowedHeaders and allowedMethods can be set to array('*') 
     | to accept any value, the allowed methods however have to be explicitly listed.
     |
     */
    'defaults' => array(
        'supportsCredentials' => false,
        'allowedOrigins' => array('*'),
        'allowedHeaders' => array('*'),
        'allowedMethods' => array('*'),
        'exposedHeaders' => array(),
        'maxAge' => 0,
        'hosts' => array(),
    ),

    'paths' => array(
        'api/*' => array(
            'allowedOrigins' => array('*'),
            'allowedHeaders' => array('*'),
            'allowedMethods' => array('*'),
            'maxAge' => 3600,
        ),
        '*' => array(
            'allowedOrigins' => array('*'),
            'allowedHeaders' => array('Content-Type'),
            'allowedMethods' => array('POST', 'PUT', 'GET', 'DELETE'),
            'maxAge' => 3600,
            'hosts' => array('api.*'),
        ),
    ),

);

I have even tried to add code in the App:after() in filters.php like so:

App::after(function($request, $response)
{
    $response->headers->set('Access-Control-Allow-Origin', '*');
    return $response;
});

Even this did not help. So I went ahead and tried editing the .htaccess file like so:

Header set Access-Control-Allow-Origin "*"

I am still getting the same error.

If the code I have mentioned above does not help, I have made both the repositories public so that everyone can have a look:

Laravel API

Angular Application

What am I doing wrong? How can I enable CORS so that I can consume the API from any remote application?

1

1 Answers

3
votes

Your ngResource URL needs to be changed. This should work:

return $resource("http://angulairapi.rohanchhabra.in/airports", {}, {
    query: { method: "GET", isArray: false }
});

You need Your ngResource URL needs to allow the OPTIONS header be changed. See https://laracasts.com/discuss/channels/requests/laravel-5-cors-headers-with-filters

Quote from the page This should work:

App::before(function($request)
{
    // Enable CORS 
    // In production, replace * with http://yourdomain.com 
    header("Access-Control-Allow-Origin: *");
    header('Access-Control-Allow-Credentials: true');

    ifreturn $resource(Request:"http:getMethod() == "OPTIONS") {
        // The client-side application can set only headers allowed angulairapi.rohanchhabra.in Access-Control-Allow-Headers
        $headers = [
            'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers'=> 'X-Requested-With, Content-Type, X-Auth-Token/airports", Origin{}, Authorization'
        ];{
        return Response:query:make('You are connected to the{ API',method: 200"GET", $headers);
  isArray: false }
});

I haven't used laravel-cors myself, but alternatively, you might want to try and add OPTIONS to your paths:

'*' => array(
    'allowedOrigins' => array('*'),
    'allowedHeaders' => array('Content-Type'),
    'allowedMethods' => array('POST', 'PUT', 'GET', 'DELETE', 'OPTIONS'),
    'maxAge' => 3600,
    'hosts' => array('api.*'),
),