beemargarida's avatar

Trying to verify if a request is AJAX

Hi! I am trying to implement pagination with AJAX, and using plain Javascript to do it. The problem is that when I run request()->ajax(), the header "X-Requested-With" isn't set. Here's the code:

UserController.php

public function showProfile(string $username) {
        if (!Auth::check()) return redirect('/login');
        $this->authorize('list', Project::class);

        $projects = Auth::user()->userProjects();

        if(request()->ajax()) {
            $viewHTML = view('partials.user_projects', ['projects' => $projects])->render();
            echo $viewHTML;
            return response()->json(array('success' => true, 'html' => $viewHTML));
        }

        $notifications = Auth::user()->userNotifications();

        $taskCompletedWeek = Auth::user()->taskCompletedThisWeek()[0];
        $taskCompletedMonth = Auth::user()->taskCompletedThisMonth()[0];
        $sprintsContributedTo = Auth::user()->sprintsContributedTo()[0];
  
        return view('pages/user_profile', ['projects' => $projects, 'taskCompletedWeek' => $taskCompletedWeek, 'taskCompletedMonth' => $taskCompletedMonth, 
        'sprintsContributedTo' => $sprintsContributedTo, 'notifications' => $notifications]);
      
    }

I only want the projects view when it is an AJAX Request.

Javascript file

function sendAjaxRequest(method, url, data, handler) {
  let request = new XMLHttpRequest();

  request.open(method, url, true);
  request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').content);
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  request.addEventListener('load', handler);
  if(data != null)
    request.send(encodeForAjax(data));
  else
    request.send();
}

function getUserProjectsPage(event) {
    event.preventDefault();

    var page = event.target.href.split('page=')[1];

    sendAjaxRequest('get', event.target.href, null, changePage);
}

function changePage() {
    var response = JSON.parse(this.responseText);
    console.log(response);

    let content = document.querySelector("div.#projects");
    content.innerHTML = response.html;
}

I searched a bit, and found out that jQuery adds this header to the request, but I can't use jQuery because this is a college project and we are forbidden to use it. Any suggestions?

Thanks in advance!

0 likes
11 replies
Cronix's avatar

If you're using npm run dev, etc, a default laravel install adds these to the axios headers in the app.js file:

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

If you're not using that, you'd have to set it yourself somewhere, or directly in the request like you are with X-CSRF-TOKEN and Content-Type.

You should set those somewhere globally, btw, so you don't have to manually set it for each individual request.

So, I'd add these to some global javascript file that gets loaded on every request.

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').content;
window.axios.defaults.headers.common['Content-Type'] = 'application/x-www-form-urlencoded';

And then you don't need

request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').content);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
beemargarida's avatar

@Cronix Like this?

function sendAjaxRequest(method, url, data, handler) {
  let request = new XMLHttpRequest();

  request.open(method, url, true);
  request.setRequestHeader('X-CSRF-TOKEN', document.querySelector('meta[name="csrf-token"]').content);
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
  request.addEventListener('load', handler);
  if(data != null)
    request.send(encodeForAjax(data));
  else
    request.send();
}
Cronix's avatar

Yes, but doing it that way you'd have to do that for every single request. If you did it the way I showed, you don't. It would automatically add them to every request.

beemargarida's avatar

@Cronix It still doesn't work...when I make

echo request()->headers->get("X-Requested-With");

in the Controller, it doesn't show anything, so it doesn't enter inside the If

Cronix's avatar

What does request()->headers->all() show?

Does your browsers dev tools show the headers are being sent?

Have you force-reloaded the page?

beemargarida's avatar

Hi @Cronix, sorry for the delay! The request()->headers->all() shows host, connection, cache-control, upgrade-insecure-requests, user-agent, accept, referer, accept-encoding, accept-language and cookie information. There is no field of X-Requested-With. Even with force-reload

Cronix's avatar

So X-CSRF-TOKEN and Content-Type were missing as well?

beemargarida's avatar

The only mentions to them were in this:

[accept] => Array
        (
            [0] => text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
        )

and

[cookie] => Array
        (
            [0] => XSRF-TOKEN=eyJpdiI6IjVYZ0FR(...)
        )
Cronix's avatar

So, it's not setting any of your custom headers. I'm afraid I can't really help with this. I haven't used XMLHttpRequest(), just axios and jquery and a few others so I'm not really familiar with it. I did some googling and it seems what you have should work, but it looks like none of your custom headers are being sent.

Please or to participate in this conversation.