【发布时间】:2017-03-27 19:04:59
【问题描述】:
我写在这里是因为我遇到了一个我自己无法解决的 Node.js 问题。让我们只关注我编写的简单服务器的 POST 请求。 我的服务器必须只接受包含 gzip 压缩数据的 POST 请求,然后解压缩它们并将提取的内容写入一个本地文件,该文件的名称位于变量“path”内。 我几乎完成了刚才解释的所有内容,我还想出了如何解压缩 gzip 数据,但我不明白如何将内容写入文件。
POST 请求(在 Debian 上执行)总是如下:
curl -sS -X POST -H "Content-Type: application/gzip" --data-binary @<(echo "Uncompressed data" | gzip) http://192.168.1.66:8080/?path=test.txt
我以许多不同的方式尝试了很多次,但尽管在我看来是正确的,但执行总是给我这个输出:
Adding Uncompressed data
to buffer..
Entering ws on finish...
buffer: 'Uncompressed data
'
events.js:163
throw er; // Unhandled 'error' event
^
Error: write after end
at writeAfterEnd (_stream_writable.js:191:12)
at WriteStream.Writable.write (_stream_writable.js:238:5)
at Gunzip.<anonymous> (C:\Users\Public\exercise2.js:54:14)
at emitNone (events.js:91:20)
at Gunzip.emit (events.js:188:7)
at endReadableNT (_stream_readable.js:974:12)
at _combinedTickCallback (internal/process/next_tick.js:80:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
我的代码是这个:
const fs = require('fs');
const http = require('http');
const url = require('url');
const zlib = require('zlib');
const home = 'C:\\Users\\Public\\server_dir'
function handle_get(path,cb){
fs.readdir(path,
(err,files) => {
if(err) cb(500,JSON.stringify({error : err.message, files: files||null})+'\n')
else cb(200,JSON.stringify({error : null, files : files})+'\n')
})
}
function handle_post(req,path,cb){
function warn(err,event){
if(err) console.warn(`Request ${event}, could not close ${path}`)
else console.warn(`Request ${event}, ${path} closed succesfully`)
}
console.log("\n\nHeaders="+req.headers+"\n\n")
var encoding = req.headers['content-encoding']
var cont_type = req.headers['content-type']
if ((encoding == undefined || encoding.indexOf("gzip") <= 0) && cont_type.indexOf("gzip") <= 0)
return cb(400, JSON.stringify({error : "Bad request: gzip encoding requested"})+'\n')
fs.open(path,'w',0o644,
(err,fd)=>
{
if(err) return cb(500,JSON.stringify({error : err.message})+'\n')
const ws=fs.createWriteStream(null,{fd:fd})
ws.on('finish',() => {
console.log("Entering ws on finish...");
cb(200, JSON.stringify({error : null, "written bytes":ws.bytesWritten})+'\n')
})
req.on('aborted',()=>fs.close(fd,err=>warn(err,'aborted')))
req.on('error',(err)=>{
fs.close(fd,err=>warn(err,'error'))
cb(500,JSON.stringify({error : err.message, "written bytes":ws.bytesWritten})+'\n')
})
var buffer = [];
var gunzip = zlib.createGunzip();
gunzip.on('data',function(data) {
var uncompressed = data.toString();
console.log("Adding '"+uncompressed+"' to buffer..")
buffer.push(uncompressed);
//ws.write(uncompressed); // I've also tried this but it does not work
}).on('end', function() {
console.log("buffer: '"+buffer+"'");
ws.write(buffer.join(""));
ws.end();
}).on('error',function(e) {
console.log("error: "+e);
})
req.pipe(gunzip);
req.pipe(ws);
})
}
var s=http.createServer(
(req,res) => {
console.log("Request: "+req.method+" URL: "+req.url)
function send(code,json_string){
res.writeHead(code,{"Content-Type" : "application/json"})
res.end(json_string)
}
if(req.method=='GET') handle_get(home+req.url,send)
if(req.method=='POST') {
var parsed_url=url.parse(req.url,true)
var path=parsed_url.query.path
console.log(parsed_url);
if(!path)
return send(400, JSON.stringify({error : 'Missing path'})+'\n')
handle_post(req,home+path,send)
}
})
s.listen(8080);
提前谢谢你。
【问题讨论】:
-
我注意到的一件事是,您正在同时从
req传输到 2 个单独的写入流。这也应该导致另一个问题,因为它们都在同时刷新流。这意味着两个目标都将具有不完整的请求数据版本。此外,当您使用fs.createWriteStream()时,应该监听'close'事件而不是'finish'事件。
标签: javascript node.js http gzip zlib