@versatiles/google-cloud
Version:
A server for VersaTiles in Google Cloud Run
117 lines (116 loc) • 4.17 kB
JavaScript
import { ENCODINGS, acceptEncoding, findBestEncoding } from './encoding.js';
import { recompress } from './recompress.js';
import { ResponseHeaders } from './response_headers.js';
var ResponderState;
(function (ResponderState) {
ResponderState[ResponderState["Initialised"] = 0] = "Initialised";
ResponderState[ResponderState["HeaderSend"] = 1] = "HeaderSend";
ResponderState[ResponderState["Finished"] = 2] = "Finished";
})(ResponderState || (ResponderState = {}));
/**
* Class defining the structure and methods of a Responder.
*/
export class Responder {
#options;
#responderState;
#time;
#responseHeaders;
constructor(options) {
this.#time = Date.now();
this.#options = options;
this.#responderState = ResponderState.Initialised;
this.#responseHeaders = new ResponseHeaders();
}
get fastRecompression() {
return this.#options.fastRecompression;
}
get headers() {
return this.#responseHeaders;
}
get verbose() {
return this.#options.verbose;
}
get requestNo() {
return this.#options.requestNo;
}
async respond(content, contentMIME, contentEncoding) {
this.headers.set('content-type', contentMIME);
ENCODINGS[contentEncoding].setEncodingHeader(this.#responseHeaders);
if (typeof content === 'string')
content = Buffer.from(content);
this.log('respond');
await recompress(this, content);
}
error(code, message) {
this.log(`error ${code}: ${message}`);
this.#options.response
.writeHead(code, { 'content-type': 'text/plain' })
.end(message);
}
write(buffer, callback) {
if (this.#responderState < ResponderState.HeaderSend)
throw Error('Headers not send yet');
this.#options.response.write(buffer, error => {
if (error)
throw Error();
callback();
});
}
end(bufferOrCallback, maybeCallback) {
if (this.#responderState < ResponderState.HeaderSend)
throw Error('Headers not send yet');
if (this.#responderState >= ResponderState.Finished)
throw Error('already ended');
if (Buffer.isBuffer(bufferOrCallback)) {
const buffer = bufferOrCallback;
const callback = maybeCallback;
if (callback !== undefined) {
this.#options.response.end(buffer, () => {
this.#responderState = ResponderState.Finished;
callback();
});
}
else {
return new Promise(resolve => this.#options.response.end(buffer, () => {
this.#responderState = ResponderState.Finished;
resolve();
}));
}
}
else {
const callback = bufferOrCallback;
if (callback !== undefined) {
this.#options.response.end(() => {
this.#responderState = ResponderState.Finished;
callback();
});
}
else {
return new Promise(resolve => this.#options.response.end(() => {
this.#responderState = ResponderState.Finished;
resolve();
}));
}
}
}
sendHeaders(status) {
if (this.#responderState >= ResponderState.HeaderSend)
throw Error('Headers already send');
const headers = this.#responseHeaders.getHeaders();
this.#responseHeaders.lock();
this.#options.response.writeHead(status, headers);
this.#responderState = ResponderState.HeaderSend;
}
acceptEncoding(encoding) {
return acceptEncoding(this.#options.requestHeaders, encoding);
}
findBestEncoding() {
return findBestEncoding(this.#options.requestHeaders);
}
log(message) {
if (!this.#options.verbose)
return;
const time = Date.now() - this.#time;
console.log(` #${this.#options.requestNo} (${time}ms) ${message}`);
}
}