UNPKG

@httpland/range-request-middleware

Version:
70 lines (69 loc) 2.97 kB
"use strict"; // Copyright 2023-latest the httpland authors. All rights reserved. MIT license. // This module is browser compatible. Object.defineProperty(exports, "__esModule", { value: true }); exports.acceptRanges = exports.contentRange = exports.rangeRequest = void 0; const deps_js_1 = require("./deps.js"); const transform_js_1 = require("./transform.js"); const bytes_js_1 = require("./ranges/bytes.js"); const utils_js_1 = require("./utils.js"); /** Create range request middleware. * * @example * ```ts * import { rangeRequest } from "https://deno.land/x/range_request_middleware@$VERSION/middleware.ts"; * import { * assert, * assertEquals, * assertThrows, * } from "https://deno.land/std/testing/asserts.ts"; * * const middleware = rangeRequest(); * const request = new Request("test:", { * headers: { range: "bytes=5-9" }, * }); * const response = await middleware( * request, * () => new Response("abcdefghijklmnopqrstuvwxyz"), * ); * * assertEquals(response.status, 206); * assertEquals(response.headers.get("content-range"), "bytes 5-9/26"); * assertEquals(response.headers.get("accept-ranges"), "bytes"); * assertEquals(await response.text(), "fghij"); * ``` */ function rangeRequest(ranges) { const $ranges = ranges ?? [new bytes_js_1.BytesRange()]; const units = Array.from($ranges).map((range) => range.rangeUnit); const unitLike = (0, deps_js_1.isNotEmpty)(units) ? units : utils_js_1.RangeUnit.None; const contentRangeMiddleware = contentRange($ranges); const acceptRangesMiddleware = acceptRanges(unitLike); return (request, next) => { return contentRangeMiddleware(request, (request) => acceptRangesMiddleware(request, next)); }; } exports.rangeRequest = rangeRequest; function contentRange(ranges) { const $ranges = ranges ?? [new bytes_js_1.BytesRange()]; return async (request, next) => { const rangeValue = request.headers.get(deps_js_1.RangeHeader.Range); // A server MUST ignore a Range header field received with a request method that is unrecognized or for which range handling is not defined. For this specification, GET is the only method for which range handling is defined. // @see https://www.rfc-editor.org/rfc/rfc9110#section-14.2-4 if (request.method !== deps_js_1.Method.Get || (0, deps_js_1.isNull)(rangeValue) || request.headers.has(deps_js_1.ConditionalHeader.IfRange)) return next(request); const response = await next(request); return (0, transform_js_1.withContentRange)(response, { ranges: $ranges, rangeValue }); }; } exports.contentRange = contentRange; function acceptRanges(unitLike) { const rangeUnit = unitLike ?? utils_js_1.RangeUnit.Bytes; return async (request, next) => { const response = await next(request); return (0, transform_js_1.withAcceptRanges)(response, rangeUnit); }; } exports.acceptRanges = acceptRanges;