75 lines
2.5 KiB
JavaScript
75 lines
2.5 KiB
JavaScript
import Stream from "stream";
|
|
import { joinURL } from "../tools/url.js";
|
|
import { encodePath } from "../tools/path.js";
|
|
import { request, prepareRequestOptions } from "../request.js";
|
|
import { handleResponseCode } from "../response.js";
|
|
const NOOP = () => { };
|
|
export function createReadStream(context, filePath, options = {}) {
|
|
const PassThroughStream = Stream.PassThrough;
|
|
const outStream = new PassThroughStream();
|
|
getFileStream(context, filePath, options)
|
|
.then(stream => {
|
|
stream.pipe(outStream);
|
|
})
|
|
.catch(err => {
|
|
outStream.emit("error", err);
|
|
});
|
|
return outStream;
|
|
}
|
|
export function createWriteStream(context, filePath, options = {}, callback = NOOP) {
|
|
const PassThroughStream = Stream.PassThrough;
|
|
const writeStream = new PassThroughStream();
|
|
const headers = {};
|
|
if (options.overwrite === false) {
|
|
headers["If-None-Match"] = "*";
|
|
}
|
|
const requestOptions = prepareRequestOptions({
|
|
url: joinURL(context.remoteURL, encodePath(filePath)),
|
|
method: "PUT",
|
|
headers,
|
|
data: writeStream,
|
|
maxRedirects: 0
|
|
}, context, options);
|
|
request(requestOptions, context)
|
|
.then(response => handleResponseCode(context, response))
|
|
.then(response => {
|
|
// Fire callback asynchronously to avoid errors
|
|
setTimeout(() => {
|
|
callback(response);
|
|
}, 0);
|
|
})
|
|
.catch(err => {
|
|
writeStream.emit("error", err);
|
|
});
|
|
return writeStream;
|
|
}
|
|
async function getFileStream(context, filePath, options = {}) {
|
|
const headers = {};
|
|
if (typeof options.range === "object" && typeof options.range.start === "number") {
|
|
let rangeHeader = `bytes=${options.range.start}-`;
|
|
if (typeof options.range.end === "number") {
|
|
rangeHeader = `${rangeHeader}${options.range.end}`;
|
|
}
|
|
headers.Range = rangeHeader;
|
|
}
|
|
const requestOptions = prepareRequestOptions({
|
|
url: joinURL(context.remoteURL, encodePath(filePath)),
|
|
method: "GET",
|
|
headers
|
|
}, context, options);
|
|
const response = await request(requestOptions, context);
|
|
handleResponseCode(context, response);
|
|
if (headers.Range && response.status !== 206) {
|
|
const responseError = new Error(`Invalid response code for partial request: ${response.status}`);
|
|
responseError.status = response.status;
|
|
throw responseError;
|
|
}
|
|
if (options.callback) {
|
|
setTimeout(() => {
|
|
options.callback(response);
|
|
}, 0);
|
|
}
|
|
// @ts-ignore
|
|
return response.body;
|
|
}
|