Total Pageviews

Wednesday, 18 December 2013

"python -m SimpleHTTPServer"的ruby版

Python 2.* 的做法是python -m SimpleHTTPServer
Python 3.* 的做法是python -m http.server

Ruby的做法也非常简单。
2步搞定:

1. 安装rack,并新建rack配置文件config.ru:



1
2
gem install rack
echo "run Rack::Directory.new('')" > ~/config.ru

2. 切换到任意目录运行



1
rackup ~/config.ru
如果觉得命令长就建立alias alias rp='rackup ~/config.ru'
默认启动的server端口是9292,-p [port_num]可以修改端口号,打开浏览器即可当前目录的文件列表: http://locahost:9292/

Appendix: rack and rackup

Rack:

Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.

Rackup:

Rackup is a useful tool for running Rack applications, which uses the Rack::Builder DSL to configure middleware and build up applications easily.


https://github.com/rack/rack
-------------------------------------------
 ruby's "python -m SimpleHTTPServer"

If I remembered right, the command below used to be the most voted one on commandlinefu.com:
$ python -m SimpleHTTPServer
the “SimpleHTTPServer” module is written in python and it maybe called “the python way”, but that’s not our topic today. what we really want to do here is just making a ruby equivalent for this popular command, using rack.
first, make sure you have rack gem installed on your system (if you’ve installed rails 2.x before, you may already have it):
$ sudo gem install rack
confirm installation (Rack 1.0 should also work for our example):
$ rackup --version
Rack 1.1
alright, preparation is done, let’s start cooking. only a rackup file will be sufficient, for consistency, let’s just call it simple_http_server.ru .
#!/usr/bin/env rackup
#\ -E deployment

use Rack::ContentLength

app = Rack::Directory.new Dir.pwd
run app

Rack::Directory is so awesome that we just simply rely on it… aren’t i cheating? hehe, maybe…
ok, we’re done. to test it, simply run:
$ rackup simple_http_server.ru
and then point your browser to http://locahost:9292/ .

to be useful for daily use, you may consider chmod +x it to make it executable and put it in your $PATH.
$ chmod +x simple_http_server.ru
$ export PATH=$PATH:`pwd`
to share a directory with your coworkers or friends, simply cd to that directory and execute the script:
$ cd /the/dir/i/want/to/share
$ simple_http_server.ru
since we’re actually using rackup to execute, all the rackup options are also available, which is good:
$ simple_http_server.ru -h
finally, let’s end up with emulating python SimpleHTTPServer’s default behavior:
$ simple_http_server.ru -p 8000
---------------------------------------------

rackup -b “run Rack::Directory.new
----------------------------------------------

Or without Rack:
ruby -run -e httpd . -p 5000


Ruby's Simple HTTP Server

I use a really simple HTTP server all the time. It happens to be written in Python:
python -m SimpleHTTPServer 5000
That serves all the files in the current directory over HTTP on port 5000. Honestly, it works just fine, but I’ve always wondered if Ruby had an equivalent.
Here it is:
ruby -run -e httpd . -p 5000
(from Aaron Patterson’s tweet found via Zach Morek)
It’s pretty much the same, except it’s written in Ruby. More often than not, that’s not a big difference — except I can understand the code behind it.
#
# = un.rb
#
# Copyright (c) 2003 WATANABE Hirofumi <eban@ruby-lang.org>
#
# This program is free software.
# You can distribute/modify this program under the same terms of Ruby.

# [...]

##
# Run WEBrick HTTP server.
#
# ruby -run -e httpd -- [OPTION] DocumentRoot
#
# --bind-address=ADDR address to bind
# --port=NUM listening port number
# --max-clients=MAX max number of simultaneous clients
# --temp-dir=DIR temporary directory
# --do-not-reverse-lookup disable reverse lookup
# --request-timeout=SECOND request timeout in seconds
# --http-version=VERSION HTTP version
# -v verbose
#

def httpd
  setup("", "BindAddress=ADDR", "Port=PORT", "MaxClients=NUM", "TempDir=DIR",
        "DoNotReverseLookup", "RequestTimeout=SECOND", "HTTPVersion=VERSION") do
    |argv, options|
    require 'webrick'
    opt = options[:RequestTimeout] and options[:RequestTimeout] = opt.to_i
    [:Port, :MaxClients].each do |name|
      opt = options[name] and (options[name] = Integer(opt)) rescue nil
    end
    unless argv.size == 1
      raise ArgumentError, "DocumentRoot is mandatory"
    end
    options[:DocumentRoot] = argv.shift
    s = WEBrick::HTTPServer.new(options)
    shut = proc {s.shutdown}
    siglist = %w"TERM QUIT"
    siglist.concat(%w"HUP INT") if STDIN.tty?
    siglist &= Signal.list.keys
    siglist.each do |sig|
      Signal.trap(sig, shut)
    end
    s.start
  end
end
So how does it work? It’s actually a little surprising. Here’s the command again for reference:
ruby -run -e httpd . -p 5000
In order:
  • Obviously, ruby is the normal Ruby interpreter.
  • The -r switch requires a file in the load path, in this case Ruby’s lib directory. In this case, it’s loading a file called un.rb so that it looks like -run when taken as a whole. (It could be written as -r un as well.) This is similar to ubygems.rb which you may have seen as ruby -rubygems. That seems like an ugly solution, but it’s elegant in its own way. This naming hack is only really an option for files in Ruby itself, anyway.
  • As you can see above, httpd is just a method, which is executed by -e.
  • The DocumentRoot argument . is just taken as a standard argument using ARGV, which I found surprising.
  • Finally, the port is set using the setup method, which in turn calls out to the built in OptionParser.
While that code is probably too clever, it’s nice to have a simple HTTP server wherever I have Ruby.
Even more, the concept is reusable:
# File: ake.rb
# Minimalist rake.  :)
def greet
  puts "Hello, #{ ARGV[0] }!"
end
Here’s the output
$ ruby -I . -rake -e greet Ben
Hello, Ben!
$ ruby -r ./ake -e greet Ben
Hello, Ben!
That could be a nice minimalist way to write some helper scripts without Rake or Thor.

from http://www.benjaminoakes.com/2013/09/13/ruby-simple-http-server-minimalist-rake/