Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
#! /usr/bin/env ruby
require 'socket'
def log(source, message)
time = Time.now.strftime("%Y-%m-%d %H:%M:%S")
puts "[%s] %s => %s" % [time, source, message]
end
# Class representing HTTP Requests
Request = Struct.new(:method, :uri, :version, :headers) do
def self.parse(client)
# parse the request line
method, uri, version = client.readline.split
Request.new(method, uri, version, {}).tap do |r|
# read the headers
until (header_line = client.readline).strip == '' do
header, value = header_line.split(':').map { |s| s.strip }
r.headers[header] = value
end
end
end
end
Response = Struct.new(:version, :status_code, :reason_phrase, :headers, :body) do
def to_s
response = "#{version} #{status_code} #{reason_phrase}\r\n"
headers.each do |key, value|
response << "#{key}: #{value}\r\n"
end
response << "\r\n"
response << body
end
end
server = TCPServer.new ARGV.first.to_i
loop do
client = server.accept
info = client.remote_address
source = "%s:%s" % [info.ip_address, info.ip_port]
log source, "Connection established"
request = Request.parse(client)
log source, "Method = %s | URI = %s | Version = %s" % [request.method, request.uri, request.version]
log source, "Headers = %s" % request.headers.inspect
response = Response.new("HTTP/1.1", 200, 'OK').tap do |r|
r.body = '<h1>Hello, world!</h1>'
r.headers = {
'Connection' => 'close',
'Content-Type' => 'text/html',
'Content-Length' => r.body.bytes.length
}
end
client.write(response)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment