mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-19 14:48:08 +02:00
Use Headers
consistently in the different IPDFStream
implementations
The `Headers` functionality is now available in all browsers/environments that we support, which allows us to consolidate and simplify how the `httpHeaders` API-option is handled; see https://developer.mozilla.org/en-US/docs/Web/API/Headers#browser_compatibility Also, simplifies the old `NetworkManager`-constructor a little bit.
This commit is contained in:
parent
0676ea19cf
commit
d3a94f17cb
5 changed files with 82 additions and 57 deletions
|
@ -15,6 +15,7 @@
|
|||
|
||||
import { AbortException, assert, warn } from "../shared/util.js";
|
||||
import {
|
||||
createHeaders,
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
|
@ -38,18 +39,6 @@ function createFetchOptions(headers, withCredentials, abortController) {
|
|||
};
|
||||
}
|
||||
|
||||
function createHeaders(httpHeaders) {
|
||||
const headers = new Headers();
|
||||
for (const property in httpHeaders) {
|
||||
const value = httpHeaders[property];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
headers.append(property, value);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
function getArrayBuffer(val) {
|
||||
if (val instanceof Uint8Array) {
|
||||
return val.buffer;
|
||||
|
@ -66,7 +55,7 @@ class PDFFetchStream {
|
|||
constructor(source) {
|
||||
this.source = source;
|
||||
this.isHttp = /^https?:/i.test(source.url);
|
||||
this.httpHeaders = (this.isHttp && source.httpHeaders) || {};
|
||||
this.headers = createHeaders(this.isHttp, source.httpHeaders);
|
||||
|
||||
this._fullRequestReader = null;
|
||||
this._rangeRequestReaders = [];
|
||||
|
@ -123,17 +112,13 @@ class PDFFetchStreamReader {
|
|||
this._abortController = new AbortController();
|
||||
this._isStreamingSupported = !source.disableStream;
|
||||
this._isRangeSupported = !source.disableRange;
|
||||
|
||||
this._headers = createHeaders(this._stream.httpHeaders);
|
||||
// Always create a copy of the headers.
|
||||
const headers = new Headers(stream.headers);
|
||||
|
||||
const url = source.url;
|
||||
fetch(
|
||||
url,
|
||||
createFetchOptions(
|
||||
this._headers,
|
||||
this._withCredentials,
|
||||
this._abortController
|
||||
)
|
||||
createFetchOptions(headers, this._withCredentials, this._abortController)
|
||||
)
|
||||
.then(response => {
|
||||
if (!validateResponseStatus(response.status)) {
|
||||
|
@ -147,7 +132,7 @@ class PDFFetchStreamReader {
|
|||
const { allowRangeRequests, suggestedLength } =
|
||||
validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp: this._stream.isHttp,
|
||||
isHttp: stream.isHttp,
|
||||
rangeChunkSize: this._rangeChunkSize,
|
||||
disableRange: this._disableRange,
|
||||
});
|
||||
|
@ -222,17 +207,14 @@ class PDFFetchStreamRangeReader {
|
|||
this._isStreamingSupported = !source.disableStream;
|
||||
|
||||
this._abortController = new AbortController();
|
||||
this._headers = createHeaders(this._stream.httpHeaders);
|
||||
this._headers.append("Range", `bytes=${begin}-${end - 1}`);
|
||||
// Always create a copy of the headers.
|
||||
const headers = new Headers(stream.headers);
|
||||
headers.append("Range", `bytes=${begin}-${end - 1}`);
|
||||
|
||||
const url = source.url;
|
||||
fetch(
|
||||
url,
|
||||
createFetchOptions(
|
||||
this._headers,
|
||||
this._withCredentials,
|
||||
this._abortController
|
||||
)
|
||||
createFetchOptions(headers, this._withCredentials, this._abortController)
|
||||
)
|
||||
.then(response => {
|
||||
if (!validateResponseStatus(response.status)) {
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import { assert, stringToBytes } from "../shared/util.js";
|
||||
import {
|
||||
createHeaders,
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
|
@ -38,11 +39,11 @@ function getArrayBuffer(xhr) {
|
|||
}
|
||||
|
||||
class NetworkManager {
|
||||
constructor(url, args = {}) {
|
||||
constructor({ url, httpHeaders, withCredentials }) {
|
||||
this.url = url;
|
||||
this.isHttp = /^https?:/i.test(url);
|
||||
this.httpHeaders = (this.isHttp && args.httpHeaders) || Object.create(null);
|
||||
this.withCredentials = args.withCredentials || false;
|
||||
this.headers = createHeaders(this.isHttp, httpHeaders);
|
||||
this.withCredentials = withCredentials || false;
|
||||
|
||||
this.currXhrId = 0;
|
||||
this.pendingRequests = Object.create(null);
|
||||
|
@ -70,12 +71,8 @@ class NetworkManager {
|
|||
|
||||
xhr.open("GET", this.url);
|
||||
xhr.withCredentials = this.withCredentials;
|
||||
for (const property in this.httpHeaders) {
|
||||
const value = this.httpHeaders[property];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
xhr.setRequestHeader(property, value);
|
||||
for (const [key, val] of this.headers) {
|
||||
xhr.setRequestHeader(key, val);
|
||||
}
|
||||
if (this.isHttp && "begin" in args && "end" in args) {
|
||||
xhr.setRequestHeader("Range", `bytes=${args.begin}-${args.end - 1}`);
|
||||
|
@ -194,10 +191,7 @@ class NetworkManager {
|
|||
class PDFNetworkStream {
|
||||
constructor(source) {
|
||||
this._source = source;
|
||||
this._manager = new NetworkManager(source.url, {
|
||||
httpHeaders: source.httpHeaders,
|
||||
withCredentials: source.withCredentials,
|
||||
});
|
||||
this._manager = new NetworkManager(source);
|
||||
this._rangeChunkSize = source.rangeChunkSize;
|
||||
this._fullRequestReader = null;
|
||||
this._rangeRequestReaders = [];
|
||||
|
|
|
@ -21,6 +21,21 @@ import {
|
|||
import { getFilenameFromContentDispositionHeader } from "./content_disposition.js";
|
||||
import { isPdfFile } from "./display_utils.js";
|
||||
|
||||
function createHeaders(isHttp, httpHeaders) {
|
||||
const headers = new Headers();
|
||||
|
||||
if (!isHttp || !httpHeaders || typeof httpHeaders !== "object") {
|
||||
return headers;
|
||||
}
|
||||
for (const key in httpHeaders) {
|
||||
const val = httpHeaders[key];
|
||||
if (val !== undefined) {
|
||||
headers.append(key, val);
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
function validateRangeRequestCapabilities({
|
||||
getResponseHeader,
|
||||
isHttp,
|
||||
|
@ -98,6 +113,7 @@ function validateResponseStatus(status) {
|
|||
}
|
||||
|
||||
export {
|
||||
createHeaders,
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
import { AbortException, assert, MissingPDFException } from "../shared/util.js";
|
||||
import {
|
||||
createHeaders,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
} from "./network_utils.js";
|
||||
|
@ -53,7 +54,7 @@ class PDFNodeStream {
|
|||
this.url.protocol === "http:" || this.url.protocol === "https:";
|
||||
// Check if url refers to filesystem.
|
||||
this.isFsUrl = this.url.protocol === "file:";
|
||||
this.httpHeaders = (this.isHttp && source.httpHeaders) || {};
|
||||
this.headers = createHeaders(this.isHttp, source.httpHeaders);
|
||||
|
||||
this._fullRequestReader = null;
|
||||
this._rangeRequestReaders = [];
|
||||
|
@ -291,6 +292,9 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
constructor(stream) {
|
||||
super(stream);
|
||||
|
||||
// Node.js requires the `headers` to be a regular Object.
|
||||
const headers = Object.fromEntries(stream.headers);
|
||||
|
||||
const handleResponse = response => {
|
||||
if (response.statusCode === 404) {
|
||||
const error = new MissingPDFException(`Missing PDF "${this._url}".`);
|
||||
|
@ -321,11 +325,7 @@ class PDFNodeStreamFullReader extends BaseFullReader {
|
|||
this._filename = extractFilenameFromHeader(getResponseHeader);
|
||||
};
|
||||
|
||||
this._request = createRequest(
|
||||
this._url,
|
||||
stream.httpHeaders,
|
||||
handleResponse
|
||||
);
|
||||
this._request = createRequest(this._url, headers, handleResponse);
|
||||
|
||||
this._request.on("error", reason => {
|
||||
this._storedError = reason;
|
||||
|
@ -342,15 +342,9 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|||
constructor(stream, start, end) {
|
||||
super(stream);
|
||||
|
||||
this._httpHeaders = {};
|
||||
for (const property in stream.httpHeaders) {
|
||||
const value = stream.httpHeaders[property];
|
||||
if (value === undefined) {
|
||||
continue;
|
||||
}
|
||||
this._httpHeaders[property] = value;
|
||||
}
|
||||
this._httpHeaders.Range = `bytes=${start}-${end - 1}`;
|
||||
// Node.js requires the `headers` to be a regular Object.
|
||||
const headers = Object.fromEntries(stream.headers);
|
||||
headers.Range = `bytes=${start}-${end - 1}`;
|
||||
|
||||
const handleResponse = response => {
|
||||
if (response.statusCode === 404) {
|
||||
|
@ -361,7 +355,7 @@ class PDFNodeStreamRangeReader extends BaseRangeReader {
|
|||
this._setReadableStream(response);
|
||||
};
|
||||
|
||||
this._request = createRequest(this._url, this._httpHeaders, handleResponse);
|
||||
this._request = createRequest(this._url, headers, handleResponse);
|
||||
|
||||
this._request.on("error", reason => {
|
||||
this._storedError = reason;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
*/
|
||||
|
||||
import {
|
||||
createHeaders,
|
||||
createResponseStatusError,
|
||||
extractFilenameFromHeader,
|
||||
validateRangeRequestCapabilities,
|
||||
|
@ -25,6 +26,44 @@ import {
|
|||
} from "../../src/shared/util.js";
|
||||
|
||||
describe("network_utils", function () {
|
||||
describe("createHeaders", function () {
|
||||
it("returns empty `Headers` for invalid input", function () {
|
||||
const headersArr = [
|
||||
createHeaders(
|
||||
/* isHttp = */ false,
|
||||
/* httpHeaders = */ { "Content-Length": 100 }
|
||||
),
|
||||
createHeaders(/* isHttp = */ true, /* httpHeaders = */ undefined),
|
||||
createHeaders(/* isHttp = */ true, /* httpHeaders = */ null),
|
||||
createHeaders(/* isHttp = */ true, /* httpHeaders = */ "abc"),
|
||||
createHeaders(/* isHttp = */ true, /* httpHeaders = */ 123),
|
||||
];
|
||||
const emptyObj = Object.create(null);
|
||||
|
||||
for (const headers of headersArr) {
|
||||
expect(Object.fromEntries(headers)).toEqual(emptyObj);
|
||||
}
|
||||
});
|
||||
|
||||
it("returns populated `Headers` for valid input", function () {
|
||||
const headers = createHeaders(
|
||||
/* isHttp = */ true,
|
||||
/* httpHeaders = */ {
|
||||
"Content-Length": 100,
|
||||
"Accept-Ranges": "bytes",
|
||||
"Dummy-null": null,
|
||||
"Dummy-undefined": undefined,
|
||||
}
|
||||
);
|
||||
|
||||
expect(Object.fromEntries(headers)).toEqual({
|
||||
"content-length": "100",
|
||||
"accept-ranges": "bytes",
|
||||
"dummy-null": "null",
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("validateRangeRequestCapabilities", function () {
|
||||
it("rejects invalid rangeChunkSize", function () {
|
||||
expect(function () {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue