Skip to content

Instantly share code, notes, and snippets.

@jonduarte
Created January 4, 2018 22:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jonduarte/d7f27c4eb3a8ae124125e9b5070e014d to your computer and use it in GitHub Desktop.
Save jonduarte/d7f27c4eb3a8ae124125e9b5070e014d to your computer and use it in GitHub Desktop.
Parser HTTP em Ruby
class Parser
END_OF_HEADERS = /\r\n\r\n/
attr_accessor :method, :version, :headers, :path
def initialize
@data = ""
@completed = false
@headers = {}
end
def feed(partial)
@data << partial
if @data =~ END_OF_HEADERS
process!(@data)
end
end
def process!(data)
lines = data.split("\r\n")
# GET /check HTTP/1.1
# @method = GET
# @path = /check
# @version = HTTP/1.1
@method, @path, @version = lines.shift.split(" ")
lines.each do |line|
name, value = line.split(":", 2)
@headers[name] = value.lstrip
end
@completed = true
end
def completed?
@completed
end
end
require_relative './parser'
describe Parser do
let(:parser) { described_class.new }
def each_chunk(file)
size = 10
open(file, 'rb') do |f|
yield f.read(size) until f.eof?
end
end
it 'parser http request' do
each_chunk('request.txt') do |chunk|
parser.feed(chunk)
end
expect(parser).to be_completed
expect(parser.method).to eq('GET')
expect(parser.path).to eq('/')
expect(parser.version).to eq('HTTP/1.1')
expect(parser.headers).to eq({
'Host' => 'localhost:8000',
'User-Agent' => 'curl/7.51.0',
'Accept' => '*/*'
})
end
end
GET / HTTP/1.1
Host: localhost:8000
User-Agent: curl/7.51.0
Accept: */*
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment