2011-06-03 68 views
8

該代碼是否爲有效的HTTP/1.1?Node.js:分塊傳輸編碼

var fs = require('fs') 
var http = require('http') 

var buf=function(res,fd,i,s,buffer){ 
if(i+buffer.length<s){ 
    fs.read(fd,buffer,0,buffer.length,i,function(e,l,b){ 
    res.write(b.slice(0,l)) 
    //console.log(b.toString('utf8',0,l)) 
    i=i+buffer.length 
    buf(res,fd,i,s,buffer) 
    }) 
} 
else{ 
    fs.read(fd,buffer,0,buffer.length,i,function(e,l,b){ 
    res.end(b.slice(0,l)) 
    fs.close(fd) 
    }) 
} 
} 

var app = function(req,res){ 
var head={'Content-Type':'text/html; charset=UTF-8'} 
switch(req.url.slice(-3)){ 
    case '.js':head={'Content-Type':'text/javascript'};break; 
    case 'css':head={'Content-Type':'text/css'};break; 
    case 'png':head={'Content-Type':'image/png'};break; 
    case 'ico':head={'Content-Type':'image/x-icon'};break; 
    case 'ogg':head={'Content-Type':'audio/ogg'};break; 
    case 'ebm':head={'Content-Type':'video/webm'};break; 
} 
head['Transfer-Encoding']='chunked' 
res.writeHead(200,head) 
fs.open('.'+req.url,'r',function(err,fd){ 
    fs.fstat(fd,function(err, stats){ 
    console.log('.'+req.url+' '+stats.size+' '+head['Content-Type']+' '+head['Transfer-Encoding']) 
    var buffer = new Buffer(100) 
    buf(res,fd,0,stats.size,buffer) 
    }) 
}) 
} 

http.createServer(app).listen(8000,"127.0.0.1") 
console.log('GET http://127.0.0.1:8000/appwsgi/www/index.htm') 

我想我在這裏違反了HTTP/1.1?文本文件似乎工作正常,但這可能是巧合。我的標題是「200 OK」還是需要它爲「100」?一個頭是否足夠?

回答

11

如果你正在做塊傳輸編碼,您實際需要設置標題:

Transfer-Encoding: chunked

您可以從由谷歌返回的頭,它不轉讓分塊的網頁,並很可能會看到其他網頁:

HTTP/1.1 200 OK 
Date: Sat, 04 Jun 2011 00:04:08 GMT 
Expires: -1 
Cache-Control: private, max-age=0 
Content-Type: text/html; charset=ISO-8859-1 
Set-Cookie: PREF=ID=f9c65f4927515ce7:FF=0:TM=1307145848:LM=1307145848:S=fB58RFtpI5YeXdU9; expires=Mon, 03-Jun-2013 00:04:08 GMT; path=/; domain=.google.com 
Set-Cookie: NID=47=UiPfl5ew2vCEte9JyBRkrFk4EhRQqy4dRuzG5Y-xeE---Q8AVvPDQq46GYbCy9VnOA8n7vxR8ETEAxKCh-b58r7elfURfiskmrOCgU706msiUx8L9qBpw-3OTPsY-6tl; expires=Sun, 04-Dec-2011 00:04:08 GMT; path=/; domain=.google.com; HttpOnly 
Server: gws 
X-XSS-Protection: 1; mode=block 
Transfer-Encoding: chunked 

編輯哎呀,那讀的方式過於複雜:

var app = function(req,res){ 
var head={'Content-Type':'text/html'} 
switch(req.url.slice(-3)){ 
    case '.js':head={'Content-Type':'text/javascript'};break; 
    case 'css':head={'Content-Type':'text/css'};break; 
    case 'png':head={'Content-Type':'image/png'};break; 
    case 'ico':head={'Content-Type':'image/x-icon'};break; 
    case 'ogg':head={'Content-Type':'audio/ogg'};break; 
    case 'ebm':head={'Content-Type':'video/webm'};break; 
} 
res.writeHead(200,head) 
var file_stream = fs.createReadStream('.'+req.url); 
file_stream.on("error", function(exception) { 
    console.error("Error reading file: ", exception); 
}); 
file_stream.on("data", function(data) { 
    res.write(data); 
}); 
file_stream.on("close", function() { 
    res.end(); 
}); 
} 

你走了,一個漂亮的流緩衝區供你寫。 這是我寫的一篇博文,以不同的方式讀取文件。我建議您仔細觀察,以便您能夠看到如何在節點的異步環境中更好地使用文件。

+0

這是令人困惑的,因爲在發送分塊軟件包時,響應是否需要爲200? – 2011-06-04 00:20:07

+0

@Gert從谷歌閱讀標題我發佈在我的回覆中,其中有200 OK。當然,如果你正在重定向,或者「是的,我現在有這個文件在這裏,然後將它發送給你」類型的情況之外,你應該使用適當的頭。我建議看看所有的頭文件和它們代表什麼:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html。如果你想繼續像這樣在一個低級別上使用node.js,這將對你有益。 – 2011-06-04 00:25:48

3

你爲什麼要手動執行所有fs操作?使用fs.createReadStream()函數可能會更好。

最重要的是,我的猜測是,Chrome期待您返回206響應代碼。檢查req.headers.range,並查看Chrome是否期待要返回媒體文件的「範圍」。如果是這樣,那麼你只需要發回網絡瀏覽器所請求的文件部分。

爲什麼要重新發明輪子?有大量的節點模塊爲你做這種事情。嘗試Connect/Express'中間件'static。祝你好運!

+1

修復代碼後,它只播放媒體一次。我想你對範圍反應是正確的。 – 2011-06-05 01:44:56

9

由於Node.js的隱式設置「傳輸編碼:分塊」,所有我需要在頭送了內容類型與字符集,如:

'Content-Type': 'text/html; charset=UTF-8' 

最初,它是:

'Content-Type': 'text/html' 

哪個沒有工作。指定「charset = UTF-8」立即強制Chrome呈現分塊響應。

+1

與我的代碼的顯式字符集工作,但我注意到,它不適用於文本/普通內容類型(在鉻上測試)......奇怪的行爲... – 2012-10-16 12:23:30

+0

我不確定你爲什麼有這種行爲。我會測試這個和稍後回覆。 – Eye 2012-10-22 12:33:48

+0

在我的測試中它可以在Firefox上使用,但不能在Chrome上使用(僅適用於文本/純文本內容類型)... – 2012-10-22 17:11:07