Instantly share code, notes, and snippets.

Embed
What would you like to do?
Introductory Rack-compliant web server
require 'socket'
require 'rack'
require 'sinatra'
# Simple, rack-compliant web server
class MyServer
STATUS_CODES = {
200 => 'OK',
500 => 'Internal Server Error'
}
attr_reader :app, :tcp_server
def initialize(app)
@app = app
end
def start
@tcp_server = TCPServer.new('localhost', 8080)
puts 'Listening on 8080...'
loop do
socket = tcp_server.accept
request = socket.gets
response = ''
puts request
env = new_env(*request.split)
status, headers, body = app.call(env)
response << "HTTP/1.1 #{status} #{STATUS_CODES[status]}\r\n"
headers.each do |k, v|
response << "#{k}: #{v}\r\n"
end
response << "Connection: close\r\n"
socket.print response
socket.print "\r\n"
if body.is_a?(String)
socket.print body
else
body.each do |chunk|
socket.print chunk
end
end
socket.close
end
end
def new_env(method, location, *args)
{
'REQUEST_METHOD' => method,
'SCRIPT_NAME' => '',
'PATH_INFO' => location,
'QUERY_STRING' => location.split('?').last,
'SERVER_NAME' => 'localhost',
'SERVER_PORT' => '8080',
'rack.version' => Rack.version.split('.'),
'rack.url_scheme' => 'http',
'rack.input' => StringIO.new(''),
'rack.errors' => StringIO.new(''),
'rack.multithread' => false,
'rack.run_once' => false
}
end
end
# Rack needs to know how to start the server
module Rack
module Handler
class MyServer
def self.run(app, options = {})
server = ::MyServer.new(app)
server.start
end
end
end
end
Rack::Handler.register('my_server', 'Rack::Handler::MyServer')
# Sinatra app
set :server, :my_server
get '/' do
'Hello world!'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment