nephele
Version:
Highly customizable and extensible WebDAV server for Node.js and Express.
217 lines (181 loc) • 5.11 kB
text/typescript
import { HTTPStatusMessages } from './HTTPStatusMessages.js';
export class PropStatStatus {
statusCode: number;
statusMessage: string;
body: { [k: string]: any } | undefined = undefined;
prop: { [k: string]: any } | undefined = undefined;
description: string | undefined = undefined;
constructor(statusCode: number, statusMessage?: string) {
this.statusCode = statusCode;
if (statusMessage) {
this.statusMessage = statusMessage;
} else if (statusCode in HTTPStatusMessages) {
this.statusMessage =
HTTPStatusMessages[statusCode as keyof typeof HTTPStatusMessages];
} else {
this.statusMessage = '';
}
}
toString() {
return `PropStatStatus: ${this.statusCode} ${this.statusMessage}${
this.description ? ` (${this.description})` : ''
}`;
}
/**
* Add an xml2js compatible body to the element.
*
* The object will be spread into the body of the element.
*
* Under normal circumstances, you shouldn't need to use this.
*
* @param body An xml2js compatible object.
*/
setBody(body: { [k: string]: any } | undefined) {
this.body = body;
}
/**
* Add an xml2js compatible body to the prop element.
*
* It should be a prop object, like this for successful props:
*
* {
* someprop: ['value'],
* otherprop: ['other value']
* }
*
* Or like this for error props (like forbidden):
*
* {
* someprop: {},
* otherprop: {}
* }
*
* @param prop An xml2js compatible object.
*/
setProp(prop: { [k: string]: any } | undefined) {
this.prop = prop;
}
render() {
let response: { [k: string]: any } = {
status: [`HTTP/1.1 ${this.statusCode} ${this.statusMessage}`],
};
if (this.description != null) {
response.responsedescription = [this.description];
}
if (this.prop) {
response.prop = this.prop;
}
if (this.body) {
response = { ...response, ...this.body };
}
return response;
}
}
export class Status {
element: string;
statusCode: number;
statusMessage: string;
body: { [k: string]: any } | undefined = undefined;
propStatStatuses: PropStatStatus[] = [];
description: string | undefined = undefined;
href: URL;
constructor(
href: URL,
statusCode: number,
statusMessage?: string,
element: string = 'response',
) {
this.href = href;
this.statusCode = statusCode;
this.element = element;
if (statusMessage) {
this.statusMessage = statusMessage;
} else if (statusCode in HTTPStatusMessages) {
this.statusMessage =
HTTPStatusMessages[statusCode as keyof typeof HTTPStatusMessages];
} else {
this.statusMessage = '';
}
}
toString() {
return `Status: ${this.statusCode} ${this.statusMessage}${
this.description ? ` (${this.description})` : ''
}`;
}
setDescription(description: string | undefined) {
this.description = description;
}
/**
* Add an xml2js compatible body to the element.
*
* The object will be spread into the body of the element.
*
* @param body An xml2js compatible object.
*/
setBody(body: { [k: string]: any } | undefined) {
// TODO: Should I use these checks?
// if (this.propStatStatuses.length) {
// throw new Error("Can't add body to a Status with PropStatStatuses.");
// }
this.body = body;
}
addPropStatStatus(propStatStatus: PropStatStatus) {
// if (this.body != null) {
// throw new Error("Can't add PropStatStatus to a Status with a body.");
// }
this.propStatStatuses.push(propStatStatus);
}
render() {
let response: { [k: string]: any } = {
href: { _: this.href.toString() },
};
if (this.description != null) {
response.responsedescription = [this.description];
}
if (this.propStatStatuses.length > 0) {
// propstat includes the response codes within the propstat object.
response.propstat = [];
for (let propStatStatus of this.propStatStatuses) {
response.propstat.push(propStatStatus.render());
}
} else {
// Build a response object.
response.status = [`HTTP/1.1 ${this.statusCode} ${this.statusMessage}`];
}
if (this.body) {
response = { ...response, ...this.body };
}
return response;
}
}
export class MultiStatus {
statuses: Status[] = [];
description: string | undefined = undefined;
addStatus(status: Status) {
this.statuses.push(status);
}
setDescription(description: string | undefined) {
this.description = description;
}
render() {
const responses: any[] = [];
const xml: any = {
multistatus: {
$: {
xmlns: 'DAV:',
},
},
};
if (this.description != null) {
xml.responsedescription = [this.description];
}
if (this.statuses.length < 1) {
return xml;
}
xml.multistatus.response = responses;
for (let status of this.statuses) {
responses.push(status.render());
}
return xml;
}
}