README
Enhance-req-res
A tool to enhance abilities of the req
and res
.
This module adds additional properties and methods to the corresponding req
and res
objects in a http server, and enhance abilities of the program.
This module has both express
style and koa
style, but only keeps very few
and useful methods. It is compatible to most well-known connect
and express
middleware, so you can use them instead.
This module also works with https
and http2
.
Install
npm install enhance-req-res
Example
const http = require("http");
const enhance = require("enhance-req-res");
http.createServer((_req, _res) => {
let { req, res } = enhance({
domain: "localhost"
})(_req, _res);
console.log(req.urlObj);
console.log(req.ip);
res.headers["x-powered-by"] = "Ayonium";
res.lastModified = new Date(1970);
res.cookies.user = req.auth ? req.auth.username : "anonymous";
res.send(["Hello", "World"]);
console.log("Cost time: %d ms", Date.now() - req.time);
}).listen(80);
API
options?: {[x: string]: string}
): (req, res) => { req: Request, res: Response }
enhance(Valid options
include:
domain
Set a domain name (or multiple ones in an array) for the program to find out the subdomain.useProxy
Iftrue
, when access properties likereq.ip
andreq.host
, will firstly try to get info from proxy, default:false
.capitalize
Auto-capitalize response headers when setting, default:true
.cookieSecret
A secret key to sign/unsign cookie values.jsonp
Set a query name for jsonp callback if needed. Iftrue
is set, then the query name will bejsonp
. In the query string, using the stylejsonp=callback
to request jsonp response.
Request
Request
The Request
interface extends IncomingMessage
/Http2ServerRequest
with
more properties and methods.
Some of these properties are read-only for security reasons, that means you won't be able to modified them.
stream
TheHttp2Stream
object backing the request (only for http2).urlObj
An object parsed by url6 module that contains URL information. Be aware ofurlObj.auth
, which is actually sent by httpBasic Authendication
.time
Request time, not really connection time, but the moment this module performs actions.proxy
If the client requested via a proxy server, this property will be set, otherwise it'snull
. If available, it may contain these properties:protocol
The client's real request protocol (x-forwarded-proto
).host
The real host that client trying to request (x-forwarded-host
).ip
The real IP of client (ips[0]
).ips
An array carries all IP addresses, includes client IP and proxy server IPs (x-forwarded-for
).
auth
Authentication of the client, it could benull
, or an object carries{ username, password }
.protocol
Eitherhttp
orhttps
, ifuseProxy
is true, then trying to useproxy
'sprotocol
first.secure
Ifprotocol
ishttps
, thentrue
, otherwisefalse
.host
The requested host address (includinghostname
andport
), ifuseProxy
is true, then try to useproxy
'shost
first.hostname
The requested host name (withoutport
).port
The requested port.domainName
The request domain name.subdomain
Unlike express or koa'ssubdomains
, this property is calculated by setting thedomain
option.path
Full requested path (withsearch
).pathname
Directory part of requested path (withoutsearch
).search
The requested URLsearch
string, with a leading?
.query
Parsed URL query object.href
Full requested URL string (withouthash
, which is not sent by the client).referer
Equivalent toheaders.referer
.origin
Reference toheaders.origin
orurlObj.origin
.type
TheContent-Type
of requested body (withoutcharset
).charset
The requested body'scharset
, or the first accepted charset (charsets[0]
), assume they both use a same charset. Unlike other properties, If you set this one to a valid charset, it will be used to decode request body.charsets
An array carries allAccept-Charset
s, ordered byq
ualities.length
TheContent-Length
of requested body.xhr
Whether the request fires withX-Requested-With: XMLHttpRequest
.cookies
An object carries all parsed cookies sent by the client.ip
The real client IP, ifuseProxy
istrue
, then trying to useproxy
'sip
first.ips
An array carries all IP addresses, includes client IP and proxy server IPs. Unlikeproxy.ips
, which may beundefined
, while this will always be available.accept
The first accepted response content type (accepts[0]
).accepts
An array carries allAccept
s types, ordered byq
ualities.lang
The first accepted response language (accepts[0]
).langs
An array carries allAccept-Language
s, ordered byq
ualities.encoding
The first accepted response encoding (encodings[0]
).encodings
An array carries allAccept-Encoding
s, ordered by sequence.cache
Cache-Control
sent by the client, it could benull
(no-cache
), anumber
of seconds (max-age
), or a string likeprivate
,public
, etc.keepAlive
Whether the request fires withConnection: keep-alive
.get(field)
Gets a request header field's (case insensitive) value.is(...types)
Checks if the requestContent-Type
matches the given types, available of using short-hand words, likehtml
indicatestext/html
. If pass, returns the first matched type.
console.log(req.urlObj);
console.log(req.ip);
console.log(req.host);
console.log(req.subdomain);
console.log(req.query);
console.log(req.lang);
// ...
Response
The Response
interface extends ServerResponse
/Http2ServerResponse
with
more properties and methods.
Most of its properties are setters/getters, if you assign a new value to them, that will actually mean something.
- The streamHttp2Stream
object backing the response (only for http2)
This property is read-only.
res.stream.push("some thing");
- Sets/Gets status code. code
res.code = 200;
console.log(res.code); // => 200
- Sets/Gets status message. message
res.message = "OK";
console.log(res.message); // => OK
- Sets/Gets both status code and message. status
res.status = 200;
console.log(res.status); // => 200 OK
res.status = "200 Everything works fine.";
console.log(res.status); // => 200 Everything works fine.
console.log(res.code); // => 200
console.log(res.message); // => Everything works fine.
- Sets/Gets typeContent-Type
without charset
part.
res.type = "text/html";
res.type = "html"; // Will auto lookup to text/html.
console.log(res.type); // => text/html
- Sets/Gets charsetContent-Type
only with charset
part.
res.charset = "UTF-8";
console.log(res.charset); // => UTF-8
Sets/Gets lengthContent-Length
.
res.length = 12;
console.log(res.length); // => 12
Sets/Gets encodingContent-Encoding
.
res.encoding = "gzip";
console.log(res.encoding); // => gzip
- Sets/Gets dateDate
.
res.date = new Date(); // You can set a date string or Date instance.
console.log(res.date); // => Fri, 15 Dec 2017 04:13:17 GMT
Sets/Gets - etagEtag
.
This properties is internally used when calling res.send()
, if you don't use
res.send()
, you can call it manually.
const etag = require("etag");
var body = "Hello, World!";
res.etag = etag(body);
console.log(res.etag); // => d-CgqfKmdylCVXq1NV12r0Qvj2XgE
- Sets/Gets lastModifiedLast-Modified
.
res.lastModified = new Date(2017); // You can set a date string or Date instance.
console.log(res.lastModified); // => Thu, 01 Jan 1970 00:00:02 GMT
- Sets/Gets locationLocation
.
res.location = "/login";
console.log(res.location); // => /login
- Sets/Gets refreshRefresh
in a number of seconds.
res.refresh = 3; // The page will auto-refresh in 3 seconds.
res.refresh = "3; URL=/logout"; // Auto-redirect to /logout in 3 seconds.
console.log(res.refresh); // => 3; URL=/logout
- Sets/Gets attachmentContent-Disposition
with a filename.
res.attachment = "example.txt";
console.log(res.attchment); // => attachment; filename="example.txt"
- Sets/Gets cahceCache-Control
.
res.cache = null; // no-cache
res.cache = 0; // max-age=0
res.cache = 3600; // max-age=3600
res.cache = "private";
console.log(res.cache); // private
- Sets/Gets varyVary
.
res.vary = "Content-Type";
res.vary = ["Content-Type", "Content-Length"]; // Set multiple fields.
console.log(res.vary); // => [Content-Type, Content-Length]
- Sets/Gets keepAliveConnection
.
res.keepAlive = true; // Connection: keep-alive
console.log(res.keepAlive); // => true
- Whether the response has been modified. modified
This property is read-only, and only works after res.atag
and
res.lastModified
are set (whether explicitly or implicitly).
res.send("Hello, World!");
if (res.modified) {
console.log("A new response has been sent to the client.");
} else {
console.log("A '304 Not Modified' response has been sent to the client");
}
- Sets/Gets response headers. headers
This property is a Proxy
instance, you can only manipulate its properties to
set headers.
res.headers["x-powered-by"] = "Node.js/8.9.3";
console.log(res.headers); // => { "x-powered-by": "Node.js/8.9.3" }
// If you want to delete a heder, just call:
delete res.headers["x-powered-by"];
- Sets/Gets response cookies. cookies
This property is a Proxy instance, you can only manipulate its properties to set cookies.
res.cookies.username = "Luna";
res.cookies.username = "Luna; Max-Age=3600"; // Set both value and max-age
// Another way to set a cookie is using the Cookie class:
const { Cookie } = require("webium");
res.cookies.username = new Cookie({ value: "Luna", maxAge: 3600 });
console.log(res.cookies); // => { username: "Luna" }
// If you want to delete a cookie, just call:
delete res.cookies.username;
// Or this may be more convinient if you just wnat it to expire:
res.cookies.username = null;
- Gets a response header field's value. get(field)
var type = res.get("Content-Type");
// equivalent to
var type = req.headers["content-type"];
- Sets a response header field's value. set(field, value)
res.set("Content-Type", "text/html");
// equivalent to:
res.headers["content-type"] = "text/html";
- Appends a value to a response header field. append(field, value)
res.append("Set-Cookie", "username=Luna");
res.append("Set-Cookie", "email=luna@example.com");
// equivalent to:
res.set("Set-Cookie", ["username=Luna", "email=luna@example.com"]);
- Removes a response header field. remove(field)
res.remove("Set-Cookie");
// equivalent to:
delete res.headers["set-cookie"];
- Gets a response cookie. cookie(name)
var name = res.cookie("username");
// equivalent to:
var name = res.cookies.username;
- Sets a response cookie. cookie(name, value, options?: object)
res.cookie("username", "Luna");
// equivalent to:
res.cookies.username = "Luna";
// you can set additinal options:
res.cookie("username", "Luna", { maxAge: 3600 });
// equivalent to:
res.cookies.username = new Cookie({ value: "Luna" , maxAge: 3600 });
Be aware, you cannot set value as Luna; Max-Age=3600
with res.cookie()
, it
will always be treated as cookie value.
- Makes an HTTP basic authentication. auth()
if(!req.auth){ // Require authendication if haven't.
res.auth();
}else{
// ...
}
- Clears authentication. unauth()
Since browsers clear authentication while respond 401 Unauthorized
, so
this method is exactly the same as res.auth()
, only more readable.
- Redirects the request to a specified URL. redirect(url, code?: 301 | 302)
res.redirect("/login"); // code is 302 by default.
// If you want to go back to the previous page, just pass url -1.
res.redirect(-1);
- Sends contents to the client. send(data)
This method will automatically perform type checking, If data
is a buffer,
the res.type
will be set to application/octet-stream
; if data
is an
object (or array), res.type
will be set to application/json
; if data
is
a string, the program will detect if it's text/plain
, text/html
,
application/xml
, or application/json
.
This method also check if a response body has been modified since the last
time, if res.modified
is false
, a 304 Not Modified
with no body will be
sent.
res.send("Hello, World!"); // text/plain
res.send("<p>Hello, World!</p>"); // text/html
res.send("<Text>Hello, World!</Text>"); // application/xml
res.send(`["Hello", "World!"]`); // application/json
res.send(["Hello", "World!"]); // application/json
res.send(Buffer.from("Hello, World!")); // application/octet-stream
This method could send jsonp response as well, if res.jsonp
is set, or
options.jsonp
for the application is set and the query matches, a jsonp
response will be sent, and the res.type
will be set to
application/javascript
.
res.jsonp = "callback";
res.send(["Hello", "World!"]); // will result as callback(["Hello", "World!"])
- Sends a file as response body. sendFile(filename, cb?: (err)=>void)
This method also performs type checking.
res.sendFile("example.txt");
// if you provide a callback function, then it will be called after the
// response has been sent, or failed.
res.sendFile("example.txt", (err)=>{
console.log(err ? `Fail due to: ${err.message}`: "Success!");
});
Performs a file download function. download(filename, newName?: string)
This method uses res.sendFile()
to transfer the file, but instead of
displaying on the page, the browser will download it to disk.
res.download("example.txt");
// You can set a new name if the original one is inconvenient.
res.download("1a79a4d60de6718e8e5b326e338ae533.txt", "example.txt");
Other forms:
download(filename, cb:? (err)=>void)
download(filename, newName, cb:? (err)=>void)
The callback function, will be called after the response has been sent, or failed.
Other than downloading a real file, you can perform downloading a string as a
text file by using res.attachment
and res.send()
.
// This content will be downloaded using the name 'example.html':
res.attachment = "example.html";
res.send("<p>Hello, World!</p>");
Worth mentioned, if you use res.send()
to send a buffer, most browsers will
download the buffer as a file, so it's always better to set res.attachment
when you are sending buffers.