Astro Cookies API
Cookies on HTTP Requests
🚀 Astro Cookies API
The Astro cookies API provides a way to pass data between user browser and the server. You can use it on your SSR sites, as an example, to keep track of whether a user is authenticated. Essentially, the API is just a wrapper for JavaScript and browser APIs which let you set cookies on HTTP requests by adding a cookies header. That said, the standard APIs have a little boilerplate code and the Astro Cookie API will save you some typing!
To see how the API works we will look at an example with the Mux video player. We will see how you might save the video playback position using cookies. This could be used to let a logged-in user resume a video from the right place even if they switch device. The main goal here is to show how the API works, and you can adapt the code we see to work with HTTP cookies in many use cases.
For some cookie use cases you can manage cookies just on the client side with JavaScript APIs. We focus on using cookies in HTTP requests between client and server.
🧱 What are we Building?
We will set up a video with Mux video player in an Astro SSR app. In the video component, we will use browser APIs to let us know when the user pauses playback. We then send the playback position to our API endpoint, where we can save it to a database ready for the user’s next login. In the API endpoint we will also set the cookie with the playback position using the Astro Cookie API, of course! Finally, in our Astro client code, we will have a check for the playback position cookie and pass any value to the video player component.
If that sounds like what you were looking for, then why don’t we get started? We won’t build the app step-by-step, but there is a link further down the page to the full project code on GitHub. You will need a Mux account (and to upload some video) to try out the full code, and you can do this for free.
🎥 Mux Video Player Component
We are working in Svelte here. This makes it easier to load the script tag we require for the Mux player and also to access the embedded video element APIs.
<script lang="ts">
export let videoId = import.meta.env.PUBLIC_MUX_PLAYBACK_ID as string;
export let title = 'Raindrops in Super Slow Motion';
export let startTime = '0';
const siteUrl = import.meta.env.PUBLIC_SITE_URL;
let playerElement: HTMLMediaElement;
async function handlePause() {
const currentTime = Math.floor(playerElement.currentTime);
fetch(`${siteUrl}/api/player?startTime=${currentTime}`, {
method: 'POST',
});
}
</script>
<svelte:head><script src="https://cdn.jsdelivr.net/npm/@mux/mux-player"></script></svelte:head>
<figure>
<mux-player
bind:this={playerElement}
playback-id={videoId}
stream-type="on-demand"
{title}
disable-cookies
start-time={startTime}
on:timeupdate={console.log(Math.floor(playerElement.currentTime))}
on:pause={handlePause}
/>
<figcaption>
{title}. Credit: <a href="https://www.videvo.net/profile/Beachfront">Beachfront</a>
</figcaption>
</figure>
<style>
mux-player {
display: flex;
max-width: var(--max-width-full);
aspect-ratio: 16 / 9;
}
</style>
We are using a couple of MediaElement API events here. onTimeUpdate
(line 27
) tracks playback, letting us know the video is actually playing. We just console log the currentTime
here and include it for reference. We do use the onPause
event (line 28
) however. As you might expect, this causes our handlePause
function to be invoked when the user taps the pause button. The current time has millisecond precision, which is probably a little more than we require. We use Math.floor
to truncate the value.
The other thing to note is using browser APIs, we can set the playback start time and do so in line 26
, This will be passed in when we create an instance of this component later.
In the handlePause
function, we use fetch
to send a POST
HTTP request to our own endpoint with the currentTime as a URL-encoded string. Let’s look at that endpoint code next.
▶️ Astro Cookies API: Player Endpoint
This code listens for for HTTP requests on the http://example.com/api/player
.
import type { APIRoute } from 'astro';
const siteUrl = import.meta.env.PUBLIC_SITE_URL;
export const post: APIRoute = async function post({ cookies, redirect, request }) {
try {
const { url: requestUrl } = request;
const { searchParams } = new URL(requestUrl);
const startTime = searchParams.get('startTime');
console.log({ startTime });
cookies.set('start-time', '31', { path: '/' });
return new Response('', { status: 200 });
} catch (error: unknown) {
console.error(`Error in player api route: ${error as string}`);
return redirect(`${siteUrl}/`);
}
};
You might notice the code is a little slimmed down compared to what you would expect to find in a production app. We just console log the startTime
once we have parsed it from the request here. You would want to store it to the database against the logged-in user in a real-world app.
The code in line 12
is where we set the cookie. In a complete app, this would probably go in the login logic, so if the user switched device. We would read the startTime
from the database and set it on the cookie.
Astro Cookies API
In endpoints, you can access the API using the cookie
object on the API route (as in line 5
). The API has a few methods which all do exactly what you would expect them to: get
, set
and has
are probably the ones you will be reaching for most often. In line 12
above, we call set
. The first argument is the cookie name start-time
in this case. The second argument is the value for that cookie. It is a simple string here. It can be an object instead, though you would want to try to limit yourself to types which can automatically serialized with JSON.stringify.
The final argument to the set
call is the options. This is where you can set expires
as a date, httpOnly
(for more secure cookies which JavaScript code running in the browser cannot access). sameSite
and secure
are other values you would consider setting here. Here we just set path
, which is the web page paths the cookie will apply to.
We just return an empty response, and this is enough to set the cookie on the user device. The final part is to read this data client-side, which we see next.
🧑🏽 Astro Cookies API: Reading Cookies Client-side
To access the Astro Cookie API from the client, we can use the Astro
global. One thing to note is that the cookie API is only accessible in .astro
and API endpoint files. Because of that, we read in the cookie value in the index.astro
client file and pass it as a prop to the Video component.
---
import '~styles/fonts.css';
import '~styles/global.css';
import Video from '~components/Video.svelte';
const startTime = Astro.cookies.get('start-time').value ?? '0';
const title = 'Astro Cookies API';
const description = 'Astro Cookies API: mux video position save example';
---
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="/favicon.ico" sizes="any" />
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/manifest.webmanifest" />
<title>{title}</title>
{description ? <meta name="description" content={description} /> : null}
</head>
<main>
<h1>Astro Cookies API 🍪</h1>
<Video client:load {startTime} />
</main>
We call Astro.cookies.get('cookie-name').value
here to retrieve the string value we stored in the endpoint. If we had stored an object, instead of a string, then we would have used:
Astro.cookies.get('cookie-name').json()
That gets us back an object. If we pause the video, then refresh the browser, the video skips to 31
. seconds (the value we set on the cookie). Remember, in a real-world app we would have pulled an actual startTime
value from our database and used that value instead of our arbitrary 31
value.
🙌🏽 Astro Cookies API: Wrapping Up
In this post, we saw how the Astro Cookies API works and also some browser Media Element APIs. In particular, we saw:
- how to set cookies in a server endpoint in Astro,
- how to read cookies in client code,
- a way to capture video current time and a pause action in Svelte.
You can see the full code for this project in the Rodney Lab GitHub repo. I do hope you have found this post useful! I am keen to hear what you are doing with Astro and ideas for future projects. Also let me know about any possible improvements to the content above.
🙏🏽 Astro Cookies API: Feedback
Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.
Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter, @rodney@toot.community on Mastodon and also the #rodney Element Matrix room. Also, see further ways to get in touch with Rodney Lab. I post regularly on Astro as well as SEO. Also subscribe to the newsletter to keep up-to-date with our latest projects.