How to fetch API from backend using vercel's serverless functions

A beginner-friendly tutorial from a beginner

·

5 min read

Imagine you're a fresh naïve junior frontend dev who's working on your first personal project outside of course materials.

You think to yourself:

There's plenty to learn just in frontend alone, I'll stick to frontend for now and learn backend later. Besides, with the ability to fetch data from APIs that's enough ammunition to build dope apps! Probably won't be touching backend anytime soon.

Then the internet hits you with that...

CORS ERROR.

Well, that happened to me.

Why don't we just fetch API using frontend?

  • Because CORS error

  • Because you want to keep your API key secure

So what do we want to happen?

  1. User inputs query on the frontend

  2. An API request is sent from the frontend to the backend sever

  3. The backend server fetches the data from the API

  4. The server returns the data to the frontend

  5. Happy days

⚠️ Note: This tutorial assumes you already have a vercel project setup and/or linked to your github repo ie. you know how to deploy updates to vercel. If not see this article to get started with vercel.

Step 1: Setup

First we'll have to install the required packages.

  • axios - an alternative to the native fetch function (optional)

  • express - creates the server

  • dotenv - to keep your API keys secret

  • cors - to deal with CORS

Go to your project's root folder, then in the terminal run:

npm install axios express cors dotenv

Then in your project root folder, create a new folder called api (must be exactly this for deploying to vercel). Inside of that folder, create a new file called index.js.

To do this via the terminal, assuming you're already in your project root folder, run

mkdir api
touch api/index.js

In index.js, paste the following code to create an express "server".

// Load packages
const express = require('express')
const cors = require('cors')
require('dotenv').config()
const axios = require('axios')

// Create express server
const app = express()

Step 2: Enable CORS

Then paste the following code to enable CORS. The * means any origin is allowed. Please see this article for alternate methods to enable CORS on vercel.

app.use(
  cors({
    origin: '*',
  })
)

Step 3: Create our backend serverless API functions

Ok, we're now going to use vercel's serverless functions feature.

Here's my basic understanding of it:

  • Typically we could set up a server that's running constantly 24/7 listening for api requests - but that can be expensive.

  • Vercel instead offers serverless functions which runs code on-demand. Basically it's like a pop-up shop that only sets up when there's a customer (a request is made). After it successfully serves the customer, it disappears, poof. The benefit is that it's cheaper (free or paid depending on how long it takes the function to finish executing) and we don't need to manage things like infrastructure etc.

If you want to understand vercel serverless functions better I recommend watching this video

In the following code, we'll create two api endpoints.

// req = request, res = response
app.get('/api', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Cache-Control', 's-max-age=1, stale-while-revalidate')
  res.send('hi wyd') // optional message
})

The following function for the 'smart-floor-price' endpoint will,

  • take in a request from the frontend (we'll sort out the frontend later),

  • read the request's parameters,

  • forward the request to the 3rd-party api and fetch the data

  • return the data to the frontend

To create more endpoints simply duplicate this function and change the endpoint name and the appropriate settings for fetching api.

app.get('/api/smart-floor-price', (req, res) => {
  async function getSmartFloorPrice(contractAddress) {
    try {
      const config = {
        method: 'GET',
        headers: { Authorization: `Bearer ${process.env.YOUR_API_KEY}` },
        url: `https://api.rarify.tech/data/contracts/ethereum:${contractAddress}/smart-floor-price`,
      }
      const data = await axios(config).then((res) => res.data)

      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  const contractAddress = req.query.contractAddress // this is how to get the request parameters from the frontend
  getSmartFloorPrice(contractAddress)
})

We're almost done! Add the following code at the end of index.js.

module.exports = app

Step 4: add some code to vercel.json

Paste the following code in your vercel.json file. If you don't have one, create one in the root folder.

{
  "rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
}

Now you're ready to save your files and deploy to vercel!

Full code for api/index.js

const express = require('express')
const cors = require('cors')
require('dotenv').config()
const axios = require('axios')

const app = express()

app.use(
  cors({
    origin: '*',
  })
)

app.get('/api', (req, res) => {
  res.setHeader('Content-Type', 'text/html')
  res.setHeader('Cache-Control', 's-max-age=1, stale-while-revalidate')
  res.send('hi wyd')
})

app.get('/api/smart-floor-price', (req, res) => {
  async function getSmartFloorPrice(contractAddress) {
    try {
      const config = {
        method: 'GET',
        headers: { Authorization: `Bearer ${process.env.YOUR_API_KEY}` },
        url: `https://api.rarify.tech/data/contracts/ethereum:${contractAddress}/smart-floor-price`,
      }
      const data = await axios(config).then((res) => res.data)

      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  const contractAddress = req.query.contractAddress 
  getSmartFloorPrice(contractAddress)
})

module.exports = app

Final step: Use your brand spanking new apis in your frontend

After deploying your serverless functions to vercel, simply fetch data from the frontend using the your app's vercel url. For example it'll be something like this in your frontend script:

async function getSmartFloorPrice(contractAddress) {
  try {
    const config = {
      method: 'GET',
      url: `https://your-app.vercel.app/api/smart-floor-price`,
      params: {
        contractAddress: contractAddress,
      },
    }
    const data = await axios(config).then((res) => res.data)
    return data
  } catch (err) {
    console.log(err)
  }
}

Remixed from / sauces:

Did you find this article valuable?

Support dahlia by becoming a sponsor. Any amount is appreciated!