1.0.0 • Published 10 months ago

koa-lbsp v1.0.0

Weekly downloads
-
License
ISC
Repository
-
Last release
10 months ago

koa-lbsp

CI KoaJs Slack


A full-featured koa lbsp parser middleware. Supports multipart, urlencoded, and json request bodies. Provides the same functionality as Express's lbspParser - multer.

Install

Install with npm

npm install koa-lbsp

Features

  • can handle requests such as:
    • multipart/form-data
    • application/x-www-form-urlencoded
    • application/json
    • application/json-patch+json
    • application/vnd.api+json
    • application/csp-report
    • text/xml
  • option for patch to Koa or Node, or either
  • file uploads
  • lbsp, fields and files size limiting

Hello World - Quickstart

npm install koa koa-lbsp # Note that Koa requires Node.js 7.6.0+ for async/await support

app.js:

const Koa = require('koa')
const app = new Koa()
const router = require('./app/router/router')
const { koaBody } = require('koa-body')
const path = require('path')
const static = require('koa-static')
const { errorHandler } = require('koa-error-handler2');
const logger = require('koa-logger2');
const cors=require('koa-cors')
app.use(cors())
app.use(errorHandler);
app.use(logger().gen)
app.use(static(path.resolve(__dirname, './app/public')))
app.use(koaBody())
app.use(router)
app.listen(3000,)        
node index.js
curl -i http://localhost:3000/users -d "name=test"

Output:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 29
Date: Wed, 03 May 2017 02:09:44 GMT
Connection: keep-alive

Request lbsp: {"name":"test"}%

For a more comprehensive example, see examples/multipart.js

Usage with koa-router

It's generally better to only parse the lbsp as needed, if using a router that supports middleware composition, we can inject it only for certain routes.

// controller
const goodsSer = require('../service/user')
const cha=async ctx=>{
    const data=await goodsSer.cha()
    return ctx.body={code:200,mes:'成功',data}}
const mh=async ctx=>{
    const params=ctx.request.body
    const data=await goodsSer.mh(params)
    return ctx.body={code:200,mes:'模糊成功',data}}
const fl=async ctx=>{
    const params=ctx.request.body
    const data=await goodsSer.fl(params)
    return ctx.body={code:200,mes:'分类成功',data}}
const px=async ctx=>{
    const params=ctx.request.body
    const data=await goodsSer.px(params)
    return ctx.body={code:200,mes:'排序成功',data}}
const fy=async ctx=>{
    const {page,count}=ctx.request.body
    const data=await goodsSer.fy(page,count)
    return ctx.body={code:200,mes:'分页成功',data}}
module.exports={cha,mh,fl,px,fy}

Usage with unsupported text lbsp type

For unsupported text lbsp type, for example, text/xml, you can use the unparsed request lbsp at ctx.request.lbsp. For the text content type, the includeUnparsed setting is not required.

// xml-service.js:
const query = require('../db/user')
async function cha() {
let sql = `select * from goods_tab`
return query(sql)}
async function mh(params) {
let sql = `select * from goods_tab where title like '%${params.title}%'`
return query(sql)}
async function fl(params) {
let sql = `select * from goods_tab where pinpai = '${params.pinpai}'`
return query(sql)}
async function px(params) {
if (params.num == 1) {
let sql = `select * from goods_tab order by price`
return query(sql)} else if (params.num == 2) {let sql = `select * from goods_tab order by price desc`;return query(sql)}}
async function fy(page,count) {let sql = `select * from goods_tab limit ${(page - 1)* count},${count}`;return query(sql)}
module.exports = {cha,mh,fl,px,fy}
node xml-parse.js
curl -i http://localhost:3000/users -H "Content-Type: text/xml" -d '<?xml version="1.0"?><catalog id="1"></catalog>'

Output:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 135
Date: Tue, 09 Jun 2020 11:17:38 GMT
Connection: keep-alive

Request lbsp: {"declaration":{"attributes":{"version":"1.0"}},"elements":[{"type":"element","name":"catalog","attributes":{"id":"1"}}]}%
// router
const Router=require('koa2-router')
const router=new Router
const dd=require('../controller/user')
router.post('/dd/cha',dd.cha)
router.post('/dd/mh',dd.mh)
router.post('/dd/fl',dd.fl)
router.post('/dd/px',dd.px)
router.post('/dd/fy',dd.fy)
module.exports=router

