Skip to content

Commit

Permalink
fix: address review
Browse files Browse the repository at this point in the history
  • Loading branch information
vasco-santos committed Jun 28, 2022
1 parent 07872ae commit 5cd00ff
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 22 deletions.
1 change: 1 addition & 0 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
},
"dependencies": {
"@supabase/postgrest-js": "^0.37.2",
"http-range-parse": "^1.0.0",
"itty-router": "^2.4.5",
"multiformats": "^9.6.4",
"nanoid": "^3.1.30",
Expand Down
6 changes: 3 additions & 3 deletions packages/api/src/env.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,16 +126,16 @@ function getSentry(request, env, ctx) {
* @property {Headers} [httpMetadata]
* @property {Record<string, string>} [customMetadata]
*
* @typedef {Object} R2Range
* @property {number} [offset]
* @property {number} [length]
* @typedef {{ offset: number, length?: number } | { offset?: number, length: number } | { suffix: number }} R2Range
*
* @typedef {Object} R2GetOptions
* @property {R2Range} [range]
*
* @typedef {Object} R2Object
* @property {Date} uploaded
* @property {number} size
* @property {string} httpEtag
* @property {(headers: Headers) => void} writeHttpMetadata
* @property {Headers} [httpMetadata]
* @property {Record<string, string>} [customMetadata]
*
Expand Down
61 changes: 42 additions & 19 deletions packages/api/src/perma-cache/get.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-env serviceworker, browser */
/* global Response */

import parseRange from 'http-range-parse'

import { getSourceUrl, getNormalizedUrl } from '../utils/url.js'
import { UrlNotFoundError, InvalidRangeError } from '../errors.js'

Expand All @@ -21,38 +23,59 @@ export async function permaCacheGet(request, env) {
const r2Key = normalizedUrl.toString()

// Get range header
const range = parseRange(request.headers.get('range'))
const range = toR2Range(request.headers.get('range'))
const r2Object = await env.SUPERHOT.get(r2Key, {
range,
})
if (r2Object) {
return new Response(r2Object.body, {
status: range ? 206 : 200,
})

if (!r2Object || !r2Object.body) {
throw new UrlNotFoundError()
}

const headers = new Headers()
headers.set('etag', r2Object.httpEtag)
r2Object.writeHttpMetadata(headers)

if (range) {
headers.set('status', '206')
let first, last
if (range.suffix != null) {
first = r2Object.size - range.suffix
last = r2Object.size - 1
} else {
first = range.offset || 0
last = range.length != null ? first + range.length - 1 : r2Object.size - 1
}
headers.set('content-range', `bytes ${first}-${last}/${r2Object.size}`)
headers.set('content-length', `${last - first + 1}`)
} else {
headers.set('status', '200')
headers.set('content-length', `${r2Object.size}`)
}

throw new UrlNotFoundError()
return new Response(r2Object.body, {
status: range ? 206 : 200,
})
}

/**
* Convert a HTTP Range header to an R2 range object.
*
* @param {string|null} encoded
* @returns {R2Range}
* @returns {R2Range|undefined}
*/
function parseRange(encoded) {
function toR2Range(encoded) {
if (encoded === null) {
return
}

const parts = encoded.split('bytes=')[1]?.split('-') ?? []
if (parts.length !== 2) {
throw new InvalidRangeError(
'Not supported to skip specifying the beginning/ending byte at this time'
)
}

return {
offset: Number(parts[0]),
length: Number(parts[1]) + 1 - Number(parts[0]),
}
const result = parseRange(encoded)
if (result.ranges)
throw new InvalidRangeError('Multiple ranges not supported')
const { unit, first, last, suffix } = result
if (unit !== 'bytes')
throw new InvalidRangeError(`Unsupported range unit: ${unit}`)
return suffix != null
? { suffix }
: { offset: first, length: last != null ? last - first + 1 : undefined }
}
9 changes: 9 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5cd00ff

Please sign in to comment.