4

I have been searching far and wide for a solution to this problem.

I have an AngularJS web app with a Laravel 4 backend implementation as follows:

http://app.mydomain.io/ = AngularJS web app
http://api.mydomain.io/ = Laravel Back-end

Within the routes.php file in Laravel I have the following PHP code to set the Access-Control headers:

header('Access-Control-Allow-Origin: http://app.mydomain.io');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE');

I also have a route set-up for a login request as follows:

Route::post('/login', function()
{
    $email = Input::get('email');
    $password = Input::get('password');
    if (Auth::attempt(array('email' => $email, 'password' => $password)))
    {
        return "Success!";
    } else {
        return "Fail!";
    }
});

In AngularJS I have a AuthService which looks like below:

app.factory('AuthService', ['$resource', '$q', '$cookieStore', function($resource, $q, $cookieStore) {
    var user = null;
    var Service = $resource('//api.mydomain.io/login/', {}, {});
    return {
        login: function(email, password) {
            var deferred = $q.defer();
            Service.save({email: email, password: password}, function(response) {
                $cookieStore.put('user', JSON.stringify(response));
                deferred.resolve(true);
            }, function(error) {
                deferred.reject(error);
            });
            return deferred.promise;
        }
    };
}]);

When this request is made I get the following:

XMLHttpRequest cannot load http://api.mydomain.io/login. Invalid HTTP status code 404

If I change the Laravel route and AngularJS service to use GET, everything works as expected. The problem stems from AngularJS .save() making a OPTIONS request instead of POST (I don't fully understand why).

Could anyone help me with the proper and best practice solution?

Thank you!

fab
  • 321
  • 4
  • 20
Leon Revill
  • 1,770
  • 2
  • 16
  • 23
  • possible duplicate of [AngularJS performs an OPTIONS HTTP request for a cross-origin resource](http://stackoverflow.com/questions/12111936/angularjs-performs-an-options-http-request-for-a-cross-origin-resource) – Barbarrosa Feb 05 '14 at 07:30

4 Answers4

7

The following solution worked:

Within filters.php add the following:

App::before(function($request)
{
    if (Request::getMethod() == "OPTIONS") {
        $headers = array(
            'Access-Control-Allow-Methods'=> 'POST, GET, OPTIONS, PUT, DELETE',
            'Access-Control-Allow-Headers'=> 'X-Requested-With, content-type',);
        return Response::make('', 200, $headers);
    }
});

And at the top of routes.php add the following:

header('Access-Control-Allow-Origin: http://app.mydomain.io');

Thanks to the Google Plus community! :)

Leon.

Leon Revill
  • 1,770
  • 2
  • 16
  • 23
0

In client side http://docs.angularjs.org/api/ng.$http

you can try setting default "Setting HTTP Headers"

himangshuj
  • 710
  • 5
  • 9
0

I have used quite some time figuring this out and that is what i came up with:

Filters.php:

App::before(function($request)
{

    header('Access-Control-Allow-Origin: http://app.mydomain.io');
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization');

    // Pre-flight request handling, this is used for AJAX
    if($request->getRealMethod() == 'OPTIONS')
    {
        Log::debug('Pre flight request from Origin'.$rq_origin.' received.');
        // This is basically just for debug purposes
        return Response::json(array('Method' => $request->getRealMethod()), 200);
    }
});

App.js (Frontend):

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.useXDomain = true;
    $httpProvider.defaults.withCredentials = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];

}]);

Also note that there is a bug with self-signed SSL certificates in Chrome and CORS request, i will provide a link if you are interested in that.

So be advised to use Firefox while debugging (or DevHTTPClient on Chrome works fine for me).

Cheers!

jfornoff
  • 1,298
  • 8
  • 14
0

Try this piece for newer versions of Laravel (5+)

public function handle($request, Closure $next)
{
    $method = $request->method();
    if($method == "OPTIONS"){
       return response('It\'s supported. Relax!', 200); 
    }
    return $next($request);
}
iongraphix
  • 86
  • 5