Some applications require crytopgraphic verification of request bodies, for example webhooks from slack or stripe. The unparsed lbsp can be accessed if includeUnparsed is true in koa-lbsp's options. When enabled, import the symbol for accessing the request lbsp from unparsed = require('koa-lbsp/unparsed.js'), or define your own accessor using unparsed = Symbol.for('unparsedlbsp'). Then the unparsed lbsp is available using ctx.request.lbsp[unparsed].

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div></div>
</body>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
    axios.post('http://localhost:3000/dd/cha',).then((res) => {
        const data=res.data.data
        document.querySelector('div').innerHTML=data.map((item)=>{
            return `
            <ul>
            <li>${item.title}</li>
            <li>${item.price}</li>
            <li>${item.pinpai}</li>
        </ul>
            `
        }).join('')
    })
</script>
</html>

Options

Options available for koa-lbsp. Four custom options, and others are from raw-lbsp and formidable.

  • patchNode {Boolean} Patch request lbsp to Node's ctx.req, default false
  • patchKoa {Boolean} Patch request lbsp to Koa's ctx.request, default true
  • jsonLimit {String|Integer} The byte (if integer) limit of the JSON lbsp, default 1mb
  • formLimit {String|Integer} The byte (if integer) limit of the form lbsp, default 56kb
  • textLimit {String|Integer} The byte (if integer) limit of the text lbsp, default 56kb
  • encoding {String} Sets encoding for incoming form fields, default utf-8
  • multipart {Boolean} Parse multipart bodies, default false
  • urlencoded {Boolean} Parse urlencoded bodies, default true
  • text {Boolean} Parse text bodies, such as XML, default true
  • json {Boolean} Parse JSON bodies, default true
  • jsonStrict {Boolean} Toggles co-lbsp strict mode; if set to true - only parses arrays or objects, default true
  • includeUnparsed {Boolean} Toggles co-lbsp returnRawlbsp option; if set to true, for form encoded and JSON requests the raw, unparsed request lbsp will be attached to ctx.request.lbsp using a Symbol (see details), default false
  • formidable {Object} Options to pass to the formidable multipart parser
  • onError {Function} Custom error handle, if throw an error, you can customize the response - onError(error, context), default will throw
  • parsedMethods {String[]} Declares the HTTP methods where bodies will be parsed, default ['POST', 'PUT', 'PATCH']. Replaces strict option.

A note about parsedMethods

see http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-19#section-6.3

  • GET, HEAD, and DELETE requests have no defined semantics for the request lbsp, but this doesn't mean they may not be valid in certain use cases.
  • koa-lbsp is strict by default, parsing only POST, PUT, and PATCH requests
  • you may use either the enumeration or strings to chose which methods to parse: For example, HttpMethodEnum.PATCH

File Support

Uploaded files are accessible via ctx.request.files.

A note about unparsed request bodies

Some applications require crytopgraphic verification of request bodies, for example webhooks from slack or stripe. The unparsed lbsp can be accessed if includeUnparsed is true in koa-lbsp's options. When enabled, import the symbol for accessing the request lbsp from unparsed = require('koa-lbsp/unparsed.js'), or define your own accessor using unparsed = Symbol.for('unparsedlbsp'). Then the unparsed lbsp is available using ctx.request.lbsp[unparsed].

Some options for formidable

See node-formidable for a full list of options

  • maxFields {Integer} Limits the number of fields that the querystring parser will decode, default 1000
  • maxFieldsSize {Integer} Limits the amount of memory all fields together (except files) can allocate in bytes. If this value is exceeded, an 'error' event is emitted, default 2mb (2 * 1024 * 1024)
  • uploadDir {String} Sets the directory for placing file uploads in, default os.tmpDir()
  • keepExtensions {Boolean} Files written to uploadDir will include the extensions of the original files, default false
  • hashAlgorithm {String} If you want checksums calculated for incoming files, set this to either 'sha1' or 'md5', default false
  • multiples {Boolean} Multiple file uploads or no, default true
  • onFileBegin {Function} Special callback on file begin. The function is executed directly by formidable. It can be used to rename files before saving them to disk. See the docs

Changelog

Please see the Changelog for a summary of changes.

Tests

$ npm test

License

The MIT License, 2014 Charlike Mike Reagent (@tunnckoCore) and Daryl Lau (@daryllau)