Skip to content

Commit

Permalink
Witness the power of this fully functional HTTP toolkit.
Browse files Browse the repository at this point in the history
  • Loading branch information
seancribbs committed Aug 25, 2011
1 parent 5f4da1b commit 11051db
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 69 deletions.
33 changes: 26 additions & 7 deletions README.md
Expand Up @@ -16,12 +16,14 @@ intentional! Rack obscures HTTP in a way that makes it hard for
Webmachine to do its job properly, and encourages people to add
middleware that might break Webmachine's behavior. Rack is also built
on the tradition of CGI, which is nice for backwards compatibility but
also an antiquated paradigm and should be scuttled (IMHO).
also an antiquated paradigm and should be scuttled (IMHO). _Rack may
be supported in the future, but only as a shim to support other web
application servers._

## Getting Started

Webmachine.rb is not fully-functional yet, but constructing an
application for it will follow this general outline:
Webmachine is very young, but it's still easy to construct an
application for it!

```ruby
require 'webmachine'
Expand All @@ -31,7 +33,7 @@ require 'my_resource'
# Point all URIs at the MyResource class
Webmachine::Dispatcher.add_route(['*'], MyResource)

# Start the server, binds to the default interface/port
# Start the server, binds to port 3000 using WEBrick
Webmachine.run
```

Expand All @@ -47,7 +49,24 @@ end

Run the first file and your application is up. That's all there is to
it! If you want to customize your resource more, look at the available
callbacks in lib/webmachine/resource/callbacks.rb.
callbacks in lib/webmachine/resource/callbacks.rb. For example, you
might want to enable "gzip" compression on your resource, for which
you can simply add an `encodings_provided` callback method:

```ruby
class MyResource < Webmachine::Resource
def encodings_provided
{"gzip" => :encode_gzip, "identity" => :encode_identity}
end

def to_html
"<html><body>Hello, world!</body></html>"
end
end
```

There are many other HTTP features exposed to your resource through
callbacks. Give them a try!

## Features

Expand All @@ -57,11 +76,11 @@ callbacks in lib/webmachine/resource/callbacks.rb.
integer response code. You generally only want to do this when new
information comes to light, requiring a modification of the response.
* Currently supports WEBrick. Other host servers are planned.
* Streaming/chunked response bodies are permitted as Enumerables or Procs.

## Problems/TODOs

* Streaming and range responses will be supported as soon as API is
decided on.
* Support streamed responses as Fibers.
* Configuration, command-line tools, and general polish.
* An effort has been made to make the code feel as Ruby-ish as
possible, but there is still work to do.
Expand Down
19 changes: 19 additions & 0 deletions examples/webrick.rb
@@ -0,0 +1,19 @@
require 'webmachine'

class HelloResource < Webmachine::Resource
def last_modified
File.mtime(__FILE__)
end

def encodings_provided
{ "gzip" => :encode_gzip, "identity" => :encode_identity }
end

def to_html
"<html><head><title>Hello from Webmachine</title></head><body>Hello, world!</body></html>"
end
end

Webmachine::Dispatcher.add_route([], HelloResource)

Webmachine.run
5 changes: 5 additions & 0 deletions lib/webmachine.rb
Expand Up @@ -4,11 +4,16 @@
require 'webmachine/errors'
require 'webmachine/decision'
require 'webmachine/streaming'
require 'webmachine/adapters'
require 'webmachine/dispatcher'
require 'webmachine/resource'
require 'webmachine/version'

# Webmachine is a toolkit for making well-behaved HTTP applications.
# It is based on the Erlang library of the same name.
module Webmachine
# Starts Webmachine serving requests
def self.run
Adapters.const_get(adapter).run
end
end
15 changes: 15 additions & 0 deletions lib/webmachine/adapters.rb
@@ -0,0 +1,15 @@
require 'webmachine/adapters/webrick'

module Webmachine
# Contains classes and modules that connect Webmachine to Ruby
# application servers.
module Adapters
end

class << self
# @return [Symbol] the current webserver adapter
attr_accessor :adapter
end

self.adapter = :WEBrick
end
74 changes: 74 additions & 0 deletions lib/webmachine/adapters/webrick.rb
@@ -0,0 +1,74 @@
require 'webrick'
require 'webmachine/version'
require 'webmachine/headers'
require 'webmachine/request'
require 'webmachine/response'
require 'webmachine/dispatcher'

module Webmachine
module Adapters
# Connects Webmachine to WEBrick.
module WEBrick
# Starts the WEBrick adapter
def self.run
server = Webmachine::Adapters::WEBrick::Server.new :Port => 3000
trap("INT"){ server.shutdown }
Thread.new { server.start }.join
end

class Server < ::WEBrick::HTTPServer
def service(wreq, wres)
header = Webmachine::Headers.new
wreq.each {|k,v| header[k] = v }
request = Webmachine::Request.new(wreq.request_method,
wreq.request_uri,
header,
RequestBody.new(wreq))
response = Webmachine::Response.new
Webmachine::Dispatcher.dispatch(request, response)
wres.status = response.code.to_i
response.headers.each do |k,v|
wres[k] = v
end
wres['Server'] = [Webmachine::SERVER_STRING, wres.config[:ServerSoftware]].join(" ")
case response.body
when String
wres.body << response.body
when Enumerable
response.body.each {|part| wres.body << part }
when response.body.respond_to?(:call)
wres.body << response.body.call
end
end
end

# Wraps the WEBrick request body so that it can be passed to
# {Request} while still lazily evaluating the body.
class RequestBody
def initialize(request)
@request = request
end

# Converts the body to a String so you can work with the entire
# thing.
def to_s
@value ? @value.join : @request.body
end

# Iterates over the body in chunks. If the body has previously
# been read, this method can be called again and get the same
# sequence of chunks.
# @yield [chunk]
# @yieldparam [String] chunk a chunk of the request body
def each
if @value
@value.each {|chunk| yield chunk }
else
@value = []
@request.body {|chunk| @value << chunk; yield chunk }
end
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/webmachine/version.rb
@@ -1,4 +1,4 @@
module Webmachine
VERSION = "0.1.0"
SERVER_STRING = "Webmachine.rb/#{VERSION}"
SERVER_STRING = "Webmachine-Ruby/#{VERSION}"
end
61 changes: 0 additions & 61 deletions lib/webmachine/webrick.rb

This file was deleted.

0 comments on commit 11051db

Please sign in to comment.