Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

beznez's avatar

Ajax Issues on Apache Server

I'm having a little trouble with Ajax. My project is in Laravel 5 and it's running on Apache and rewrite is enabled and the VerifyCsrfToken middleware is in place. I'm trying to send a POST request to another route inside my project. Here's what my Ajax looks like:

    $.ajax({
        url: '/add-device/',
        type: 'POST',
        data: form_data,
        success: function(data)
        {
            console.log(data);
        },
            error: function(data)
        {
            console.log(data);
        }
    });

When I click the button that triggers this Ajax, I get a 405: MethodNotAllowed response. So I went into routes.php and I added a GET route. I've also included my POST route:

    Route::get('add-device', function()
    {
        return 'hello';
    });

    Route::post('add-device', [
        'middleware' => 'auth',
        'uses' => 'FormController@add_device'
    ]);

I get the 'hello' message, so this is being sent as GET instead of POST. I tried to use $.post instead of $.ajax to force the POST but I still get the same behavior. For good measure, here is my .htaccess file:

    <IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

        RewriteEngine On

        # Redirect Trailing Slashes...
        RewriteRule ^(.*)/$ /$1 [L,R=301]

        # Handle Front Controller...
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteRule ^ index.php [L]
    </IfModule>

I also tried the Ajax without the trailing slash because of the rewrite rule (/add-device) but I get the same 'hello' message.

I tested all of my Ajax requests (half GET, half POST) during development and they worked fine while being served with artisan. I've only had this problem come up after switching to Apache. I've moved into the QA phase of my project and so I moved the project onto our development server, which is running Apache 2.4.10 on Debian 8.

Anyone have any ideas on what is going on and how to resolve it? This question is also on Stack, if you want to check out other steps I have taken.

0 likes
7 replies
jimmck's avatar

Sounds like you are not sending the _token to the Laravel server instance. I had the same issue when i moved from L4 to L5. In your HTML or Blade do this tom get you started.

<!doctype html>
<html>
<head>
    <title>Manage Contact Types</title>
    <link rel="stylesheet" href="/assets/css/main.css">
    <link rel="stylesheet" href="/assets/css/alertify.css" />
    <link rel="stylesheet" href="/assets/css/themes/default.css" />
    <meta name="csrf-token" content="<?php echo csrf_token() ?>"/>
</head>
<body>
....... blah blah

This puts the token in your header. Then pick it up and send it back as part of AJAX data.

PayloadMsg.prototype.call = function(url, callData, context) {
    this.urlExists(url, this.exists);

    if (this.urlOk == false || url == ""  || arguments.length == 0) {
        fyi("Bad URL [" + url + "]");
        this.getToken();
        return;
    }

    if (arguments.length == 1) {
        callData = "";
        this.context = null;
    }

    if (arguments.length == 2) {
        this.context = null;
    }

    if (arguments.length > 2) {
        this.context = arguments[2];
    }

    //fyi("inside call...");
    // how do we check the url is correct? timeout causes problems.
    // the busy flag needs to be static for the class.

    // make sure if callData is an object we make it an empty object.
    // we do this so we can add _token to it.

    if (callData == "") {
        callData = {};
    }
    this.busy = true;
    callData['_token'] = this.csrf_token;
    fyi('Post token [' + callData['_token'] + ']');
    $.myPost(url, callData, this, this.handlePost, this.postError, this.timeout, this.async);
};

In the beginning I was just pulling the token out of the header in my JS AJAX class constructor...

    //this.csrf_token = $('meta[name="csrf-token"]').attr('content');

Of course that token will expire

beznez's avatar

I'm not so sure if it's the Csrf since the error I'm getting is a 405: MethodNotAllowed. Right now I have a csrf token defined like so:

<script type="text/javascript">if (top != self) {top.location.href = self.location.href;}</script><script type="text/javascript">var csrfMagicToken = "sid:c5470f028e13004f1ec2da1a3239652b38c7fc12,1424914587";var csrfMagicName = "__csrf_magic";</script><script src="/csrf-magic.js" type="text/javascript"></script>
<script type="text/javascript">if (top != self) {top.location.href = self.location.href;}</script><script type="text/javascript">var csrfMagicToken = "sid:01258c12fbb5b0e85f2e66822e52015e4a16d791,1424963999";var csrfMagicName = "__csrf_magic";</script><script src="/csrf-magic.js" type="text/javascript"></script><script type="text/javascript">if (top != self) {top.location.href = self.location.href;}</script><script type="text/javascript">var csrfMagicToken = "sid:9eaf850507b5ba1ee561c16685b70eb6099f9547,1425001497";var csrfMagicName = "__csrf_magic";</script><script src="/csrf-magic.js" type="text/javascript"></script><script type="text/javascript">if (top != self) {top.location.href = self.location.href;}</script><script type="text/javascript">var csrfMagicToken = "sid:9d1f54071dc4af69b21c39bca79b2fcc60f7cc99,1425053738";var csrfMagicName = "__csrf_magic";</script><script src="/csrf-magic.js" type="text/javascript"></script>

I think this was generated for me by Laravel and so I haven't touched it, yet.

beznez's avatar

@JeffreyWay @bashy @JarekTkaczyk @pmall @bestmomo @bobbybouwmann Any help on this would be fantastic. I feel like this is a jQuery thing, but my syntax is good and none of my other jQuery or javascript is broken. So I'm not sure what exactly is going on here. Sorry, this isn't exactly a Laravel question. This is something that arose when I changed the environment that the project lives in. I switched from serving locally on a Mac with artisan to serving from the company's dev server running Apache on Debian. For that reason I think it must have something to do with the environment. But on the other hand, it's just javascript. Thanks for any help!

bobbybouwmann's avatar

I don't understand much about your code but I would do it like this

$('button').on('click', function() {
    $.ajax({
        url: '/post/url', // Change this to the url you want, notice I don't have an extra / add the end!
        type: "POST",
        headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') }, // More information on this below
        data: {
            'title' => 'Sample data title',
            'body' => 'Sample data body'
        }
        }).done(function (response) {
        // Do what ever you want to do here
    });
});

Now for the headers part I have this defined in my html head

<!doctype html>
<html>
    <head>
        // Other head stuff
        <meta name="_token" content="{{ csrf_token() }}"/>
    </head>
    <body>
    </body>
</html>

This way I always have the correct csrf token for submitting the form ;) If you have any questions let me know!

1 like
JarekTkaczyk's avatar

@beznez Read about CORS. jQuery sends 2 ajax requests here - first is dummy request to check whether the server accepts requests from this domain, then it sends the one, you defined. I guess that's the problem, without reading your code.

bashy's avatar
bashy
Best Answer
Level 65

Probably due to the trailing slash, Laravel doesn't respond to that on the same route unless you have it setup to do so, which you do not by the htaccess content.

1 like
beznez's avatar

I left off the trailing slash and it works now. Which is weird, because I did that before and it didn't. Now I have done some things in between then and now so maybe there was a different problem then that has since been resolved. Apache logs are recording POST requests and I am receiving my data back. But in any case, I've decided to use the Csrf token as suggested by @bobbybouwmann instead of the way that I'm doing it presently. Thanks everyone!

Please or to participate in this conversation.