Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Http requests multi browser troubles

I am building in laravel 5.1 using angularJs.

When the user clicks a button, I want to send a destroy request to delete it from the database and then when thats completed send a get request to get the new data now that one has been deleted.

So I attached my method to an ng-click event on a button, this works, it hits the method.

I then run a .destroy request. Inside the .then() method of that .destroy I want to then call another method which has a .get request.

This works perfectly in Safari, but doesn't work in Chrome or Firefox.

Here is my code for the controller, the method that is called on button click to delete is deleteOpportunity():

$scope.getOpportunities = function()
    {
        UBOService.get()
            .then(function successCallback(responsed) {
                $scope.opportunities = responsed.data;
            }, function errorCallback(response) {
                $scope.error = response;
            });
    }
$scope.deleteOpportunity = function()
    {

                UBOService.destroy($scope.activeItem.id)
                    .then(function successCallback(response) {
                        $scope.getOpportunities();

                        return false;
                    }, function errorCallback(response) {
                        $scope.error = response;
                    });

    }

My service code:

app.service('UBOService', function($http) {

    return {
        get : function() {
            return $http.get('/api/user-booked-opportunities');
        },

        destroy : function(id) {

            return $http.delete('/api/user-booked-opportunities/' +  id);
        }
    }
})

Am I doing something wrong? Is there something I am missing? How does Safari interact differently with this code which makes it work?

like image 329
RSM Avatar asked Mar 02 '16 13:03

RSM


2 Answers

It's tough to gauge from the parameters you posted, but just based on you saying that this works perfectly in Safari, but doesn't work in Chrome or Firefox, it sounds like this could be a CORS issue.

Firefox and Chrome have different requirements for cross-origin requests than Safari. Is your Laravel api endpoint for this destroy action located at the same location as your Angular app? What Access-Control-Allow-Origin header is the API returning?

Try adding something like the following to Laravel and see if it makes it this block consistent across those browsers:

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

  if (Request::getMethod() == "OPTIONS") {
    // The client-side application can set only headers allowed 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, Origin, Authorization'
    ];
    return Response::make('You are connected to the API', 200, $headers);
  }
});

(^ source)

like image 164
wesww Avatar answered Oct 23 '22 16:10

wesww


I guess its a CORS issue. And moreover this issue normally happens if you decouple your client side from your server side. You need to create a before middleware to handle such issues.

namespace App\Http\Middleware;

use Closure;

class BeforeMiddleware
{
  /**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  \Closure  $next
  * @return mixed
  */
 public function handle($request, Closure $next)
 {
    /** 
    * The access control allow origin and 
    * allow credential is set to * and true 
    * because i allow request from different domains
    * to hit the server
    */
    header('Access-Control-Allow-Origin: *');
    header('Access-Control-Allow-Credentials: false');
    header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
    header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization');

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

    return $next($request);
 }
}

And at the angular side of things add this config block

app.config(['$httpProvider', function ($httpProvider) {

  $httpProvider.defaults.useXDomain = false;
  $httpProvider.defaults.withCredentials = false;
  delete $httpProvider.defaults.headers.common['X-Requested-With'];

}]);
like image 29
oseintow Avatar answered Oct 23 '22 15:10

oseintow