@inweb/client
Version:
JavaScript REST API client for the Open Cloud Server
172 lines (155 loc) • 5.79 kB
text/typescript
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2002-2026, Open Design Alliance (the "Alliance").
// All rights reserved.
//
// This software and its documentation and related materials are owned by
// the Alliance. The software may only be incorporated into application
// programs owned by members of the Alliance, subject to a signed
// Membership Agreement and Supplemental Software License Agreement with the
// Alliance. The structure and organization of this software are the valuable
// trade secrets of the Alliance and its suppliers. The software is also
// protected by copyright law and international treaty provisions. Application
// programs incorporating this software must include the following statement
// with their copyright notices:
//
// This application incorporates Open Design Alliance software pursuant to a
// license agreement with Open Design Alliance.
// Open Design Alliance Copyright (C) 2002-2026 by Open Design Alliance.
// All rights reserved.
//
// By use of this software, its documentation or related materials, you
// acknowledge and accept the above terms.
///////////////////////////////////////////////////////////////////////////////
import { IHttpClient } from "./IHttpClient";
import { $fetch } from "./Fetch";
import { $xmlhttp } from "./XMLHttp";
export class HttpClient implements IHttpClient {
public serverUrl: string;
public headers: HeadersInit = {};
public signInUserId = "";
public signInUserIsAdmin = false;
constructor(serverUrl: string) {
this.serverUrl = serverUrl;
}
get(relativePath: string, init: RequestInit = {}): Promise<Response> {
return $fetch(`${this.serverUrl}${relativePath}`, {
...init,
method: "GET",
headers: { ...this.headers, ...init.headers },
});
}
post(relativePath: string, body?: BodyInit | object, init: RequestInit = {}): Promise<Response> {
return $fetch(`${this.serverUrl}${relativePath}`, {
...init,
method: "POST",
headers: { ...this.headers, ...init.headers },
body,
});
}
put(relativePath: string, body?: BodyInit | object, init: RequestInit = {}): Promise<Response> {
return $fetch(`${this.serverUrl}${relativePath}`, {
...init,
method: "PUT",
headers: { ...this.headers, ...init.headers },
body,
});
}
delete(relativePath: string, init: RequestInit = {}): Promise<Response> {
return $fetch(`${this.serverUrl}${relativePath}`, {
...init,
method: "DELETE",
headers: { ...this.headers, ...init.headers },
});
}
uploadFile(
relativePath: string,
file: File,
onProgress?: (progress: number) => void,
init: RequestInit = {}
): Promise<XMLHttpRequest> {
const data = new FormData();
data.append("file", file);
return $xmlhttp(`${this.serverUrl}${relativePath}`, {
method: "POST",
headers: { ...this.headers, ...init.headers },
body: data,
uploadProgress: onProgress,
});
}
async downloadFile(
relativePath: string,
onProgress?: (progress: number, chunk: Uint8Array) => void,
init: RequestInit = {}
): Promise<Response> {
const response = await this.get(relativePath, init);
if (!onProgress) return response;
const contentLength = response.headers.get("Content-Length");
const total = parseInt(contentLength || "", 10) || 1;
const stream = new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
let loaded = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
controller.enqueue(value);
loaded += value.length;
onProgress(loaded / total, value);
}
controller.close();
},
});
return new Response(stream);
}
async downloadFileRange(
relativePath: string,
reserved: number | string,
ranges: Array<{ begin: number; end: number; requestId: number }>,
onProgress?: (progress: number, chunk: Uint8Array, requestId: number) => void,
init: RequestInit = {}
): Promise<Response> {
const headers = {
...init.headers,
Range: "bytes=" + ranges.map((x) => `${x.begin}-${x.end}`).join(","),
};
const response = await this.get(relativePath, { ...init, headers });
if (!onProgress) return response;
const contentLength = response.headers.get("content-length");
const total = parseInt(contentLength || "", 10) || 1;
const stream = new ReadableStream({
async start(controller) {
const reader = response.body.getReader();
let loaded = 0;
let rangedIndex = 0;
let rangePos = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
controller.enqueue(value);
loaded += value.length;
let chunkLeft = value.length;
let chunkPos = 0;
while (chunkLeft > 0) {
const range = ranges[rangedIndex];
const rangeLeft = range.end - range.begin + 1 - rangePos;
if (chunkLeft < rangeLeft) {
const chunk = value.subarray(chunkPos, chunkPos + chunkLeft);
onProgress(loaded / total, chunk, range.requestId);
rangePos += chunkLeft;
chunkLeft = 0;
} else {
const chunk = value.subarray(chunkPos, chunkPos + rangeLeft);
onProgress(loaded / total, chunk, range.requestId);
chunkPos += rangeLeft;
chunkLeft -= rangeLeft;
rangedIndex++;
rangePos = 0;
}
}
}
controller.close();
},
});
return new Response(stream);
}
}