httpao
Version:
Simple, lighweight http server module
106 lines (92 loc) • 3.03 kB
JavaScript
const dir = __dirname;
const {Socket} = require('net'),
InComing = require(`${dir}/incoming.js`),
Codes = require(`${dir}/codes.js`);
const validheader = (o) => {
if (typeof o != 'object') throw new TypeError('The headers type must be a object');
};
const validheadername = (k) => {
if (typeof k != 'string') throw new TypeError(`Header name must be a valid HTTP token ["${String(k)}"]`);
};
const validheadervalue = (k, v) => {
if (typeof v == 'undefined') throw new TypeError(`Invalid value "${String(v)}" for header "${k}"`);
}
const validstatuscode = (c) => {
if (typeof c != 'number' || c < 100 || c > 999) throw new Error(`Invalid status code: ${c}`);
};
const ksocket = Symbol('socket');
const kheadersSent = Symbol('headersSent');
const knoBody = Symbol('noBody');
const kheaders = Symbol('headers');
const kEnded = Symbol('Ended');
class OutGoing {
constructor (socket, req) {
if (!(socket instanceof Socket)) throw new TypeError('socket not a Socket instance');
if (!(req instanceof InComing)) throw new TypeError('req not a InComing instance');
this[ksocket] = socket;
this[kheadersSent] = false;
this[knoBody] = false;
this[kheaders] = {};
this[kEnded] = false;
}
write (d, e) {
if (!this[kheadersSent]) {
this._sendHeaders();
}
this[ksocket].write(d, e);
}
end (d, e) {
this.write(d, e);
this[ksocket].end();
this[kEnded] = true;
}
setHeader (k, v) {
if (this[kheadersSent]) throw new Error('Cannot set headers after they are sent to the client');
validheadername(k);
validheadervalue(k, v);
this[kheaders][k] = String(v);
}
setHeaders (o) {
validheaders(o);
Object.keys(o).forEach(k => {
this.setHeader(k, o[k]);
});
}
writeHead (c, m, h) {
validstatuscode(c);
this.statusCode = c;
if (m) {
if (typeof m == 'string') {
this.statusMessage = m;
} else if (typeof m == 'object') {
this.setHeaders(m);
return;
} else {
throw new TypeError('The status message type must be a string');
}
}
if (h) {
this.setHeaders(h);
}
this._sendHeaders();
}
_sendHeaders () {
this[kheadersSent] = true;
this.statusCode = this.statusCode || 200;
this.statusMessage = this.statusMessage ? this.statusMessage : (Codes[this.statusCode] ? Codes[this.statusCode] : this.statusCode);
this[ksocket].write(`HTTP/1.1 ${this.statusCode} ${this.statusMessage}\r\n`);
this[kheaders]['Date'] = new Date().toString();
this[kheaders]['X-Powered-By'] = 'HTTPAO';
Object.keys(this[kheaders]).forEach(k => {
this[ksocket].write(`${k}: ${this[kheaders][k]}\r\n`);
});
this[ksocket].write(`\r\n`);
}
get headersSent () {
return this[kheadersSent];
}
get Ended () {
return this[kEnded];
}
}
module.exports = OutGoing;