1
mirror of https://github.com/jakejarvis/jarv.is.git synced 2025-04-26 14:28:25 -04:00

clean up serverless functions

This commit is contained in:
Jake Jarvis 2021-11-08 07:01:05 -05:00
parent 4da59e5e81
commit 6ff4bc52e5
Signed by: jake
GPG Key ID: 2B0C9CF251E69A39
8 changed files with 43 additions and 51 deletions

View File

@ -29,6 +29,6 @@ The [Vercel CLI](https://vercel.com/docs/cli) is not included as a project depen
![Creative Commons Attribution 4.0 International License](https://raw.githubusercontent.com/creativecommons/cc-cert-core/master/images/cc-by-88x31.png "CC BY")
Site content (everything in [`content/notes`](content/notes/)) is published under the [**Creative Commons Attribution 4.0 International License**](LICENSE.md) (CC-BY-4.0), which means that you can copy, redistribute, remix, transform, and build upon the content for any purpose as long as you give appropriate credit.
Site content (everything in [`content/notes`](content/notes/)) is published under the [**Creative Commons Attribution 4.0 International License**](LICENSE) (CC-BY-4.0), which means that you can copy, redistribute, remix, transform, and build upon the content for any purpose as long as you give appropriate credit.
All original code in this repository is published under the [**MIT License**](https://opensource.org/licenses/MIT).

View File

@ -16,22 +16,17 @@ const { AIRTABLE_API_KEY, AIRTABLE_BASE } = process.env;
const AIRTABLE_API_ENDPOINT = "https://api.airtable.com/v0/";
export default async (req, res) => {
// disable caching on both ends
res.setHeader("Cache-Control", "private, no-cache, no-store, must-revalidate");
res.setHeader("Expires", 0);
res.setHeader("Pragma", "no-cache");
// permissive access control headers
res.setHeader("Access-Control-Allow-Methods", "POST");
res.setHeader("Access-Control-Allow-Origin", "*");
try {
// some rudimentary error handling
// permissive access control headers
res.setHeader("Access-Control-Allow-Methods", "POST");
res.setHeader("Access-Control-Allow-Origin", "*");
// disable caching on both ends
res.setHeader("Cache-Control", "private, no-cache, no-store, must-revalidate");
res.setHeader("Expires", 0);
res.setHeader("Pragma", "no-cache");
if (req.method !== "POST") {
throw new Error(`Method ${req.method} not allowed.`);
}
if (!AIRTABLE_API_KEY || !AIRTABLE_BASE) {
throw new Error("Airtable API credentials aren't set.");
return res.status(405).send(); // 405 Method Not Allowed
}
const { body } = req;
@ -60,7 +55,7 @@ export default async (req, res) => {
}
// return in JSON format
res.status(200).json({ success: true });
return res.status(200).json({ success: true });
} catch (error) {
console.error(error);
@ -73,7 +68,8 @@ export default async (req, res) => {
await Sentry.flush(2000);
}
res.status(400).json({ success: false, message: message });
// 500 Internal Server Error
return res.status(500).json({ success: false, message: message });
}
};

View File

@ -15,12 +15,12 @@ const BASE_URL = "https://jarv.is/";
export default async (req, res) => {
try {
// some rudimentary error handling
// permissive access control headers
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
if (req.method !== "GET") {
throw new Error(`Method ${req.method} not allowed.`);
}
if (!process.env.FAUNADB_SERVER_SECRET) {
throw new Error("Database credentials aren't set.");
return res.status(405).send(); // 405 Method Not Allowed
}
const client = new faunadb.Client({
@ -52,10 +52,7 @@ export default async (req, res) => {
res.setHeader("Pragma", "no-cache");
}
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
res.status(200).json(result);
return res.status(200).json(result);
} catch (error) {
console.error(error);
@ -65,7 +62,8 @@ export default async (req, res) => {
const message = error instanceof Error ? error.message : "Unknown error.";
res.status(400).json({ success: false, message: message });
// 500 Internal Server Error
return res.status(500).json({ success: false, message: message });
}
};

View File

@ -8,12 +8,12 @@ Sentry.init({
export default async (req, res) => {
try {
// some rudimentary error handling
// permissive access control headers
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
if (req.method !== "GET") {
throw new Error(`Method ${req.method} not allowed.`);
}
if (!process.env.GH_PUBLIC_TOKEN) {
throw new Error("GitHub API credentials aren't set.");
return res.status(405).send(); // 405 Method Not Allowed
}
// allow custom limit, max. 24 results
@ -33,10 +33,8 @@ export default async (req, res) => {
// let Vercel edge and browser cache results for 15 mins
res.setHeader("Cache-Control", "public, max-age=900, s-maxage=900, stale-while-revalidate");
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
res.status(200).json(result);
return res.status(200).json(result);
} catch (error) {
console.error(error);
@ -46,7 +44,8 @@ export default async (req, res) => {
const message = error instanceof Error ? error.message : "Unknown error.";
res.status(400).json({ success: false, message: message });
// 500 Internal Server Error
return res.status(500).json({ success: false, message: message });
}
};

View File

@ -23,17 +23,18 @@ const TOP_TRACKS_ENDPOINT = "https://api.spotify.com/v1/me/top/tracks?time_range
export default async (req, res) => {
try {
// some rudimentary error handling
// permissive access control headers
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
if (req.method !== "GET") {
throw new Error(`Method ${req.method} not allowed.`);
}
if (!process.env.SPOTIFY_CLIENT_ID || !process.env.SPOTIFY_CLIENT_SECRET || !process.env.SPOTIFY_REFRESH_TOKEN) {
throw new Error("Spotify API credentials aren't set.");
return res.status(405).send(); // 405 Method Not Allowed
}
// default to top tracks
let response;
// get currently playing track (/music/?now), otherwise top 10 tracks
// get currently playing track (/api/tracks/?now), otherwise top 10 tracks
if (typeof req.query.now !== "undefined") {
response = await getNowPlaying();
@ -46,10 +47,7 @@ export default async (req, res) => {
res.setHeader("Cache-Control", "public, max-age=10800, s-maxage=10800, stale-while-revalidate");
}
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Access-Control-Allow-Origin", "*");
res.status(200).json(response);
return res.status(200).json(response);
} catch (error) {
console.error(error);
@ -59,7 +57,8 @@ export default async (req, res) => {
const message = error instanceof Error ? error.message : "Unknown error.";
res.status(400).json({ success: false, message: message });
// 500 Internal Server Error
return res.status(500).json({ success: false, message: message });
}
};
@ -100,7 +99,7 @@ const getNowPlaying = async () => {
if (active.is_playing === true && active.item) {
return {
isPlaying: active.is_playing,
artist: active.item.artists.map((_artist) => _artist.name).join(", "),
artist: active.item.artists.map((artist) => artist.name).join(", "),
title: active.item.name,
album: active.item.album.name,
imageUrl: active.item.album.images ? active.item.album.images[0].url : undefined,
@ -126,7 +125,7 @@ const getTopTracks = async () => {
const { items } = await response.json();
const tracks = items.map((track) => ({
artist: track.artists.map((_artist) => _artist.name).join(", "),
artist: track.artists.map((artist) => artist.name).join(", "),
title: track.name,
album: track.album.name,
imageUrl: track.album.images ? track.album.images[0].url : undefined,

View File

@ -1,6 +1,6 @@
import "./src/dark-mode.js";
import "./src/emoji.js";
import "./src/counter.js";
import "./src/hits.js";
import "./src/clipboard.js";
import "./src/anchor.js";
import "./src/contact.js";

View File

@ -13,7 +13,7 @@ Okay, this is an easy one. 😉
A simple hit counter on each page tallies an aggregate number of pageviews (i.e. `hits = hits + 1`). Individual views and identifying (or non-identifying) details are **never stored or logged**.
The [serverless function](https://github.com/jakejarvis/jarv.is/blob/main/api/hits.js) and [client script](https://github.com/jakejarvis/jarv.is/blob/main/assets/js/src/counter.js) are open source, and [snapshots of the database](https://github.com/jakejarvis/website-stats) are public.
The [serverless function](https://github.com/jakejarvis/jarv.is/blob/main/api/hits.js) and [client script](https://github.com/jakejarvis/jarv.is/blob/main/assets/js/src/hits.js) are open source, and [snapshots of the database](https://github.com/jakejarvis/website-stats) are public.
{{< image src="images/fauna_hits.png" alt="The entire database schema." link="/privacy/images/fauna_hits.png" />}}