Resolve CORS with Vercel Serverless Functions

Resolve CORS with Vercel Serverless Functions

So you've got a cool idea for a side project that involves an API, let's Say Twitter API. You quickly signed up for the dev account and generated an Access Token.

Your brain is having an overflow of ideas. You've already sketched a rough design for your cool app and can't wait to code it out.

You start a React project and just want to see that first beautiful response from API:

export default function App() {
  const [data, setData] = useState();
  const handler = () =>
    fetch(
      'https://api.twitter.com/2/users/by/username/naval',
      {
        headers: {
          Accept: 'application/json',
 // TWITTER_BEARER_TOKEN: is your Token you got from Twitter
          Authorization: process.env.TWITTER_BEARER_TOKEN
        }
      }
    )
      .then((x) => x.json())
      .then((data) => setData(JSON.stringify(data)))
      .catch((error) => console.log(JSON.stringify(error.message)));

  return (
    <div className="App">
      <header className="App-header">
        <p>User: {data}</p>
        <button onClick={handler}>Bring me User</button>
      </header>
    </div>
  );
}

Yay, It's ready to bring you the user info.

you start the project yarn start, but oops...

Access to fetch at 'https://api.twitter.com/2/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

Stopped.jpg

Now you googled and found that Twitter API doesn't support CORS and this API can't be used on the frontend. Now one solution is to set up a proxy server and call it on that proxy server and return the response you want from that server, easy-peasy(Not so much 😶).

Ah, all this just to make a simple app and get a single response?

Vercel Serverless Functions to the Rescue

Writing a Vercel serverless function is super easy (trust me on this). Vercel Serverless functions aren't dependent on any frontend framework configuration, If you've an existing project then on the project's root directory create a new folder /api Or if you want to set up it as a standalone project then just create a folder and inside it create a new folder /api, we'll put our files here in this directory.

Now create a file in this /api/test.js, and write below code:

export default function handler(request, response) {
  const { name } = request.query;
  response.status(200).json({name});
}

Now, we need Vercel CLI, run the below command in your terminal:

npm i -g vercel
OR
yarn global add vercel

after this, Now run below commands in the root directory of your project to configure Vercel with your awesome project.

It may ask you to log in if it's the first time you're using it

VercelProjectSetup.png

after this setup to start the project run command vercel dev , Now if everything works in your favor you'll see something like this in your terminal.

image.png

Now go to this URL http://localhost:3000/api/test?name=Thanos

Your API is running and you'll get your response.

Now coming back to our original problem, the Twitter API. to get the response in your browser or in your React app, etc. configure it like this.

const fetch = require('node-fetch');

const handler = async (req, res) => {
  const { username } = req.query;

  let url = `https://api.twitter.com/2/users/by/username/${username}`;

  try {
    const response = await fetch(url, {
      headers: {
        Accept: 'application/json',
        Authorization: process.env.TWITTER_BEARER_TOKEN,
      },
    });

    if (!response.ok) {
      res.status(response.status).json(response.statusText);
    }
    const data = await response.json();

    res.status(200).json(data);
  } catch (error) {
    res.status(500).json(error);
  }
};

export default handler;

Now you may have to set up your project with npm init because we'll need node-fetch to make a network request here. You need a little bit of familiarity with Syntax and the basics of Node.js to make tweaks in this to make it work for you.

Now our API is done and if you run your project you'll get the response in the browser from the Twitter API but if you get an error or maybe no response when you try to use your awesome proxy API in code to fetch the data, It could be because CORS is disabled here too but this being your own API you can modify this, you need to set up the headers, To do so:

Create a new vercel.json file in the project's root and put below JSON Object of headers:

{
  "headers": [
    {
      "source": "/api/(.*)",
      "headers": [
        { "key": "Access-Control-Allow-Credentials", "value": "true" },
        { "key": "Access-Control-Allow-Origin", "value": "*" },
        { "key": "Access-Control-Allow-Methods", "value": "GET,OPTIONS,PATCH,DELETE,POST,PUT" },
        { "key": "Access-Control-Allow-Headers", "value": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" }
      ]
    }
  ]
}

And here we're done, to deploy it to production just run command vercel in the terminal, you'll get the deployment message with the temporary URL of the production environment.

Conclusion

Now you can make use of these serverless functions to proxy literally any API be it due to CORS or other reasons.

So did you face such CORS errors anytime? Let me know in the comments and yes it'll be of great help if you can give some feedback/suggestions.

That's all I got today. I'll be back with another blog on some core concept or a hack just like this one, until then 🫡.