Skip to content

Instantly share code, notes, and snippets.

@h0rs3r4dish
Created December 17, 2009 04:42
Show Gist options
  • Save h0rs3r4dish/258527 to your computer and use it in GitHub Desktop.
Save h0rs3r4dish/258527 to your computer and use it in GitHub Desktop.
HumaneBrick: WEBrick for sane people

HumaneBrick = some WEBrick + some sanity

It's hard to argue that WEBrick is good at documentation. So, there are other servers. But how many come built-in? None.

As a result, lot of my projects use WB. It's a pain in the ass. It's a very verbose and painful way to write code, especially when you're trying to test an idea that doesn't quite agree with WB's way of doing things.

That's when you need to assert yourself as a human, and write in English: server.path "/" do |name| if not posted? :name then write "You need to POST name!" else write "Hi there, %s" % name end end

Wouldn't that just be great? HumaneBrick does that. You can practically write in English, if you do things right. See the humane-examples.rb file at the end if you really want a treat. As for the code, it manages to hold itself at 80 lines of code, without any extra compression. Enjoy.

Meticulous documentation

Okay, maybe meticulous isn't the right word. But I digress.

  • Server#path(url, &block) This is the big one. Give it a URL and a block and let her rip. If you've got stuff POSTed to your page, then have at'em, in alphabetical order.

That's the real one you need to worry about. But if you're interested, there are a bunch of helpers out there.

If you're defining a page...

  • write(parse,text) drops the text into the browser's lap. Set parse to true if you want auto-paragraph/header wrappings, or just ignore it and have your words repeated verbatim.
  • redirect_to(url) sends the browser to the new location.
  • url hands you the path (ex, "/index.html")
  • posted?(varname) is kind of important, since it'll tell you whether or not a certain variable was POSTed
  • There are times you don't want to talk HTML (say, a JSON response). For that, to ahead and set @format to the desired value (see HB.Content_Types)

Fine, let's talk cookies while we're here too:

  • add_cookie(name,value) makes a new one
  • read_cookie(name) will give them back
  • If you feel like holding onto some cookies instead of passing them back to the browser, make sure to call do_not_save_cookies for good measure. Otherwise, they'll be saved & sent back.

There's another handy utility if you don't feel like writing it all in the current file: view(name) loads HUMANEDIR/views/name.@format, for either executing or writeing

But what about the other stuff?

If you really want to, you can add new content types with HB.content_type(hash) (for example, content_type :js => "text/javascript")

Nothing to see, really. Go back to writing fun code again.

require 'humane'
server = HB::Server.new # use "include HB" for even more fun
server.path "/" do # Hello world, HB style
write true, "h1. Hello, world!" # write() = puts() for the web; hx. = <hx></hx>
write true, "The URL you entered was '%s'" % url # Just pop that word in there and enjoy
end
server.path "/submit" do |name| # auto-magically gives you POST/GET-ed variables
if not posted? :name then # this could be "view 'index'", if you had views/index.html
write <<EOF
<form method="POST" action="/submit">
Enter your name: <input type='text' name='name' />
<input type='submit' />
</form>
EOF
else
write "Hi there %s!" % name # Don't you love cheerful webpages?
end
end
server.path "/cookie" do # Let's have some fun with these
if (c = read_cookie "grah") then
write "Cookie found."
write "Value: '%s'" % c # c = WEBrick::Cookie#value
else
write "Creating cookie." # Refresh the page to see the result if you get this
add_cookie "grah", "Hello, cookies!" # Nice and easy
end
end
server.path "/ajax" do # Who doesn't like AJAX sometimes?
@format = :json # XMLHttpRequest.new.open("GET") this and see for yourself
write "{ 'source': 'HumaneBrick' }"
end
server.start! # The exclamation point is because you just want it to work
#!/usr/bin/ruby
require 'webrick'
module HB
VERSION = "1.1"
class Server
def initialize(config={:Port => 8000})
@server = WEBrick::HTTPServer.new(config)
['INT','TERM'].each { |s| trap(s) { @server.shutdown; Process.exit } }
end
def path(str,&block)
str = '/'+str if str[0].chr != '/'
@server.mount_proc(str, HB.wrap_proc(&block))
end
def start!
@server.start
end
end
class Page
def write(p=false,*str)
if p.class == String then str = [p] + str; p = false; end
str.each { |line|
if p then
found = line =~ /^h(\d)\. (.+)/
line = "<h#{$1}>#{$2}</h#{$1}>" if found
line = "<p>#{line}</p>" if not found
end
@res.body << line+"\n"
}
end
def redirect_to(path)
@res.set_redirect(WEBrick::HTTPStatus::Found,path)
end
def posted?(name)
@req.query.key? name.to_s
end
def url
@req.path
end
def view(name)
IO.readlines("views/%s.%s" % [name, @format]).join
end
def add_cookie(name,value)
@res.cookies.push WEBrick::Cookie.new(name,value)
end
def read_cookie(name)
@req.cookies.each { |c| return c.value if c.name == name }
return false
end
def do_not_save_cookies
@ditch_cookies = true
end
def initialize(req, res, block)
@req = req; @res = res; @ditch_cookies = false
@format = (@req.path =~ /\.([^\.]+)$/) ? $1.to_s : :html
args = @req.query.keys.sort.map { |k| @req.query[k] } # POSTed vars
instance_exec args, &block
res["Content-type"] = Content_Types[@format]
@req.cookies.each { |c| @res.cookies << c } unless @ditch_cookies
end
end
Content_Types = {
:html => 'text/html', :json => 'text/json',
:xml => 'text/xml', :js => 'text/javascript'
}
def HB.content_type(values)
Content_Types.merge! values
end
def HB.wrap_proc(&block)
Proc.new { |req, res| Page.new(req,res,block) }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment