Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cabinjs/parse-request
Parse requests in the Browser and Node (with added support for multer and passport). Made for Cabin.
https://github.com/cabinjs/parse-request
arraybuffer buffer express javascript koa logger logging middleware multer node parse parser passport req request requests route stream utility
Last synced: 7 days ago
JSON representation
Parse requests in the Browser and Node (with added support for multer and passport). Made for Cabin.
- Host: GitHub
- URL: https://github.com/cabinjs/parse-request
- Owner: cabinjs
- License: mit
- Created: 2018-06-24T00:23:36.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-06-25T19:05:20.000Z (4 months ago)
- Last Synced: 2024-09-28T03:52:37.018Z (about 1 month ago)
- Topics: arraybuffer, buffer, express, javascript, koa, logger, logging, middleware, multer, node, parse, parser, passport, req, request, requests, route, stream, utility
- Language: JavaScript
- Homepage: https://cabinjs.com
- Size: 947 KB
- Stars: 9
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# parse-request
[![build status](https://github.com/cabinjs/parse-request/actions/workflows/ci.yml/badge.svg)](https://github.com/cabinjs/parse-request/actions/workflows/ci.yml)
[![code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![made with lass](https://img.shields.io/badge/made_with-lass-95CC28.svg)](https://lass.js.org)
[![license](https://img.shields.io/github/license/cabinjs/parse-request.svg)](LICENSE)> Parse requests in the Browser and Node (with added support for [multer][] and [passport][]). Made for [Cabin][].
## Table of Contents
* [Install](#install)
* [How does it work](#how-does-it-work)
* [Credit Card Masking](#credit-card-masking)
* [Sensitive Field Names Automatically Masked](#sensitive-field-names-automatically-masked)
* [Sensitive Header Names Automatically Masked](#sensitive-header-names-automatically-masked)
* [Usage](#usage)
* [VanillaJS](#vanillajs)
* [Koa](#koa)
* [Express](#express)
* [Contributors](#contributors)
* [License](#license)## Install
[npm][]:
```sh
npm install parse-request
```## How does it work
> **This package is used internally by Cabin's middleware, and we highly recommend you to simply use [Cabin][] instead of this package in particular.**
This package exports a function that accepts an Object `options` argument:
* `options` (Object) - a configuration object
* `req` (Object) - an Express/Connect request object (defaults to `false`) (you must either pass this option or `ctx` option, but not both)
* `ctx` (Object) - a Koa context object (defaults to `false`) (you must either pass this option or `req` option, but not both)
* `responseHeaders` (String or Object) - we highly recommend that you pass `res._headers` (see [Cabin][]'s middleware logic if you need an example of this)
* `userFields` (Array) - defaults to `[ 'id', 'email', 'full_name', 'ip_address' ]`, list of fields to cherry-pick from the user object parsed out of `req.user`
* `sanitizeFields` (Array) - defaults to the list of Strings provided under [Sensitive Field Names Automatically Masked](#sensitive-field-names-automatically-masked) below
* `sanitizeHeaders` (Array) - defaults to the list of Strings provided under [Sensitive Header Names Automatically Masked](#sensitive-header-names-automatically-masked) below (case insensitive)
* `maskCreditCards` (Boolean) - defaults to `true`, and specifies whether or not credit card numbers are masked
* `maskBuffers` (Boolean) - defaults to `true`, and will rewrite `Buffer`'s, `ArrayBuffer`'s, and `SharedArrayBuffer`'s recursively as an object of `{ type: , byteLength: }`. Note that this will save you on disk log storage size as logs will not output verbose stringified buffers – e.g. imagine a 10MB file image upload sent across the request body as a Buffer!)
* `maskStreams` (Boolean) - defauls to `true`, and will rewrite `Stream`'s to `{ type: 'Stream' }` (this is useful for those using multer v2.x (streams version), or those that have streams in `req.body`, `req.file`, or `req.files`)
* `checkId` (Boolean) - defaults to `true`, and prevents Strings that closely resemble primary key ID's from being masked (e.g. properties named `_id`, `id`, `ID`, `product_id`, `product-id`, `productId`, `productID`, and `product[id]` won't get masked or show as a false-positive for a credit card check)
* `checkCuid` (Boolean) - defaults to `true`, and prevents [cuid][] values from being masked
* `checkObjectId` (Boolean) - defaults to `true`, and prevents [MongoDB BSON ObjectId][bson-objectid] from being masked
* `checkUUID` (Boolean) - defaults to `true`, and prevents [uuid][] values from being masked
* `rfdc` (Object) - defaults to `{ proto: false, circles: false }` (you should not need to customize this, but if necessary refer to [rfdc][] documentation)
* `parseBody` (Boolean) - defaults to `true`, if you set to `false` we will not parse nor clone the request `body` property (this overrides all other parsing settings related)
* `parseQuery` (Boolean) - defaults to `true`, if you set to `false` we will not parse nor clone the request `query` property (this overrides all other parsing settings related)
* `parseFiles` (Boolean) - defaults to `true`, if you set to `false` we will not parse nor clone the request `file` nor `files` properties (this overrides all other parsing settings related)It automatically detects whether the request is from the Browser, Koa, or Express, and returns a parsed object with populated properties.
Here's an example object parsed:
```js
{
"id": "5d126d86160cea56950f80a9",
"timestamp": "2019-06-25T18:52:54.000Z",
"is_http": true,
"request": {
"method": "POST",
"query": {
"foo": "bar",
"beep": "boop"
},
"headers": {
"host": "127.0.0.1:59746",
"accept-encoding": "gzip, deflate",
"user-agent": "node-superagent/3.8.3",
"authorization": "Basic ********************",
"accept": "application/json",
"cookie": "foo=bar;beep=boop",
"content-type": "multipart/form-data; boundary=--------------------------104476455118209968089794",
"content-length": "1599",
"connection": "close"
},
"cookies": {
"foo": "bar",
"beep": "boop"
},
"url": "/?foo=bar&beep=boop",
"body": "{\"product_id\":\"5d0350ef2ca74d11ee6e4f00\",\"name\":\"nifty\",\"surname\":\"lettuce\",\"bank_account_number\":\"1234567890\",\"card\":{\"number\":\"****-****-****-****\"},\"stripe_token\":\"***************\",\"favorite_color\":\"green\"}",
"timestamp": "2019-06-25T18:52:54.589Z",
"id": "fbbce5d4-02d9-4a81-9a70-909631317e7d",
"http_version": "1.1",
"files": "{\"avatar\":[{\"fieldname\":\"avatar\",\"originalname\":\"avatar.png\",\"encoding\":\"7bit\",\"mimetype\":\"image/png\",\"buffer\":{\"type\":\"Buffer\",\"byteLength\":216},\"size\":216}],\"boop\":[{\"fieldname\":\"boop\",\"originalname\":\"boop-1.txt\",\"encoding\":\"7bit\",\"mimetype\":\"text/plain\",\"buffer\":{\"type\":\"Buffer\",\"byteLength\":7},\"size\":7},{\"fieldname\":\"boop\",\"originalname\":\"boop-2.txt\",\"encoding\":\"7bit\",\"mimetype\":\"text/plain\",\"buffer\":{\"type\":\"Buffer\",\"byteLength\":7},\"size\":7}]}"
},
"user": {
"ip_address": "::ffff:127.0.0.1"
},
"response": {
"headers": {
"x-powered-by": "Express",
"x-request-id": "fbbce5d4-02d9-4a81-9a70-909631317e7d",
"content-security-policy": "default-src 'none'",
"x-content-type-options": "nosniff",
"content-type": "text/html; charset=utf-8",
"content-length": "1213",
"x-response-time": "48.658ms",
"date": "Tue, 25 Jun 2019 18:52:54 GMT",
"connection": "close"
},
"http_version": "1.1",
"status_code": 200,
"reason_phrase": "OK",
"timestamp": "2019-06-25T18:52:54.000Z",
"duration": 48.658
},
"duration": 1.350323,
"app": {
"name": "parse-request",
"version": "1.0.11",
"node": "v10.15.3",
"hash": "f99bb8f28be5c6dc76bed76f6dd8984accc5c5fa",
"environment": "test",
"hostname": "users-MacBook-Pro.local",
"pid": 22165
}
}
```A few extra details about the above parsed properties:
* `id` (String) - is a newly created BSON ObjectId used to uniquely identify this log
* `timestamp` (String) - is the [ISO-8601][] date time string parsed from the `id` (thanks to MongoDB BSON `ObjectID.getTimestamp` method)
* `is_http` (Boolean) - defaults to `true` to indicate that this was a parsed HTTP request
* `duration` (Number) - is the number of milliseconds that `parseRequest` took to parse the request object (note that this uses `process.hrtime` which this package polyfills thanks to [browser-process-hrtime][])
* `user` (Object) - is parsed from the user object on `req.user` automatically (e.g. you are using [passport][]):
* `ip_address` (String) - IP address parsed
* `...` - additional fields are optionally parsed from `req.user`
* `request` (Object) - request object information parsed from `options.req`:
* `id` (String) - is conditionally added if `req.id` is a String (we highly recommend that you use [express-request-id][] in your project, which will automatically add this property if `X-Request-Id` if it is set, otherwise it will generate it as a new UUID)
* `file` (Object) - is conditionally added if you have a `req.file` property (e.g. if you're using [multer][])
* `files` (Array) - is conditionally added if you have a `req.files` property (e.g. if you're using [multer][])
* `http_version` (String) - is parsed from `req.httpVersion` or `req.httpVersionMajor` and `req.httpVersionMinor`
* `timesamp` (String) - is the [ISO-8601][] date time string parsed from when the request was received (we highly recommend that you use [request-received][] for this to be parsed as accurately as possible, although we do support a few widely-used fallback approaches)
* `headers` (Object) - the raw request headers (lowercased)
* `response` (Object) - response object information parsed from `options.responseHeaders` (we use [http-headers][] to parse this information):
* `http_version` (String) - is parsed from the response HTTP headers major and minor HTTP version
* `timestamp` (String) - is the [ISO-8601][] date time string parsed from the response's `Date` header
* `duration` (Number) - is the number of milliseconds parsed from the `X-Response-Time` HTTP header (we highly recommend that you use [response-time][] and [request-received][])
* `headers` (Object) - the raw response headers (lowercased)
* `status_code` (Number) - the response's status code (see RFC spec on [Status Code and Reason Phrase][rfc-spec])
* `reason_phrase` (String) - the response's reason phrase (see RFC spec on [Status Code and Reason Phrase][rfc-spec])Please see [Credit Card Masking](#credit-card-masking) and [Sensitive Field Names Automatically Masked](#sensitive-field-names-automatically-masked) below for more information about how `request.body`, `request.file`, and `request.files` are parsed and conditionally masked for security.
### Credit Card Masking
We also have built-in credit-card number detection and masking using the [credit-card-type][] library.
This means that credit card numbers (or fields that are very similar to a credit card) will be automatically masked. If you'd like to turn this off, pass `false` to `maskCreditCards`\*\*
### Sensitive Field Names Automatically Masked
See [sensitive-fields][] for the complete list.
### Sensitive Header Names Automatically Masked
The `Authorization` HTTP header has its `` portion automatically masked.
This means that if you are using BasicAuth or JSON Web Tokens ("JWT"), then your tokens will be hidden.
## Usage
We highly recommend to simply use [Cabin][] as this package is built-in!
### VanillaJS
The example below uses [xhook][] which is used to intercept HTTP requests made in the browser.
```html
(function() {
xhook.after(function(req, res) {
var req = parseRequest({ req });
console.log('req', req);
// ...
});
})();```
#### Required Browser Features
We recommend using (specifically with the bundle mentioned in [VanillaJS](#vanillajs) above):
```html
```
* performance.now() is not supported in op\_mini all
* WeakRef is not supported in Opera 91### Koa
```js
const parseRequest = require('parse-request');// ...
app.get('/', (ctx, next) => {
const req = parseRequest({ req: ctx });
console.log('req', req);
// ...
});
```### Express
```js
const parseRequest = require('parse-request');// ...
app.get('/', (req, res, next) => {
const req = parseRequest({ req });
console.log('req', req);
// ...
});
```#### If you override req.body and need to preserve original in logs
Sometimes developers overwrite `req.body` or `req.body` properties – therefore if you want to preserve the original request, you can add `req._originalBody = req.body` (or `ctx.request._originalBody = ctx.request.body` if you're using Koa) at the top of your route middleware (or as a global route middleware).
#### If you want to disable body parsing just for a specific route (e.g. prevent log output from showing the body)
If you're using Express:
```js
const disableBodyParsing = Symbol.for('parse-request.disableBodyParsing');// ...
app.get('/', (req, res, next) => {
req[disableBodyParsing] = true;
next();
});
```If you're using Koa:
```js
const disableBodyParsing = Symbol.for('parse-request.disableBodyParsing');// ...
app.get('/', (ctx, next) => {
ctx.req[disableBodyParsing] = true;
next();
});
```#### If you want to disable file parsing just for a specific route (e.g. prevent log output from showing the file(s))
If you're using Express:
```js
const disableFileParsing = Symbol.for('parse-request.disableFileParsing');// ...
app.get('/', (req, res, next) => {
req[disableFileParsing] = true;
next();
});
```If you're using Koa:
```js
const disableFileParsing = Symbol.for('parse-request.disableFileParsing');// ...
app.get('/', (ctx, next) => {
ctx.req[disableFileParsing] = true;
next();
});
```## Contributors
| Name | Website |
| -------------- | -------------------------- |
| **Nick Baugh** | |## License
[MIT](LICENSE) © [Nick Baugh](http://niftylettuce.com/)
##
[npm]: https://www.npmjs.com/
[passport]: http://www.passportjs.org/
[cabin]: https://cabinjs.com
[xhook]: https://github.com/jpillora/xhook
[credit-card-type]: https://github.com/braintree/credit-card-type
[sensitive-fields]: https://github.com/cabinjs/sensitive-fields
[cuid]: https://github.com/ericelliott/cuid
[bson-objectid]: https://docs.mongodb.com/manual/reference/method/ObjectId/
[uuid]: https://github.com/kelektiv/node-uuid#uuid-
[multer]: https://github.com/expressjs/multer
[rfdc]: https://github.com/davidmarkclements/rfdc
[request-received]: https://github.com/cabinjs/request-received
[express-request-id]: https://github.com/floatdrop/express-request-id
[browser-process-hrtime]: https://github.com/kumavis/browser-process-hrtime/
[iso-8601]: https://en.wikipedia.org/wiki/ISO_8601
[response-time]: https://github.com/expressjs/response-time
[http-headers]: https://github.com/watson/http-headers
[rfc-spec]: https://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6.1.1