axios returns a 419 response every time
I am using Laravel 5.5 and have been following along with the "Let's build a forum with Laravel and TDD" tutorials. I am in the middle of Lesson 32 where a Vue reply component is created. I have followed the tutorials to the letter and have made no modifications.
All of my non-AJAX requests have been fine. However, as soon as we use axios in this lesson, I'm getting a 419 response every time I try a patch request. I also get a 419 response with put, post and delete requests. I'm pretty comfortable with Vue and axios and have used them in tandem many times before with no issues.
When I get this 419 response, Laravel logs me out so it's an authentication issue for sure.
My relevant code:
reply.blade.php
<reply :attributes="{{ $reply }}" inline-template v-cloak>
<div id="reply-{{ $reply->id }}" class="panel panel-default">
<div class="panel-heading">
<div class="level">
<h5 class="flex">
<a href="{{ route('profile', $reply->owner) }}">
{{ $reply->owner->name }}
</a> said {{ $reply->created_at->diffForHumans() }}...
</h5>
<div>
<form method="POST" action="/replies/{{ $reply->id }}/favorites">
{{ csrf_field() }}
<button class="btn btn-default" type="submit" {{ $reply->isFavorited() ? 'disabled' : '' }}>
{{ $reply->favorites()->count() }}
{{ str_plural('Favorite', $reply->favorites_count) }}
</button>
</form>
</div>
</div>
</div>
<div class="panel-body">
<div v-if="editing">
<div class="form-group">
<textarea class="form-control" v-model="body"></textarea>
</div>
<button class="btn btn-xs btn-primary" @click="update">Update</button>
<button class="btn btn-xs btn-link" @click="editing = false">Cancel</button>
</div>
<div v-else>
{{ $reply->body }}
</div>
</div>
@can('update', $reply)
<div class="panel-footer level">
<button class="btn btn-xs mr-1" @click="editing = true">Edit</button>
<form method="POST" action="/replies/{{ $reply->id }}">
{{ csrf_field() }}
{{ method_field('DELETE')}}
<button type="submit" class="btn btn-danger btn-xs">Delete</button>
</form>
</div>
@endcan
</div>
</reply>
Reply.vue
<script>
export default {
props: ["attributes"],
data() {
return {
editing: false,
body: this.attributes.body
};
},
methods: {
update() {
axios.patch("/replies/" + this.attributes.id, {
body: this.body
});
this.editing = false;
}
}
};
</script>
routes/web.php
<?php
Auth::routes();
Route::get('/threads', 'ThreadsController@index');
Route::get('/threads/create', 'ThreadsController@create');
Route::post('/threads', 'ThreadsController@store');
Route::get('/threads/{channel}/{thread}', 'ThreadsController@show');
Route::delete('/threads/{channel}/{thread}', 'ThreadsController@destroy');
Route::get('/threads/{channel}', 'ThreadsController@index');
Route::post('/threads/{channel}/{thread}/replies', 'RepliesController@store');
Route::patch('/replies/{reply}', 'RepliesController@update');
Route::delete('/replies/{reply}', 'RepliesController@destroy');
Route::post('/replies/{reply}/favorites', 'FavoritesController@store');
Route::get('/profiles/{user}', 'ProfilesController@show')->name('profile');
Route::get('/home', 'HomeController@index')->name('home');
RepliesController
<?php
namespace App\Http\Controllers;
use App\Reply;
use App\Thread;
use Illuminate\Http\Request;
class RepliesController extends Controller
{
public function __construct()
{
$this->middleware('auth');
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store($channelId, Thread $thread)
{
request()->validate([
'body' => 'required'
]);
$thread->addReply([
'body' => request('body'),
'user_id' => auth()->id()
]);
return back()
->with('flash', 'Reply successfully created');
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param \App\Reply $reply
* @return \Illuminate\Http\Response
*/
public function update(Request $request, Reply $reply)
{
$this->authorize('update', $reply);
$reply->update(request(['body']));
}
/**
* Remove the specified resource from storage.
*
* @param \App\Reply $reply
* @return \Illuminate\Http\Response
*/
public function destroy(Reply $reply)
{
$this->authorize('update', $reply);
$reply->delete();
return back();
}
}
app/Policies/ReplyPolicy.php
<?php
namespace App\Policies;
use App\User;
use App\Reply;
use Illuminate\Auth\Access\HandlesAuthorization;
class ReplyPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can update the reply.
*
* @param \App\User $user
* @param \App\Reply $reply
* @return mixed
*/
public function update(User $user, Reply $reply)
{
return $reply->user_id == $user->id;
}
}
Interestingly, when I dd(auth()->user()) in the constructor function of RepliesContoller when I issue the AJAX patch request:
RepliesController.php
...
public function __construct()
{
dd(auth()->user());
$this->middleware('auth');
}
it returns null and auth()->guest() returns true. If I dd(auth()->user()) on a non AJAX request or in the constructor of TheadsController, it returns the user.
Help!
Please or to participate in this conversation.