0

I have read other SO entries about issues with how mobile safari will cache POST requests. I have implemented what I "thought" was the fix on my express app, but still when I POST to my app (hosted on Heroku) from my Angular client I get a status 204 from Heroku and nothing is returned.

Here is the controller function that that does the POST in the client:

 $scope.signUp = function(user){

    $scope.passwordsmatch = true;
    $scope.waitingToSignUp = true;
    $scope.noSignUpError = true;

    if(user.password != user.password2) {

        $scope.passwordsmatch = false;
        return;
    }

    if($scope.signupForm.$valid) {


        $http({
            url: "https://frozen-peak-5921.herokuapp.com/api/users",
            method: "POST",
            data: user,
            headers: {'Content-Type': 'application/json'}})
            .success(function(obj){

                $scope.resultAction(obj);



            })
            .error (function(err){

            $scope.resultAction(err);
        });
    }
    else{

        $scope.showValidation = true;

        }
    };

Here is the POST route in Express:

router.route('/users')
.post(function(req, res) {

    var user = new User();
    user.username = req.body.username;
    user.password = req.body.password;

    user.save(function(err){

        if (err) {
            res.status(500);
            res.json({
                status: 500,
                error: err
            });

        }
        else {
            res.json({
                status: 200,
                user: user
            });

        }
    });
});

Here is how my Headers are set my Express Middleware:

app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,  
Content-Type, Accept");
res.header("Content-Type", "application/json");
res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate');
res.header('Expires', '-1');
res.header('Pragma', 'no-cache');
next();

});

And here is what I see in the Heroku logs

at=info method=OPTIONS path="/api/users" host=<myhost removed on purpose>.herokuapp.com 
request_id=dd16af0c-5a77-4c1e-9f88-73e97e6de89d fwd="70.197.166.161" 
dyno=web.1 connect=1ms service=5ms status=204 bytes=297

This POST works perfect from other browsers, just not mobile safari? Is there something else I need to do?

Tommy Alexander
  • 701
  • 1
  • 7
  • 17

2 Answers2

0

Did you by any chance try setting cache: false?

    $http({
        cache: false,
        url: "https://frozen-peak-5921.herokuapp.com/api/users",
        method: "POST",
        data: user,
        headers: {'Content-Type': 'application/json'}})
        .success(function(obj){
            $scope.resultAction(obj);
        })
        .error (function(err){
        $scope.resultAction(err);
    });
taxicala
  • 21,408
  • 7
  • 37
  • 66
  • I had not done that. I made that change and still get the same message from Heroku. Still works on all other browsers, not mobile Safari on the iPhone. Grrrr.... – Tommy Alexander Oct 15 '15 at 18:37
  • Also, I thought this was happening only in mobile Safari but that seems to be not true. I get the same result in Safari on OSX as well. Chrome, FIrefox, Opera all work fine... – Tommy Alexander Oct 15 '15 at 19:13
0

I managed to resolve this. Once I saw the problem was happening in Safari on OSX as well, I started looking into other differences in how different browsers handle POST requests (outside of the Cache issue previously noted with mobile Safari). Turns out, this was a CORS configuration problem. This post helped me figure this out CORS request not working in Safari

I am using the cors npm module and ultimately this is the configuration that works in Safari and all other browsers:

var whitelist = ['http://myclient.com', 'http://www.myclient.com'];

var corsOptions = {
origin: function(origin, callback){
    var originIsWhitelisted = whitelist.indexOf(origin) !== -1;
    callback(null, originIsWhitelisted);
},
methods:["GET", "PUT", "POST", "DELETE"],
allowedHeaders:["Origin", "X-Requested-With", "Content-Type", "Accept"],
maxAge:-1
};

Now I do set the maxAge to -1 which disabled cache of the POST requests. Without that it is possible I would of hit the cache issue in mobile Safari once the CORS issue got sorted, but ultimately, that CORS configuration seems to do it for me.

Community
  • 1
  • 1
Tommy Alexander
  • 701
  • 1
  • 7
  • 17