Axios: Request failed with status code 404



  • Hi Everyone

    I’m new to VueJS and Quasar, so hopefully I’m not doing some very weird beginner mistakes 🙂

    My goal is to use Quasar as Frontend and NodeJS/Express as backend (MEVN stack).
    Now I found this Tutorial here that helps me setting up my NodeJS server and connecting to it using axios.

    As this Tutorial is based open native VueJS and not Quasar I tried to apply this to the framework.
    What I did is I changed the /boot/axios.js to the following:

    import Vue from 'vue'
    import axios from 'axios'
    
    Vue.prototype.$axios = axios
    
    export default () => {
      return axios.create({
        baseURL: `http://localhost:8081/` // the url of our server
      })
    }
    

    This should make sure axios is connecting to my NodeJS Server.
    The backend server is up and running and I can see my test-data at http://localhost:8081/test

    I then created the file usersAPI.js in the folder /boot.

    import axios from '../boot/axios'
    
    export default {
      getUsers () {
        // console.log('GET USERS', axios().get('users'))
        var usersPromise = axios().get('users')
        usersPromise.then(function (result) {
          console.log('RESULT', result)
          return result
        })
          .catch(function (err) {
            console.log('ERROR: ', err)
          })
      }
    }
    

    Last but not least my code in the vue page:

    <template>
      <q-page class="flex flex-center">
        <div class="boxes">
          <div class="box">
            This is a box.
            <div v-if="dataReady">
              <p>Data:</p>
              <div v-for="user in users" v-bind:key="user._id.$oid">
                <p>{{ user.name }}</p>
              </div>
            </div>
          </div>
          <div class="box">
            This is a box
          </div>
        </div>
        <q-footer>
          <q-tabs>
            <q-tab
              name="new_entry"
              icon="add"
              label="" />
          </q-tabs>
        </q-footer>
      </q-page>
    </template>
    
    <script>
    import usersAPI from '../boot/usersAPI.js'
    
    export default {
      name: 'PageIndex',
      data () {
        return {
          dataReady: false,
          users: []
        }
      },
      mounted () {
        this.loadUsers()
      },
      methods: {
        async loadUsers () {
          const response = await usersAPI.getUsers()
          this.users = response.data
    
          this.dataReady = true
        }
      }
    }
    </script>
    

    Now the promise that is created in the getUsers() function returns the following error: ERROR: Error: "Request failed with status code 404"

    Also just before that my console returns the error TypeError: response is undefined, but I am not sure what part of my code throws this error.

    Hope you can help me!
    Thanks!



  • Have a look at this code: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Accessing-data-from-boot-files

    Notice how the instance is built, then bound to the Vue prototype and then also used as a named export. This make sure the axios attached to Vue and the exported axios are the same thing. Your code doesn’t do that. In your code, the axios Vue has is different than the one being exported. This doesn’t solve your problem. But, I figured I’d mention it.

    The 404 error means axios couldn’t get the resource that it requested. That error is from the server though. So, it sounds like axios connects with your server i.e. your server receives the request. However, your server isn’t finding the resource being requested. So, I think you’ll need to trouble shoot your server set up.

    Scott



  • @dollique said in Axios: Request failed with status code 404:

    axios().get(‘users’)

    You could have a look in the dev console network tab what url is actually called and see if it’s correct.



  • Thank you for your help.

    I resolved the problem thanks to the tip of @gvorster and the description of the issue by @s-molinari
    The URL was indeed wrong, but only because I defined it wrongly in the backend.

    I checked the docs that @s-molinari sent and noticed that I didn’t use the part where it says export { axiosInstance }.
    Should I do this? It works currently without this by just using mport axios from '../boot/axios' in my JS.
    When I put everything into the axiosInstance variable how do I use this instance? It throws an error that I have to use it, and that ‘axios’ is undefined.

    Thanks!



  • @dollique the problem with your way is you are always recreating your axios instance via axios.create when you import it, exposing the instance ie per docs example export { axiosInstance } means you are using the same instance that you have initiated in your boot file, so all configs you have already set in your bootfile is already there when you import it somewhere. in oop it’s called a singleton.



  • Do I understand correctly that this is used so, if I want a second instance (like a second backend server) I could just create another instance? I do not fully understand why to do this.

    I did it anyway and it also looks like my code is a bit cleaner now:

    axios.js

    import Vue from 'vue'
    import axios from 'axios'
    
    const axiosInstance = axios.create({
      baseURL: `http://localhost:8081/` // the url of our server
    })
    
    Vue.prototype.$axios = axiosInstance
    
    export { axiosInstance }
    

    usersAPI.js

    import { axiosInstance } from '../boot/axios'
    
    export default {
      getUsers: async () => {
        var usersPromise = axiosInstance.get('users')
        return usersPromise
      }
    }
    


  • Short follow-up question.

    I want to filter my results by the name of the user, so I implemented params like this:

    import { axiosInstance } from '../boot/axios'
    
    export default {
      getUsers: async (userName) => {
        var usersPromise = axiosInstance.get('users', {
          params: {
            name: 'test'
          }
        })
        return usersPromise
      }
    }
    

    This is ignored somehow so I tried to also change the backend to the following:

    app.get('/users', (req, res) => {
      const collection = client.db("MYDB").collection("users")
    
      collection.find(req.query.name).toArray(function (err, results) {
        if (err) {
          console.log(err)
          res.send([])
          return
        }
        res.send(results)
      })
    })
    

    changed find() to find(req.query.name).
    I also tried find(req.params.name) but didn’t work either.

    Hope you can help me.
    Thanks!

    EDIT:
    Found the solution.

    1. There is a difference between ‘query paramters’ and Route paramaters (‘params’).
    2. The correct code to filter for query parameters is find({name: req.query.name})

Log in to reply