1

I have a form for "Books" and I'm sending a HTTP request through axios with post, it is returning 405 error

My routes

(web.php)

Route::redirect('/', 'login');
Auth::routes();
Route::resource('/books', 'books\BooksController')->middleware('auth');

I have seen that many people use the api routes but it has worked with web with me before (but with a less complex crud)

My controller

    public function store(Request $request)
    {
        $book = new Book();
        $book->isbn = $request->isbn;
        $book->titulo_ori = $request->titulo_ori;
        $book->sinop = $request->sinop;
        $book->n_pag = $request->n_pag;
        $book->save();
        return $book;
    }

I am not using migrations so my model looks like this

My model

class Book extends Model
{
    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = 'sjl_libros';
    protected $fillable = ['isbn', 'titulo_ori' 'sinop', 'n_pag'];
    public $timestamps = false;
}

My form

<b-form @submit.prevent="add">
     <b-row>
         <b-col cols="4">
             <label for="isbn">ISBN</label>
                <b-form-input type="text" v-model="book.isbn" id="isbn" name="isbn"></b-form-input>
         </b-col>

          <b-col cols="4">
             <label for="titulo_ori">Original Title</label>
                <b-form-input type="text" v-model="book.titulo_ori" id="titulo_ori" name="titulo_ori"></b-form-input>
          </b-col>
 </b-row><br>

 <b-row>
     <b-col cols="12">
         <label for="sinop">Plot</label>
         <b-form-textarea v-model="book.sinop" size="lg" rows="8" id="sinop" name="sinop"></b-form-textarea>
     </b-col>
 </b-row><hr>

<b-row>
   <b-col cols="4">
      <label for="n_pag">Number of pages</label>
          <b-form-input v-model="book.n_pag" id="n_pag" name="n_pag"></b-form-input>
   </b-col>                                   
   </b-row><hr>

   <div class="d-flex flex-row-reverse bd-highlight">
       <b-button variant="default" @click="add">Continue</b-button>
       <b-link class="btn btn-danger" href="/books">Cancel</b-link>
   </div>
</b-form>

My axios script

add() {
    const params = {
        isbn: this.book.isbn,
        titulo_ori: this.book.titulo_ori,
        sinop: this.book.titulo_esp,
        n_pag: this.book.n_pag,
        headers: {
            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
        }
};


        axios.post('/books', params)
           .then(res => {
               alert('success');
               console.log(res.data);
                }). catch (e=> {
                    console.log(e);
                })
        },

The exact error I get in console is the following

Error: "Request failed with status code 405"
    createError http://localhost:8000/js/app.js:653
    settle http://localhost:8000/js/app.js:899
    handleLoad http://localhost:8000/js/app.js:166

What could I do to solve this problem?

4
  • I get 500 error now, I appended it like this const params = { isbn: this.book.isbn, titulo_ori: this.book.titulo_ori, sinop: this.book.sinop, n_pag: this.book.n_pag, headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } };
    – pinkWojak
    Commented Dec 6, 2019 at 16:57
  • Please run php artisan route:list and show us the result. I think your route uri shoud be '/books' instead '/books/create' Commented Dec 6, 2019 at 16:57
  • yeah, just edited my question, that's what made me get a 500 error now.
    – pinkWojak
    Commented Dec 6, 2019 at 17:03
  • For a status 500 you must look at the Laravel logs /yourproject/storage/logs/laravel.log to know what it is. With _token field, I meant a field within the parameters just like the others you already have const params = { isbn: this.book.isbn, titulo_ori: this.book.titulo_ori, sinop: this.book.sinop, n_pag: this.book.n_pag, _token: $('meta[name="csrf-token"]').attr('content') };, you should only add it to the headers if you had not done it before with something like window.axios.defaults.headers.common = { ... } Commented Dec 6, 2019 at 17:14

1 Answer 1

0

A resource route like the one you have:

Route::resource('books', 'books\BooksController');

will result for the post method in something like this:

Verb    URI        Action   Route Name
POST    /books     store    books.store

So for your axios url, you must use '/books' (the route URI)

axios.post('/books', params)

Also you will need to add the CSRF token in a _token field. You can append it to the params object

const params = { 
    isbn: this.book.isbn, 
    titulo_ori: this.book.titulo_ori, 
    sinop: this.book.sinop, 
    n_pag: this.book.n_pag, 
    _token: document.querySelector('meta[name="csrf-token"]').getAttribute('content')
};

You should only add the token to the headers if you had not done it before with something like

window.axios = require('axios');
window.axios.defaults.headers.common = {
    'X-Requested-With': 'XMLHttpRequest',
    'X-CSRF-TOKEN' : document.querySelector('meta[name="csrf-token"]').getAttribute('content');
};

But if you are using Laravel default frontend scaffolding that's probably already done. If don't, use the previus code.

But remember, in both cases you will need that meta tag in your page <head>:

<meta name="csrf-token" content="{{ csrf_token() }}">

Not related, but for all the routes you write after Auth::routes(), you don't need to manually add the auth middleware ->middleware('auth')

Auth::routes();
Route::resource('/books', 'books\BooksController');
1
  • 1
    thank you for the very complete answer, i fixed the problem
    – pinkWojak
    Commented Dec 6, 2019 at 18:16

Not the answer you're looking for? Browse other questions tagged or ask your own question.