adsf-1.2.1/000077500000000000000000000000001267157276000124455ustar00rootroot00000000000000adsf-1.2.1/.travis.yml000066400000000000000000000003041267157276000145530ustar00rootroot00000000000000language: ruby rvm: - 2.1.2 - 2.2.2 - 2.3.0 - ruby-head branches: only: - "master" - "/^release-/" before_install: gem install bundler cache: bundler sudo: false git: depth: 1 adsf-1.2.1/ChangeLog000066400000000000000000000002741267157276000142220ustar00rootroot00000000000000For a list of all changes, please see the changelog on the project repository instead (http://projects.stoneship.org/hg/shared/adsf/shortlog). For release notes, please see the NEWS file. adsf-1.2.1/Gemfile000066400000000000000000000002321267157276000137350ustar00rootroot00000000000000source 'https://rubygems.org' gem 'rack' group :development do gem 'rake' end group :testing do gem 'mocha' gem 'rack-test' gem 'minitest' end adsf-1.2.1/LICENSE000066400000000000000000000020421267157276000134500ustar00rootroot00000000000000Copyright (c) 2009 Denis Defreyne Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. adsf-1.2.1/NEWS.md000066400000000000000000000005701267157276000135450ustar00rootroot00000000000000adsf News ========= 1.2.1 ----- * Fixed compatibility with Ruby 2.3.0 (#3) [Vipul Amler] 1.2.0 ----- * Add `--local-only` and `--listen-address` options (#1) [Ed Brannin] 1.1.1 ----- * Made SIGINT/SIGTERM cause proper exit 1.1.0 ----- * Added support for custom index filenames [Mark Meves] 1.0.1 ----- * Added runtime dependency on Rack 1.0 --- * Initial release adsf-1.2.1/README.md000066400000000000000000000050061267157276000137250ustar00rootroot00000000000000adsf ==== adsf (A Dead Simple Fileserver) is a tiny static file server that you can launch instantly in any directory, like this: ▸ ls -l total 0 drwxr-xr-x 2 ddfreyne staff 68 May 29 10:04 about drwxr-xr-x 2 ddfreyne staff 68 May 29 10:04 contact -rw-r--r-- 1 ddfreyne staff 0 May 29 10:04 index.html drwxr-xr-x 2 ddfreyne staff 68 May 29 10:04 projects ▸ adsf [2009-05-29 10:04:44] INFO WEBrick 1.3.1 [2009-05-29 10:04:44] INFO ruby 1.8.7 (2008-08-11) [i686-darwin9.6.1] [2009-05-29 10:04:44] INFO WEBrick::HTTPServer#start: pid=2757 port=3000 … and now you can go to http://localhost:3000/ and start browsing. You can specify a custom web root with `-r` or `--root`; the server will be started in that directory (e.g. `adsf -r public/`). If you want to specificy custom index filenames (other than the default `index.html`), you can use the `-i` or `--index-filename` option, which is a comma-separated list of filenames (e.g. `adsf -i index.html,index.xml`). adsf has one dependency, namely on Rack. It is licenced under the MIT license. Patches are always welcome; check my contact e-mail address at the bottom of this document. Using adsf programmatically --------------------------- You can use adsf programmatically in your Rack applications. [nanoc](http://nanoc.stoneship.org/) uses adsf for its “view” command, for example. adsf consists of one middleware class that finds index filenames, and rewrites these requests so that Rack::File can be used to serve these files. Here’s an example middleware/application stack that runs a web server with the "public/" directory as its web root: use Adsf::Rack::IndexFileFinder, :root => "public/" run Rack::File.new("public/") The `:root` option is required; it should contain the path to the web root. You can also specify an `:index_filenames` option, containing the names of the index filenames that will be served when a directory containing an index file is requested. Usually, this will simply be `[ 'index.html' ]`, but under different circumstances (when using IIS, for exmaple), the array may have to be modified to include index filenames such as `default.html` or `index.xml`. Here’s an example middleware/application stack that uses custom index filenames: use Adsf::Rack::IndexFileFinder, :root => "public/", :index_filenames => %w( index.html index.xhtml index.xml ) run Rack::File.new("public/") Contributors ------------ * Ed Brannin * Larissa Reis * Mark Meves Contact ------- You can reach me at . adsf-1.2.1/Rakefile000066400000000000000000000005361267157276000141160ustar00rootroot00000000000000# Load adsf $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/lib')) require 'adsf' desc 'Run all tests' task :test do $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) require 'minitest/autorun' MiniTest.autorun test_files = Dir["test/**/test_*.rb"] test_files.each { |f| require f } end task :default => :test adsf-1.2.1/adsf.gemspec000066400000000000000000000016021267157276000147260ustar00rootroot00000000000000# encoding: utf-8 $LOAD_PATH.unshift(File.expand_path('../lib/', __FILE__)) require 'adsf' Gem::Specification.new do |s| s.name = 'adsf' s.version = Adsf::VERSION s.platform = Gem::Platform::RUBY s.summary = 'a tiny static file server' s.description = 'A web server that can be spawned in any directory' s.homepage = 'http://github.com/ddfreyne/adsf/' s.license = 'MIT' s.author = 'Denis Defreyne' s.email = 'denis.defreyne@stoneship.org' s.required_ruby_version = '>= 1.8.5' s.add_runtime_dependency('rack', '>= 1.0.0') s.has_rdoc = false s.files = Dir['[A-Z]*'] + Dir['bin/**/*'] + Dir['lib/**/*'] s.executables = [ 'adsf' ] s.require_path = 'lib' s.bindir = 'bin' end adsf-1.2.1/bin/000077500000000000000000000000001267157276000132155ustar00rootroot00000000000000adsf-1.2.1/bin/adsf000077500000000000000000000036201267157276000140610ustar00rootroot00000000000000#!/usr/bin/env ruby $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) require 'rack' require 'optparse' require 'adsf' # Parse options options = { :handler => nil, :port => 3000, :index_filenames => %w( index.html ), :root => '.', :host => '0.0.0.0', } OptionParser.new do |opts| opts.banner = "Usage: adsf [options]" opts.separator '' opts.separator 'Specific options:' # handler opts.on('-H', '--handler [handler]', 'Specify the handler to use') do |o| options[:handler] = o end # help opts.on('-h', '--help', 'Display help') do |o| puts opts exit end # index filenames opts.on('-i', '--index-filenames [index-filenames]', 'Specify index filenames (comma-separated)') do |o| options[:index_filenames] = o.split(',') end # port opts.on('-p', '--port [port]', Integer, 'Specify the port number to use') do |o| options[:port] = o end # root opts.on('-r', '--root [root]', 'Specify the web root to use') do |o| options[:root] = o end # host opts.on('-l', '--local-only', 'Only listen to requests from localhost (short for "-a localhost")') do options[:host] = 'localhost' end # host opts.on('-a', '--listen-address [host]', 'Specify the address to listen to') do |o| options[:host] = o end end.parse! # Find handler handler = Rack::Handler.get(options[:handler]) if handler.nil? handler = Rack::Handler::WEBrick end # Create app app = Rack::Builder.new do use Rack::CommonLogger use Rack::ShowExceptions use Rack::Lint use Adsf::Rack::IndexFileFinder, :root => options[:root], :index_filenames => options[:index_filenames] run Rack::File.new(options[:root]) end.to_app # Be quittable %w( INT TERM ).each do |s| Signal.trap(s) { handler.shutdown } end # Run handler.run(app, :Port => options[:port], :Host => options[:host]) adsf-1.2.1/lib/000077500000000000000000000000001267157276000132135ustar00rootroot00000000000000adsf-1.2.1/lib/adsf.rb000066400000000000000000000000731267157276000144550ustar00rootroot00000000000000module Adsf VERSION = '1.2.1' end require 'adsf/rack' adsf-1.2.1/lib/adsf/000077500000000000000000000000001267157276000141305ustar00rootroot00000000000000adsf-1.2.1/lib/adsf/rack.rb000066400000000000000000000001151267157276000153720ustar00rootroot00000000000000module Adsf module Rack end end require 'adsf/rack/index_file_finder' adsf-1.2.1/lib/adsf/rack/000077500000000000000000000000001267157276000150505ustar00rootroot00000000000000adsf-1.2.1/lib/adsf/rack/index_file_finder.rb000066400000000000000000000022421267157276000210320ustar00rootroot00000000000000module Adsf::Rack class IndexFileFinder def initialize(app, options) @app = app @root = options[:root] or raise ArgumentError, ':root option is required but was not given' @index_filenames = options[:index_filenames] || [ 'index.html' ] end def call(env) # Get path path_info = ::Rack::Utils.unescape(env['PATH_INFO']) path = ::File.join(@root, path_info) # Redirect if necessary if ::File.directory?(path) && path_info !~ /\/$/ new_path_info = env['PATH_INFO'] + '/' return [ 302, { 'Location' => new_path_info, 'Content-Type' => 'text/html' }, [ "Redirecting you to #{new_path_info}…" ] ] end # Add index file if necessary new_env = env.dup if ::File.directory?(path) if index_filename = index_file_in(path) new_env['PATH_INFO'] = ::File.join(path_info, index_filename) end end # Pass on @app.call(new_env) end private def index_file_in(dir) @index_filenames.find do |index_filename| ::File.file?(::File.join(dir, index_filename)) end end end end adsf-1.2.1/sample/000077500000000000000000000000001267157276000137265ustar00rootroot00000000000000adsf-1.2.1/sample/index.html000066400000000000000000000010331267157276000157200ustar00rootroot00000000000000

It works! :D

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

And here's a very pretty image:

adsf-1.2.1/test/000077500000000000000000000000001267157276000134245ustar00rootroot00000000000000adsf-1.2.1/test/helper.rb000066400000000000000000000013151267157276000152300ustar00rootroot00000000000000# Load unit testing stuff begin require 'minitest/unit' require 'rack/test' require 'mocha/setup' rescue => e $stderr.puts "To run the tests, you need MiniTest, Mocha and Rack::Test." raise e end # Load adsf $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib')) require 'adsf' module Adsf::Test module Rack ; end end module Adsf::Test::Helpers def setup # Clean up GC.start # Go quiet $stdout = StringIO.new $stderr = StringIO.new # Enter tmp FileUtils.mkdir_p('tmp') FileUtils.cd('tmp') end def teardown # Exit tmp FileUtils.cd('..') FileUtils.rm_rf('tmp') # Go unquiet $stdout = STDOUT $stderr = STDERR end end adsf-1.2.1/test/rack/000077500000000000000000000000001267157276000143445ustar00rootroot00000000000000adsf-1.2.1/test/rack/test_index_file_finder.rb000066400000000000000000000047411267157276000213730ustar00rootroot00000000000000require 'test/helper' class Adsf::Test::Rack::IndexFileFinder < MiniTest::Test include Rack::Test::Methods include Adsf::Test::Helpers def app ::Adsf::Rack::IndexFileFinder.new( stub_app, (@options || {}).merge({ :root => '.' }) ) end def stub_app Rack::File.new('.') end def test_get_file # Create test file File.open('motto.txt', 'w') { |io| io.write('More human than human') } # Request test file get '/motto.txt' assert last_response.ok? assert_equal 'More human than human', last_response.body end def test_get_dir_without_index_file_without_slash # Create test directory FileUtils.mkdir('replicants') # Request test directory get '/replicants' assert last_response.redirect? assert_equal '/replicants/', last_response.location end def test_get_dir_without_index_file_with_slash # Create test directory FileUtils.mkdir('replicants') # Request test directory get '/replicants/' assert last_response.not_found? end def test_get_dir_with_index_file_without_slash # Create test directory FileUtils.mkdir('replicants') # Create test file File.open('replicants/index.txt', 'w') { |io| io.write('Leon, Roy, Pris, Zhora, etc.') } # Request test directory get '/replicants' assert last_response.redirect? assert_equal '/replicants/', last_response.location end def test_get_dir_with_index_file_with_slash # Create test directory FileUtils.mkdir('replicants') # Create test file File.open('replicants/index.html', 'w') { |io| io.write('Leon, Roy, Pris, Zhora, etc.') } # Request test directory get '/replicants/' assert last_response.ok? assert_equal 'Leon, Roy, Pris, Zhora, etc.', last_response.body end def test_get_dir_with_custom_index_file @options = { :index_filenames => [ 'list.xml' ] } # Create test directory FileUtils.mkdir('replicants') # Create test file File.open('replicants/list.xml', 'w') { |io| io.write('Leon, Roy, Pris, Zhora, etc.') } # Request test directory get '/replicants/' assert last_response.ok? assert_equal 'Leon, Roy, Pris, Zhora, etc.', last_response.body end def test_get_dir_without_slash_with_escaped_url # Create test directory FileUtils.mkdir('animal replicants') # Request test directory get '/animal%20replicants' assert last_response.redirect? assert_equal '/animal%20replicants/', last_response.location end end