Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
yutent | 7f6e506f4a | |
yutent | a395c87101 | |
yutent | 8afca9afaa | |
yutent | 9d66a77b4d | |
yutent | 2203b683f5 | |
yutent | face3185f7 | |
yutent | 5ecf94b5f3 | |
yutent | 53b0e2443e |
110
Readme.md
110
Readme.md
|
@ -1,4 +1,6 @@
|
||||||
![module info](https://nodei.co/npm/@gm5/request.png?downloads=true&downloadRank=true&stars=true)
|
|
||||||
|
![downloads](https://img.shields.io/npm/dt/@gm5/request.svg)
|
||||||
|
![version](https://img.shields.io/npm/v/@gm5/request.svg)
|
||||||
|
|
||||||
# @gm5/equest
|
# @gm5/equest
|
||||||
> 对Http的request进一步封装, 提供常用的API.
|
> 对Http的request进一步封装, 提供常用的API.
|
||||||
|
@ -19,115 +21,13 @@ http
|
||||||
.createServer((req, res) => {
|
.createServer((req, res) => {
|
||||||
let request = new Request(req, res)
|
let request = new Request(req, res)
|
||||||
|
|
||||||
console.log(request.origin) // {req, res}
|
|
||||||
|
|
||||||
// print the fixed url
|
// print the fixed url
|
||||||
console.log(request.url)
|
console.log(request.url)
|
||||||
|
|
||||||
request.ip() // get client ip address
|
request.ip // get client ip address
|
||||||
|
|
||||||
// http://test.com/?foo=bar
|
// http://test.com/?foo=bar
|
||||||
request.get('foo') // bar
|
request.query['foo'] // bar
|
||||||
})
|
})
|
||||||
.listen(3000)
|
.listen(3000)
|
||||||
```
|
```
|
||||||
|
|
||||||
## API
|
|
||||||
|
|
||||||
### origin
|
|
||||||
> 返回原始的response & request对象
|
|
||||||
|
|
||||||
```js
|
|
||||||
console.log(request.origin) // {req: request, res: response}
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### app
|
|
||||||
> 返回一级路由的名字
|
|
||||||
|
|
||||||
```js
|
|
||||||
// abc.com/foo/bar
|
|
||||||
console.log(request.app) // foo
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
### path
|
|
||||||
> 以数组形式,返回除一级路由之外剩下的路径
|
|
||||||
|
|
||||||
```js
|
|
||||||
// abc.com/foo/bar/aa/bb
|
|
||||||
console.log(request.path) // ['bar', 'aa', 'bb']
|
|
||||||
```
|
|
||||||
|
|
||||||
### url
|
|
||||||
> 返回修正过的url路径
|
|
||||||
|
|
||||||
```js
|
|
||||||
// abc.com/foo/bar/aa/bb
|
|
||||||
// abc.com////foo///bar/aa/bb
|
|
||||||
console.log(request.url) // foo/bar/aa/bb
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### get([key[,xss]])
|
|
||||||
|
|
||||||
* key `<String>` 字段名 [可选], 不则返回全部参数
|
|
||||||
* xss `<Boolean>` 是否进行xss过滤 [可选], 默认为ture
|
|
||||||
|
|
||||||
> 返回URL上的query参数, 类似于`$_GET[]`;
|
|
||||||
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// http://test.com?name=foo&age=18
|
|
||||||
request.get('name') // foo
|
|
||||||
request.get('age') // 18
|
|
||||||
|
|
||||||
request.get() // {name: 'foo', age: 18}
|
|
||||||
request.get('weight') // return null if not exists
|
|
||||||
```
|
|
||||||
|
|
||||||
### post([key[,xss]])
|
|
||||||
|
|
||||||
* key `<String>` optional
|
|
||||||
* xss `<Boolean>` optional
|
|
||||||
|
|
||||||
> 读取post请求的body, 类似于 `$_POST[]`.
|
|
||||||
|
|
||||||
> **该方法返回的是Promise对象**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// http://test.com
|
|
||||||
await request.post('name') // foo
|
|
||||||
await request.post('age') // 18
|
|
||||||
|
|
||||||
// return all if not yet argument given
|
|
||||||
await request.post() // {name: 'foo', age: 18}
|
|
||||||
await request.post('weight') // return null if not exists
|
|
||||||
```
|
|
||||||
|
|
||||||
### header([key])
|
|
||||||
|
|
||||||
* key `<String>` 字段名[可选], 不传则返回全部
|
|
||||||
|
|
||||||
> 返回请求头
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
request.header('user-agent') // Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 ...
|
|
||||||
|
|
||||||
// return all if not yet argument given
|
|
||||||
request.header() // {'user-agent': '...'[, ...]}
|
|
||||||
```
|
|
||||||
|
|
||||||
### ip()
|
|
||||||
|
|
||||||
> 获取客户端IP地址.
|
|
||||||
>
|
|
||||||
> It would return '127.0.0.1' maybe if in local area network.
|
|
||||||
|
|
||||||
|
|
||||||
### cookie(key)
|
|
||||||
|
|
||||||
> 获取客户端带上的cookie.
|
|
||||||
> 不传key时返回所有的
|
|
||||||
|
|
||||||
|
|
86
index.js
86
index.js
|
@ -5,12 +5,13 @@
|
||||||
|
|
||||||
import 'es.shim'
|
import 'es.shim'
|
||||||
|
|
||||||
|
import { fileURLToPath, parse } from 'node:url'
|
||||||
|
import { dirname, resolve } from 'node:path'
|
||||||
|
import fs from 'iofs'
|
||||||
|
|
||||||
import Parser from './lib/index.js'
|
import Parser from './lib/index.js'
|
||||||
import { parseCookie } from './lib/cookie.js'
|
import { parseCookie } from './lib/cookie.js'
|
||||||
import fs from 'iofs'
|
import { querystring } from './lib/helper.js'
|
||||||
import { fileURLToPath, parse } from 'node:url'
|
|
||||||
import QS from 'node:querystring'
|
|
||||||
import { dirname, resolve } from 'node:path'
|
|
||||||
|
|
||||||
const DEFAULT_FORM_TYPE = 'application/x-www-form-urlencoded'
|
const DEFAULT_FORM_TYPE = 'application/x-www-form-urlencoded'
|
||||||
|
|
||||||
|
@ -45,11 +46,14 @@ export default class Request {
|
||||||
#body = null
|
#body = null
|
||||||
#cookies = Object.create(null)
|
#cookies = Object.create(null)
|
||||||
|
|
||||||
|
controller = 'index'
|
||||||
method = 'GET'
|
method = 'GET'
|
||||||
path = []
|
path = []
|
||||||
|
|
||||||
url = ''
|
url = ''
|
||||||
host = '127.0.0.1'
|
host = '127.0.0.1'
|
||||||
|
hostname = '127.0.0.1'
|
||||||
|
protocol = 'http'
|
||||||
|
|
||||||
constructor(req, res, opts = {}) {
|
constructor(req, res, opts = {}) {
|
||||||
this.method = req.method.toUpperCase()
|
this.method = req.method.toUpperCase()
|
||||||
|
@ -57,7 +61,10 @@ export default class Request {
|
||||||
this.#req = req
|
this.#req = req
|
||||||
this.#res = res
|
this.#res = res
|
||||||
|
|
||||||
this.host = req.headers['host']
|
this.host = req.headers['host'] || '127.0.0.1'
|
||||||
|
this.hostname = this.host.split(':')[0]
|
||||||
|
this.protocol = req.headers['x-forwarded-proto'] || 'http'
|
||||||
|
|
||||||
this.#cookies = parseCookie(this.headers['cookie'] || '')
|
this.#cookies = parseCookie(this.headers['cookie'] || '')
|
||||||
|
|
||||||
Object.assign(this.#opts, opts)
|
Object.assign(this.#opts, opts)
|
||||||
|
@ -67,44 +74,44 @@ export default class Request {
|
||||||
|
|
||||||
// 修正请求的url
|
// 修正请求的url
|
||||||
#init() {
|
#init() {
|
||||||
let _url = parse(this.#req.url)
|
let url = parse(this.#req.url)
|
||||||
.pathname.slice(1)
|
.pathname.slice(1)
|
||||||
.replace(/[\/]+$/, '')
|
.replace(/[\/]+$/, '')
|
||||||
let app = '' // 将作为主控制器(即apps目录下的应用)
|
let controller = '' // 将作为主控制器(即apps目录下的应用)
|
||||||
let pathArr = []
|
let path = []
|
||||||
|
|
||||||
// URL上不允许有非法字符
|
// URL上不允许有非法字符
|
||||||
if (/[^\w-/.,@~!$&:+'"=]/.test(decode(_url))) {
|
if (/[^\w-/.,@~!$&:+'"=]/.test(decode(url))) {
|
||||||
this.#res.rendered = true
|
this.#res.rendered = true
|
||||||
this.#res.writeHead(400, {
|
this.#res.writeHead(400, {
|
||||||
'X-debug': `url [/${encode(_url)}] contains invalid characters`
|
'X-debug': `url [/${encode(url)}] contains invalid characters`
|
||||||
})
|
})
|
||||||
return this.#res.end(`Invalid characters: /${_url}`)
|
return this.#res.end(`Invalid characters: /${url}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 修正url中可能出现的"多斜杠"
|
// 修正url中可能出现的"多斜杠"
|
||||||
_url = _url.replace(/[\/]+/g, '/').replace(/^\//, '')
|
url = url.replace(/[\/]+/g, '/').replace(/^\//, '')
|
||||||
|
|
||||||
pathArr = _url.split('/')
|
path = url.split('/')
|
||||||
if (!pathArr[0] || pathArr[0] === '') {
|
if (!path[0] || path[0] === '') {
|
||||||
pathArr[0] = 'index'
|
path[0] = 'index'
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathArr[0].indexOf('.') !== -1) {
|
if (path[0].includes('.')) {
|
||||||
app = pathArr[0].slice(0, pathArr[0].indexOf('.'))
|
controller = path[0].slice(0, path[0].indexOf('.'))
|
||||||
// 如果app为空(这种情况一般是url前面带了个"."造成的),则自动默认为index
|
// 如果app为空(这种情况一般是url前面带了个"."造成的),则自动默认为index
|
||||||
if (!app || app === '') {
|
if (!controller || controller === '') {
|
||||||
app = 'index'
|
controller = 'index'
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
app = pathArr[0]
|
controller = path[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
pathArr.shift()
|
path.shift()
|
||||||
|
|
||||||
this.app = app
|
this.controller = controller
|
||||||
this.url = _url
|
this.url = url
|
||||||
this.path = pathArr
|
this.path = path
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,32 +133,22 @@ export default class Request {
|
||||||
this.#body = value
|
this.#body = value
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (~contentType.indexOf('urlencoded')) {
|
|
||||||
if (
|
|
||||||
name.slice(0, 2) === '{"' &&
|
|
||||||
(name.slice(-2) === '"}' || value.slice(-2) === '"}')
|
|
||||||
) {
|
|
||||||
name = name.replace(/\s/g, '+')
|
|
||||||
|
|
||||||
if (value.slice(0, 1) === '=') value = '=' + value
|
if (name.endsWith('[]')) {
|
||||||
|
|
||||||
return Object.assign(this.#body, JSON.parse(name + value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name.slice(-2) === '[]') {
|
|
||||||
name = name.slice(0, -2)
|
name = name.slice(0, -2)
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
value = [value]
|
value = [value]
|
||||||
}
|
}
|
||||||
} else if (name.slice(-1) === ']') {
|
} else if (name.slice(-1) === ']') {
|
||||||
let key = name.slice(name.lastIndexOf('[') + 1, -1)
|
let idx = name.lastIndexOf('[')
|
||||||
name = name.slice(0, name.lastIndexOf('['))
|
let key = name.slice(idx + 1, -1)
|
||||||
|
name = name.slice(0, idx)
|
||||||
|
|
||||||
//多解析一层对象(也仅支持到这一层)
|
//多解析一层对象(也仅支持到这一层)
|
||||||
if (name.slice(-1) === ']') {
|
if (name.slice(-1) === ']') {
|
||||||
let pkey = name.slice(name.lastIndexOf('[') + 1, -1)
|
idx = name.lastIndexOf('[')
|
||||||
name = name.slice(0, name.lastIndexOf('['))
|
let pkey = name.slice(idx + 1, -1)
|
||||||
|
name = name.slice(0, idx)
|
||||||
|
|
||||||
if (!this.#body.hasOwnProperty(name)) {
|
if (!this.#body.hasOwnProperty(name)) {
|
||||||
this.#body[name] = {}
|
this.#body[name] = {}
|
||||||
|
@ -191,6 +188,9 @@ export default class Request {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on('buffer', buf => {
|
||||||
|
this.#body = buf
|
||||||
|
})
|
||||||
.on('error', out.reject)
|
.on('error', out.reject)
|
||||||
.on('end', _ => {
|
.on('end', _ => {
|
||||||
if (contentType.includes('urlencoded')) {
|
if (contentType.includes('urlencoded')) {
|
||||||
|
@ -225,8 +225,8 @@ export default class Request {
|
||||||
|
|
||||||
get query() {
|
get query() {
|
||||||
if (!this.#query) {
|
if (!this.#query) {
|
||||||
let para = parse(this.#req.url).query
|
let data = parse(this.#req.url).query
|
||||||
this.#query = QS.parse(para)
|
this.#query = querystring(data)
|
||||||
}
|
}
|
||||||
return this.#query
|
return this.#query
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/**
|
||||||
|
* {}
|
||||||
|
* @author yutent<yutent.io@gmail.com>
|
||||||
|
* @date 2024/07/16 17:01:43
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { parse } from 'node:querystring'
|
||||||
|
|
||||||
|
export function querystring(str) {
|
||||||
|
let query = parse(str)
|
||||||
|
for (let k of Object.keys(query)) {
|
||||||
|
let val = query[k]
|
||||||
|
|
||||||
|
if (k.endsWith('[]')) {
|
||||||
|
let _k = k.slice(0, -2)
|
||||||
|
query[_k] = val
|
||||||
|
delete query[k]
|
||||||
|
} else if (k.endsWith(']')) {
|
||||||
|
let idx = k.lastIndexOf('[')
|
||||||
|
let _pk = k.slice(0, idx)
|
||||||
|
let _k = k.slice(idx + 1, -1)
|
||||||
|
|
||||||
|
if (query[_pk]) {
|
||||||
|
query[_pk][_k] = val
|
||||||
|
} else {
|
||||||
|
query[_pk] = { [_k]: val }
|
||||||
|
}
|
||||||
|
delete query[k]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return query
|
||||||
|
}
|
29
lib/index.js
29
lib/index.js
|
@ -6,7 +6,7 @@ import { EventEmitter } from 'node:events'
|
||||||
import File from './file.js'
|
import File from './file.js'
|
||||||
import { MultipartParser } from './multipart_parser.js'
|
import { MultipartParser } from './multipart_parser.js'
|
||||||
import { UrlencodedParser } from './urlencoded_parser.js'
|
import { UrlencodedParser } from './urlencoded_parser.js'
|
||||||
import { OctetParser, EmptyParser } from './octet_parser.js'
|
import { OctetParser, BufferParser, EmptyParser } from './octet_parser.js'
|
||||||
import { JSONParser } from './json_parser.js'
|
import { JSONParser } from './json_parser.js'
|
||||||
|
|
||||||
function randomPath(uploadDir) {
|
function randomPath(uploadDir) {
|
||||||
|
@ -98,8 +98,8 @@ export default class IncomingForm extends EventEmitter {
|
||||||
let value = Buffer.from('')
|
let value = Buffer.from('')
|
||||||
|
|
||||||
part
|
part
|
||||||
.on('data', buff => {
|
.on('data', buf => {
|
||||||
value = Buffer.concat([value, buff])
|
value = Buffer.concat([value, buf])
|
||||||
})
|
})
|
||||||
.on('end', () => {
|
.on('end', () => {
|
||||||
this.emit('field', part.name, value.toString(this.encoding))
|
this.emit('field', part.name, value.toString(this.encoding))
|
||||||
|
@ -138,7 +138,7 @@ export default class IncomingForm extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
#parseContentType() {
|
#parseContentType() {
|
||||||
let contentType = this.headers['content-type']
|
let contentType = this.headers['content-type'] || ''
|
||||||
let lower = contentType.toLowerCase()
|
let lower = contentType.toLowerCase()
|
||||||
|
|
||||||
if (this.bytesExpected === 0) {
|
if (this.bytesExpected === 0) {
|
||||||
|
@ -167,7 +167,7 @@ export default class IncomingForm extends EventEmitter {
|
||||||
return this.#createJsonParser()
|
return this.#createJsonParser()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#handleError(new TypeError('unknown content-type: ' + contentType))
|
this.#createBufferParser()
|
||||||
}
|
}
|
||||||
|
|
||||||
#parseContentLength() {
|
#parseContentLength() {
|
||||||
|
@ -278,6 +278,10 @@ export default class IncomingForm extends EventEmitter {
|
||||||
#createUrlencodedParser() {
|
#createUrlencodedParser() {
|
||||||
this.#parser = new UrlencodedParser()
|
this.#parser = new UrlencodedParser()
|
||||||
|
|
||||||
|
if (this.bytesExpected) {
|
||||||
|
this.#parser.initLength(this.bytesExpected)
|
||||||
|
}
|
||||||
|
|
||||||
this.#parser
|
this.#parser
|
||||||
.on('field', fields => this.emit('field', false, fields))
|
.on('field', fields => this.emit('field', false, fields))
|
||||||
.on('end', () => this.#handleEnd())
|
.on('end', () => this.#handleEnd())
|
||||||
|
@ -316,6 +320,21 @@ export default class IncomingForm extends EventEmitter {
|
||||||
.on('error', err => this.#handleError(err))
|
.on('error', err => this.#handleError(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#createBufferParser() {
|
||||||
|
this.#parser = new BufferParser()
|
||||||
|
|
||||||
|
if (this.bytesExpected) {
|
||||||
|
this.#parser.initLength(this.bytesExpected)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.#parser
|
||||||
|
.on('buffer', buf => {
|
||||||
|
this.emit('buffer', buf)
|
||||||
|
})
|
||||||
|
.on('end', () => this.#handleEnd())
|
||||||
|
.on('error', err => this.#handleError(err))
|
||||||
|
}
|
||||||
|
|
||||||
#clearUploads() {
|
#clearUploads() {
|
||||||
while (this.#openedFiles.length) {
|
while (this.#openedFiles.length) {
|
||||||
let file = this.#openedFiles.pop()
|
let file = this.#openedFiles.pop()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { EventEmitter } from 'node:events'
|
import { EventEmitter } from 'node:events'
|
||||||
|
|
||||||
export class JSONParser extends EventEmitter {
|
export class JSONParser extends EventEmitter {
|
||||||
#buff = Buffer.from('')
|
#buf = Buffer.from('')
|
||||||
#byteLen = 0
|
#byteLen = 0
|
||||||
|
|
||||||
initLength(length) {
|
initLength(length) {
|
||||||
|
@ -9,12 +9,12 @@ export class JSONParser extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
write(buffer) {
|
write(buffer) {
|
||||||
this.#buff = Buffer.concat([this.#buff, buffer])
|
this.#buf = Buffer.concat([this.#buf, buffer])
|
||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
if (this.#buff.length === this.#byteLen) {
|
if (this.#buf.length === this.#byteLen) {
|
||||||
let data = this.#buff.toString()
|
let data = this.#buf.toString()
|
||||||
let fields = data
|
let fields = data
|
||||||
try {
|
try {
|
||||||
fields = JSON.parse(data)
|
fields = JSON.parse(data)
|
||||||
|
@ -28,14 +28,14 @@ export class JSONParser extends EventEmitter {
|
||||||
this.emit('field', false, fields)
|
this.emit('field', false, fields)
|
||||||
this.emit('end')
|
this.emit('end')
|
||||||
|
|
||||||
this.#buff = null
|
this.#buf = null
|
||||||
} else {
|
} else {
|
||||||
this.emit(
|
this.emit(
|
||||||
'error',
|
'error',
|
||||||
new Error(
|
new Error(
|
||||||
`The uploaded data is incomplete. Expected ${
|
`The uploaded data is incomplete. Expected ${
|
||||||
this.#byteLen
|
this.#byteLen
|
||||||
}, Received ${this.#buff.length} .`
|
}, Received ${this.#buf.length} .`
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,11 +73,11 @@ export class MultipartParser {
|
||||||
this[k + 'Mark'] = v
|
this[k + 'Mark'] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
#emit(name, buff, idx, cleanup) {
|
#emit(name, buf, idx, cleanup) {
|
||||||
let mark = name + 'Mark'
|
let mark = name + 'Mark'
|
||||||
if (this[mark] !== void 0) {
|
if (this[mark] !== void 0) {
|
||||||
let start = this[mark]
|
let start = this[mark]
|
||||||
let end = buff.length
|
let end = buf.length
|
||||||
|
|
||||||
if (cleanup) {
|
if (cleanup) {
|
||||||
end = idx
|
end = idx
|
||||||
|
@ -89,7 +89,7 @@ export class MultipartParser {
|
||||||
if (start === end) {
|
if (start === end) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this['$' + name](buff.slice(start, end))
|
this['$' + name](buf.slice(start, end))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,36 @@ export class OctetParser extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class BufferParser extends EventEmitter {
|
||||||
|
#buf = Buffer.from('')
|
||||||
|
#byteLen = 0
|
||||||
|
|
||||||
|
initLength(length) {
|
||||||
|
this.#byteLen = length
|
||||||
|
}
|
||||||
|
|
||||||
|
write(buffer) {
|
||||||
|
this.#buf = Buffer.concat([this.#buf, buffer])
|
||||||
|
}
|
||||||
|
|
||||||
|
end() {
|
||||||
|
if (this.#buf.length === this.#byteLen) {
|
||||||
|
this.emit('buffer', this.#buf)
|
||||||
|
this.emit('end')
|
||||||
|
this.#buf = null
|
||||||
|
} else {
|
||||||
|
this.emit(
|
||||||
|
'error',
|
||||||
|
new Error(
|
||||||
|
`The uploaded data is incomplete. Expected ${
|
||||||
|
this.#byteLen
|
||||||
|
}, Received ${this.#buf.length} .`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class EmptyParser extends EventEmitter {
|
export class EmptyParser extends EventEmitter {
|
||||||
write() {}
|
write() {}
|
||||||
|
|
||||||
|
|
|
@ -4,23 +4,40 @@
|
||||||
* @date 2023/10/27 12:14:05
|
* @date 2023/10/27 12:14:05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { parse } from 'node:querystring'
|
|
||||||
import { EventEmitter } from 'node:events'
|
import { EventEmitter } from 'node:events'
|
||||||
|
import { querystring } from './helper.js'
|
||||||
|
|
||||||
export class UrlencodedParser extends EventEmitter {
|
export class UrlencodedParser extends EventEmitter {
|
||||||
#buff = Buffer.from('')
|
#buf = Buffer.from('')
|
||||||
|
#byteLen = 0
|
||||||
|
|
||||||
|
initLength(length) {
|
||||||
|
this.#byteLen = length
|
||||||
|
}
|
||||||
|
|
||||||
write(buffer) {
|
write(buffer) {
|
||||||
this.#buff = Buffer.concat([this.#buff, buffer])
|
this.#buf = Buffer.concat([this.#buf, buffer])
|
||||||
}
|
}
|
||||||
|
|
||||||
end() {
|
end() {
|
||||||
let data = this.#buff.toString()
|
if (this.#buf.length === this.#byteLen) {
|
||||||
let fields = parse(data)
|
let data = this.#buf.toString()
|
||||||
|
let fields = querystring(data)
|
||||||
|
|
||||||
this.#buff = null
|
this.#buf = null
|
||||||
|
|
||||||
this.emit('field', fields)
|
this.emit('field', fields)
|
||||||
this.emit('end')
|
this.emit('end')
|
||||||
|
this.#buf = null
|
||||||
|
} else {
|
||||||
|
this.emit(
|
||||||
|
'error',
|
||||||
|
new Error(
|
||||||
|
`The uploaded data is incomplete. Expected ${
|
||||||
|
this.#byteLen
|
||||||
|
}, Received ${this.#buf.length} .`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@gm5/request",
|
"name": "@gm5/request",
|
||||||
"version": "2.0.0",
|
"version": "2.0.7",
|
||||||
"description": "对Http的Request进一步封装, 提供常用的API",
|
"description": "对Http的Request进一步封装, 提供常用的API",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"author": "yutent",
|
"author": "yutent",
|
||||||
|
@ -15,9 +15,9 @@
|
||||||
"http"
|
"http"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"es.shim": "^2.0.1",
|
"es.shim": "^2.2.0",
|
||||||
"iofs": "^1.5.0"
|
"iofs": "^1.5.3"
|
||||||
},
|
},
|
||||||
"repository": "https://github.com/bytedo/gmf.request.git",
|
"repository": "https://git.wkit.fun/gm5/request.git",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue