1

I am working with a Nuxt.js v2.15.8 project and I am attempting to use the server middleware feature that Nuxt offers for A custom API endpoint. https://nuxtjs.org/docs/configuration-glossary/configuration-servermiddleware/#custom-api-endpoint

What I am trying to accomplish:

Use Nuxt server middleware to make a GET request to a 3rd party api to retrieve data. When I try to set this up and make the request to the endpoint in Postman, I get an error

<!doctype html>
<html data-n-head-ssr lang="en" data-n-head="%7B%22lang%22:%7B%22ssr%22:%22en%22%7D%7D">

<head>
    <title>This page could not be found</title> etc....

How do I use the Nuxt server middleware to make api calls to external api's?

Nuxt.config.js

  serverMiddleware: [
    {
      path: '/api/server-middleware',
      handler: '~/api/getData.js',
    },
  ],

~/api/getData.js

const bodyParser = require('body-parser');
const app = require('express')();

app.use(bodyParser.json());

app.all('https://jsonplaceholder.typicode.com/todos/1', (req, res) => {
  res.json({ data: res.data });
});

module.exports = app;

In Postman I try to make a GET request to http://localhost:3000/api/server-middleware after running npm run dev and my Nuxt project is running.

Am I misunderstanding how this is supposed to work? Is the Server Middleware for internal api calls only?

kissu
  • 40,416
  • 14
  • 65
  • 133
CodeConnoisseur
  • 1,452
  • 4
  • 21
  • 49

1 Answers1

1

Applying the least possible amount of changes to your shared code gives us the following

getData.js

import axios from 'axios'
const app = require('express')()

app.all('/jsonplaceholder/:id', async (req, res) => {
  const { data } = await axios(
    `https://jsonplaceholder.typicode.com/todos/${req.params.id}`
  )
  res.json({ ...data })
})

module.exports = app

/pages/index.vue

<template>
  <div>
    <input id="name" v-model="todoId" type="text" name="name" />
    <button @click="callNuxtApi">try local Nuxt API</button>
    <div>
      Response from the backend:
      <pre>{{ response }}</pre>
    </div>
  </div>
</template>

<script>
export default {
  name: 'JsonPlaceholderPage',
  data() {
    return {
      todoId: 1,
      response: {},
    }
  },
  methods: {
    async callNuxtApi() {
      const response = await this.$axios.$get(`/api/server-middleware/jsonplaceholder/${this.todoId}`)
      console.log('response', response)
      this.response = response
    },
  },
}
</script>

As you can see, /jsonplaceholder/:id is something more reasonable considering that it will be prefixed by /api/server-middleware/ already.
Having https:// inside of a path is not really nice to the browser overall.

PS: you need to install axios and express for it to work. @nuxtjs/axios will not work here.


This answer joins my other one here: https://stackoverflow.com/a/72102209/8816585

kissu
  • 40,416
  • 14
  • 65
  • 133
  • I guess my question is, what is the purpose of having the server middleware setup at all if I can just make the api call to json placeholder directly from any vue component? What problem does nuxt server middleware solve? Thanks! – CodeConnoisseur Aug 21 '22 at 14:05
  • 1
    @CodeConnoisseur it makes the call on the backend (Node.js part) so it could avoid some CORS issues, use some private tokens, use some non-browser APIs etc... Your question here is more of: "what is the difference between a client-side vs server-side HTTP call". So, it solves this particular use-case. Probably totally not worth in your example indeed. – kissu Aug 21 '22 at 14:10
  • that makes sense, so in a scenario where I am making a REST call to an endpoint that requires me to send a bearer token without exposing to the client, in that case I would want to use the nuxt server middleware...correct? – CodeConnoisseur Aug 21 '22 at 15:50
  • 1
    @CodeConnoisseur you can do that yes, as [explained here](https://stackoverflow.com/a/72102209/8816585) but with Nuxt2 it's a bit tricky (simpler with Nuxt3 tho). You can also use a middleware backend (located somewhere else) or a serverless function for simple and quick tasks that still need to hide some private tokens. – kissu Aug 21 '22 at 17:43