代码拉取完成,页面将自动刷新
'use strict'
const http = require('http')
const fs = require('fs')
const fsp = fs.promises
/** ---------------------解析Body数据----------------------------- */
/**
* Content-Disposition: form-data; name="file"; filename="xxx"
* Content-Type: text/plain
*
* @param {string} headerData
*/
function parseBodyHeaders (headerData) {
let hlist = headerData.split('\r\n').filter(p => p.length > 0)
//解析content-disposition => hlist[0]
//按照; 切分数组,选出从第二个元素开始的数组
let csplit = hlist[0].split('; ').slice(1)
let filename
let name
for (let a of csplit) {
if (a.indexOf('filename=') === 0) {
filename = a.substring(a.indexOf('=')+2, a.length - 1)
} else {
name = a.substring(a.indexOf('=')+2, a.length - 1)
}
}
let headers = {}
let ind = 0
let k
for (let h of hlist) {
ind = h.indexOf(':')
k = h.substring(0, ind).toLowerCase()
headers[k] = h.substring(ind+1).trim()
}
return {
filename,
name,
headers,
contentType: headers['content-type'] || ''
}
}
function parseBody (bodyData, headers) {
let ctype = headers['content-type']
let bdy = ctype.substring( ctype.indexOf('=') + 1 )
let crlf_bdy = `\r\n--${bdy}`
let header_end_index = bodyData.indexOf('\r\n\r\n',
crlf_bdy.length);
let headerData = bodyData.toString('utf8',
crlf_bdy.length,
header_end_index);
//解析文件头信息
let hd = parseBodyHeaders(headerData)
let file = {
start: header_end_index + 4,
end: bodyData.indexOf(crlf_bdy, header_end_index),
...hd
}
file.length = file.end - file.start
return file
}
//解析文件扩展名
function parseExtName (filename) {
if(filename.length < 2) {
return ''
}
let nsplit = filename.split('.').filter(p => p.length > 0)
if(nsplit.length < 2) return ''
return `.${nsplit[ nsplit.length - 1 ]}`
}
/** ----------------------解析Body数据 - END ----------------------- */
let html = `
<!DOCTYPE html>
<html>
<head>
<title>First HTTP</title>
</head>
<body>
你好。
</body>
</html>
`
let routerTable = {
GET : {
'/' : async (ctx) => {
response.setHeader('content-type',
'text/html; charset=utf-8')
ctx.end(html)
},
'/test' : async (ctx) => {
let status = parseInt(Math.random() * 200) + 199
ctx.response.statusCode = status
ctx.end('test end')
},
'/upload' : async (ctx) => {
let stm = fs.createReadStream('./upload.html')
stm.pipe(ctx.response, {end: false})
stm.on('end', () => {
ctx.end()
})
},
},
POST : {
'/data': async (ctx) => {
let file = parseBody(ctx.rawBody, ctx.headers)
console.log(file)
if(!ctx.rawBody) {
ctx.end();
return
}
let fname = `${Date.now()}-${Math.random()}` + `${parseExtName(file.filename)}`;
let fh = await fsp.open(fname, 'a+')
let fret = await fh.write(ctx.rawBody, file.start, file.length, 0)
fh.close();
ctx.end(`${fret.bytesWritten}`);
//ctx.end(ctx.rawBody)
}
}
}
http.createServer(async(request, response) => {
let rm = routerTable[ request.method ]
let usplit = request.url.split('?')
let pathname = usplit[0]
let querystring = usplit[1] || ''
if (!rm || !rm[ pathname ] ) {
response.statusCode = 404
response.end('page not found')
return
}
//ctx 是 contenxt的缩写,意为请求上下文,就是一个打包了各种数据和方法的对象
let ctx = {
method: request.method,
path: pathname,
search: querystring,
headers: request.headers,
reuqest: request,
response: response,
end: (data, encoding = 'utf8') => {
response.end(data, encoding)
},
write: (data, encoding = 'utf8') => {
response.write(data, encoding)
},
totalLength: 0,
rawBody: null,
bufferList: []
}
await new Promise((rv,rj) => {
if('PD'.indexOf(request.method[0]) >= 0) {
request.on('data', chunk => {
ctx.bufferList.push(chunk)
ctx.totalLength += chunk.length
})
}else {
request.on('data', data => {
response.statusCode = 400
response.end('bad request', () => {
request.destroy()
})
})
}
let resolved = false;
request.on('end', () => {
resolved = true;
rv();
})
request.on('close', () => {
(!resolved) && rv();
})
})
if(!response.writable || response.writableEnded) {
return
}
if(ctx.bufferList.length > 0) {
ctx.rawBody = Buffer.concat(ctx.bufferList, ctx.totalLength)
ctx.bufferList = []
}
rm[ pathname ](ctx)
})
.listen(3456)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。