//
// SPDX-License-Identifier: AGPL-3.0
+import { customEncodeURI } from "./url";
+
export class WebDAV {
- static create(config?: Partial<WebDAVDefaults>, createRequest?: () => XMLHttpRequest) {
- return new WebDAV(config, createRequest);
- }
defaults: WebDAVDefaults = {
- baseUrl: '',
+ baseURL: '',
headers: {},
};
- propfind = (url: string, config: PropfindConfig = {}) =>
+ constructor(config?: Partial<WebDAVDefaults>, private createRequest = () => new XMLHttpRequest()) {
+ if (config) {
+ this.defaults = { ...this.defaults, ...config };
+ }
+ }
+
+ propfind = (url: string, config: WebDAVRequestConfig = {}) =>
this.request({
...config, url,
method: 'PROPFIND'
})
- put = (url: string, config: PutConfig = {}) =>
+ put = (url: string, data?: any, config: WebDAVRequestConfig = {}) =>
this.request({
...config, url,
- method: 'PUT'
+ method: 'PUT',
+ data
})
- copy = (url: string, { destination, ...config }: CopyConfig) =>
+ upload = (url: string, files: File[], config: WebDAVRequestConfig = {}) => {
+ return Promise.all(
+ files.map(file => this.request({
+ ...config, url,
+ method: 'PUT',
+ data: file
+ }))
+ );
+ }
+
+ copy = (url: string, destination: string, config: WebDAVRequestConfig = {}) =>
this.request({
...config, url,
method: 'COPY',
- headers: { ...config.headers, Destination: this.defaults.baseUrl + destination }
+ headers: {
+ ...config.headers,
+ Destination: this.defaults.baseURL
+ ? this.defaults.baseURL.replace(/\/+$/, '') + '/' + destination.replace(/^\/+/, '')
+ : destination
+ }
})
- move = (url: string, { destination, ...config }: MoveConfig) =>
+ move = (url: string, destination: string, config: WebDAVRequestConfig = {}) =>
this.request({
...config, url,
method: 'MOVE',
- headers: { ...config.headers, Destination: this.defaults.baseUrl + destination }
+ headers: {
+ ...config.headers,
+ Destination: this.defaults.baseURL
+ ? this.defaults.baseURL.replace(/\/+$/, '') + '/' + destination.replace(/^\/+/, '')
+ : destination
+ }
})
- delete = (url: string, config: DeleteConfig = {}) =>
+ delete = (url: string, config: WebDAVRequestConfig = {}) =>
this.request({
...config, url,
method: 'DELETE'
})
- private constructor(config?: Partial<WebDAVDefaults>, private createRequest = () => new XMLHttpRequest()) {
- if (config) {
- this.defaults = { ...this.defaults, ...config };
- }
- }
-
private request = (config: RequestConfig) => {
return new Promise<XMLHttpRequest>((resolve, reject) => {
const r = this.createRequest();
- r.open(config.method, this.defaults.baseUrl + config.url);
+ this.defaults.baseURL = this.defaults.baseURL.replace(/\/+$/, '');
+ r.open(config.method,
+ `${this.defaults.baseURL
+ ? this.defaults.baseURL+'/'
+ : ''}${customEncodeURI(config.url)}`);
const headers = { ...this.defaults.headers, ...config.headers };
Object
.keys(headers)
.forEach(key => r.setRequestHeader(key, headers[key]));
- if (config.onProgress) {
- r.addEventListener('progress', config.onProgress);
+ if (!(window as any).cancelTokens) {
+ Object.assign(window, { cancelTokens: {} });
}
- r.addEventListener('load', () => resolve(r));
- r.addEventListener('error', () => reject(r));
+ (window as any).cancelTokens[config.url] = () => {
+ resolve(r);
+ r.abort();
+ }
- r.send(config.data);
- });
+ if (config.onUploadProgress) {
+ r.upload.addEventListener('progress', config.onUploadProgress);
+ }
- }
-}
+ // This event gets triggered on *any* server response
+ r.addEventListener('load', () => {
+ if (r.status >= 400) {
+ return reject(r);
+ } else {
+ return resolve(r);
+ }
+ });
-export interface PropfindConfig extends BaseConfig { }
+ // This event gets triggered on network errors
+ r.addEventListener('error', () => {
+ return reject(r);
+ });
-export interface PutConfig extends BaseConfig {
- data?: any;
- onProgress?: (event: ProgressEvent) => void;
-}
+ r.upload.addEventListener('error', () => {
+ return reject(r);
+ });
-export interface CopyConfig extends BaseConfig {
- destination: string;
-}
-
-export interface MoveConfig extends BaseConfig {
- destination: string;
+ r.send(config.data);
+ });
+ }
}
-export interface DeleteConfig extends BaseConfig { }
-
-interface BaseConfig {
+export interface WebDAVRequestConfig {
headers?: {
[key: string]: string;
};
+ onUploadProgress?: (event: ProgressEvent) => void;
}
interface WebDAVDefaults {
- baseUrl: string;
+ baseURL: string;
headers: { [key: string]: string };
}
url: string;
headers?: { [key: string]: string };
data?: any;
- onProgress?: (event: ProgressEvent) => void;
-}
+ onUploadProgress?: (event: ProgressEvent) => void;
+}
\ No newline at end of file