Skip to content

Instantly share code, notes, and snippets.

@jkup
Last active May 2, 2023 04:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jkup/51a70a4241763157d353ef61b3c03376 to your computer and use it in GitHub Desktop.
Save jkup/51a70a4241763157d353ef61b3c03376 to your computer and use it in GitHub Desktop.
Building a video app with Cloudflare
export const cfTeamsAccessAuthMiddleware = async ({request, data, env, next}) => {
try {
const userEmail = request.headers.get("cf-access-authenticated-user-email")
if (!userEmail) {
throw new Error("User not found, make sure application is behind Cloudflare Access")
}
// Pass user info to next handlers
data.user = {
email: userEmail
}
return next()
} catch (e) {
return new Response(e.toString(), {status: 401})
}
}
export const onRequest = [
cfTeamsAccessAuthMiddleware
]
import { getSignedStreamId } from "../../src/cfStream"
export async function onRequestGet(context) {
const {
request,
env,
params,
} = context
const { id } = params
if (id) {
const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${env.CF_ACCOUNT_ID}/stream/${id}`, {
method: "GET",
headers: {
"Authorization": `Bearer ${env.CF_API_TOKEN_STREAM}`
}
})
const video = (await res.json()).result
if (video.meta.visibility !== "public") {
return new Response(null, {status: 401})
}
const signedId = await getSignedStreamId(id, env.CF_STREAM_SIGNING_KEY)
return new Response(JSON.stringify({
signedId: `${signedId}`
}), {
headers: {
"content-type": "application/json"
}
})
} else {
const url = new URL(request.url)
const res = await (await fetch(`https://api.cloudflare.com/client/v4/accounts/${env.CF_ACCOUNT_ID}/stream?search=${url.searchParams.get("search") || ""}`, {
headers: {
"Authorization": `Bearer ${env.CF_API_TOKEN_STREAM}`
}
})).json()
const filteredVideos = res.result.filter(x => x.meta.visibility === "public")
const videos = await Promise.all(filteredVideos.map(async x => {
const signedId = await getSignedStreamId(x.uid, env.CF_STREAM_SIGNING_KEY)
return {
uid: x.uid,
status: x.status,
thumbnail: `https://videodelivery.net/${signedId}/thumbnails/thumbnail.jpg`,
meta: {
name: x.meta.name
},
created: x.created,
modified: x.modified,
duration: x.duration,
}
}))
return new Response(JSON.stringify(videos), {headers: {"content-type": "application/json"}})
}
}
export async function onRequestPost(context) {
// Contents of context object
const {
env,
data,
} = context
const res = await fetch(`https://api.cloudflare.com/client/v4/accounts/${env.CF_ACCOUNT_ID}/stream/direct_upload`, {
method: "POST",
headers: {
"Authorization": `Bearer ${env.CF_API_TOKEN_STREAM}`
},
body: JSON.stringify({
maxDurationSeconds: 21600,
requireSignedURLs: true,
})
})
const newVideo = await res.json()
await fetch(`https://api.cloudflare.com/client/v4/accounts/${env.CF_ACCOUNT_ID}/stream/${newVideo.result.uid}`, {
method: "POST",
headers: {
"Authorization": `Bearer ${env.CF_API_TOKEN_STREAM}`
},
body: JSON.stringify({
meta: {
modified_by: data.user.email
}
})
})
return new Response(JSON.stringify(newVideo.result), {headers: {"content-type": "application/json"}})
}
async function getOneTimeUploadUrl() {
const res = await fetch('/api/admin/videos', {method: 'POST', headers: {'accept': 'application/json'}})
const upload = await res.json()
return upload.uploadURL
}
async function uploadVideo() {
const videoInput = document.getElementById("video");
const oneTimeUploadUrl = await getOneTimeUploadUrl();
const video = videoInput.files[0];
const formData = new FormData();
formData.append("file", video);
const uploadResult = await fetch(oneTimeUploadUrl, {
method: "POST",
body: formData,
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment