私は小さなウェブサーバーを書いています。を読みたいですHTTP Request
。体が関与していないときに機能します。しかし、ボディが送信されると、ボディの内容を満足のいく方法で読み取ることができません。
経由でクライアントからのデータを読み取りますTCPSocket
。このTCPSocket::gets
メソッドは、本体のデータが受信されるまで読み取ります。EOF
HTTP リクエスト本文の末尾には、区切り文字や send to signal はありません。HTTP/1.1 仕様 - セクション 4.4には、メッセージの長さを取得する 5 つのケースがリストされています。ポイント1)は機能します。ポイント 2) と 4) は、私のアプリケーションには関係ありません。ポイント 5) は、応答を送信する必要があるため、オプションではありません。
フィールドの値を読み取ることができますContent-Length
。しかし、read(contentlength)
またはを介してHTTPリクエストの最後の部分を読み取るようにTCPSocketを「説得」しようとするとrcv(contentlength)
、成功しません。ヘッダーとボディを分離するまで行ごとに読む\r\n
ことはできますが、その後は行き詰まります-少なくとも私がやりたい方法で。
だから私の質問は:
コードで意図したようにする可能性はありますか? 正しく読むという私の目標を達成するためのより良い方法はありますかHTTP Request
(私が本当に望んでいます)?
これが実行可能なコードです。やりたい部分はコメントに。
#!/usr/bin/ruby
require 'socket'
server = TCPServer.new 2000
loop do
Thread.start(server.accept) do |client|
hascontent = false
contentlength = 0
content = ""
request = ""
#This seems to work, but I'm not really happy with it, too much is happening in
#the loop
while(buf = client.readpartial(4096))
request = request + buf
split = request.split("\r\n")
puts request
puts request.dump
puts split.length
puts split.inspect
if(request.index("\r\n\r\n")>0)
break
end
end
#This part is commented out because it doesn't work
=begin
while(line = client.gets)
puts ":" + line
request = request + line
if(line.start_with?("Content-Length"))
hascontent = true
split = line.split(' ')
contentlength = split[1]
end
if(line == "\r\n" and !hascontent)
break
end
if(line == "\r\n" and hascontent)
puts "Trying to get content :P"
puts contentlength
puts content.length
puts client.inspect
#tried read, with and without parameter, rcv, also with and
#without param and their nonblocking couterparts
#where does my thought process go in the wrong direction
while(readin = client.readpartial(contentlength))
puts readin
content = content + readin
end
break
end
end
=end
puts request
client.close
end