Skip to content

Instantly share code, notes, and snippets.

@Najaf
Created June 1, 2014 00:04
Show Gist options
  • Select an option

  • Save Najaf/7f0ca8ac1449e85d46ad to your computer and use it in GitHub Desktop.

Select an option

Save Najaf/7f0ca8ac1449e85d46ad to your computer and use it in GitHub Desktop.

Revisions

  1. Najaf created this gist Jun 1, 2014.
    59 changes: 59 additions & 0 deletions simple-response.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,59 @@
    #! /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