ferver 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +78 -0
- data/Rakefile +8 -0
- data/bin/ferver +11 -0
- data/ferver.gemspec +32 -0
- data/lib/ferver.rb +5 -0
- data/lib/ferver/app.rb +137 -0
- data/lib/ferver/file_list.rb +74 -0
- data/lib/ferver/version.rb +3 -0
- data/run.rb +21 -0
- data/spec/ferver_spec.rb +211 -0
- data/spec/file_list_spec.rb +147 -0
- data/spec/spec_helper.rb +39 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 137fd53d644093579a6fd6c6dae744d54e6bf9b0
|
4
|
+
data.tar.gz: 588b0d87f456072b9d577f766c4cd623de59487b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7833e07900143a2ee6bb1ebbf007fe744a5ab814082dc93b2a9b0ed9840c7f184b7a36891d5b73d6a882107a43e1bcf917d0d5cf0f2c3be7e8ce154705bc03fd
|
7
|
+
data.tar.gz: 3b79d0e6fed0e1913fc084d4d0ae6c29c5539e52a73ef3de62a01802533b0227c2849ceef016c64a805e0dbd48105ab5e519922b530981f6e79ddc4144819d94
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Rob Murray
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
## Ferver = File-Server
|
2
|
+
|
3
|
+
#### Ferver: A simple web app to server files over HTTP packaged as a Ruby gem.
|
4
|
+
|
5
|
+
[](https://travis-ci.org/rob-murray/ferver) [](https://codeclimate.com/github/rob-murray/ferver) [](https://coveralls.io/r/rob-murray/ferver) [](https://gemnasium.com/rob-murray/ferver)
|
6
|
+
|
7
|
+
### Description
|
8
|
+
|
9
|
+
This is super, simple ruby gem to serve files over **http**, useful as a basic file server to quickly share files on your local network or something. Just install the gem and go!
|
10
|
+
|
11
|
+
Here's the spec for **ferver**:
|
12
|
+
|
13
|
+
* available over http
|
14
|
+
* provide a list of files as html and json
|
15
|
+
* ignore directories
|
16
|
+
* serve files as individual files
|
17
|
+
* minimal config
|
18
|
+
* able to specify the directory to serve files from
|
19
|
+
|
20
|
+
### Getting started
|
21
|
+
|
22
|
+
Using **ferver** could not be simpler;
|
23
|
+
|
24
|
+
Install the **ferver** gem
|
25
|
+
|
26
|
+
```bash
|
27
|
+
$ gem install ferver
|
28
|
+
```
|
29
|
+
|
30
|
+
### Usage
|
31
|
+
|
32
|
+
You can run **ferver** from any directory, just pass in the directory you want to serve files from or if leave blank to use the current directory.
|
33
|
+
|
34
|
+
##### Use the current directory
|
35
|
+
|
36
|
+
```bash
|
37
|
+
$ ferver
|
38
|
+
````
|
39
|
+
|
40
|
+
##### Use a specific directory
|
41
|
+
|
42
|
+
For exmple, to serve files from **/Users/rob/Projects/ferver/** directory pass the path in as below;
|
43
|
+
|
44
|
+
```bash
|
45
|
+
# Serve files from a specific directory
|
46
|
+
$ ferver /Users/rob/Projects/ferver/
|
47
|
+
````
|
48
|
+
|
49
|
+
### Accessing files
|
50
|
+
|
51
|
+
The **ferver** gem uses [Sinatra](http://www.sinatrarb.com/) and runs on default port configuration so just point your browser to `http://localhost:4567` to list the files.
|
52
|
+
|
53
|
+
#### HTML
|
54
|
+
|
55
|
+
`http://localhost:4567/files` - List available files
|
56
|
+
|
57
|
+
#### JSON
|
58
|
+
|
59
|
+
Passing the header `Accept: application/json` will return the list of files as json.
|
60
|
+
|
61
|
+
```bash
|
62
|
+
curl -i -H "Accept: application/json" http://localhost:4567/files
|
63
|
+
```
|
64
|
+
|
65
|
+
#### Download a file
|
66
|
+
|
67
|
+
Files are available via their index in the list, e.g. `http://localhost:4567/files/:id`
|
68
|
+
|
69
|
+
For example to download file appearing third in the list displayed earlier, request `http://localhost:4567/files/2`
|
70
|
+
|
71
|
+
### Contributions
|
72
|
+
|
73
|
+
Please use the GitHub pull-request mechanism to submit contributions.
|
74
|
+
|
75
|
+
### License
|
76
|
+
|
77
|
+
This project is available for use under the MIT software license.
|
78
|
+
See LICENSE
|
data/Rakefile
ADDED
data/bin/ferver
ADDED
data/ferver.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'ferver/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "ferver"
|
8
|
+
spec.version = Ferver::VERSION
|
9
|
+
spec.authors = ["Rob Murray"]
|
10
|
+
spec.email = ["robmurray17@gmail.com"]
|
11
|
+
spec.summary = %q{A simple web app to serve files over HTTP.}
|
12
|
+
spec.description = %q{Ferver is a super, simple ruby gem to serve files over http; useful as a basic file server to quickly share files on your local network.}
|
13
|
+
spec.homepage = "https://github.com/rob-murray/ferver"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
23
|
+
spec.add_development_dependency "rake", "~> 0"
|
24
|
+
spec.add_development_dependency "rspec", "~> 2.14.1"
|
25
|
+
spec.add_development_dependency "rack-test", "~> 0.6.2"
|
26
|
+
spec.add_development_dependency "mocha", "~> 1.0.0"
|
27
|
+
spec.add_development_dependency "spork", "~> 0.9.2"
|
28
|
+
spec.add_development_dependency "webrat", "~> 0.7.3"
|
29
|
+
spec.add_development_dependency "coveralls", "~> 0.7.0"
|
30
|
+
|
31
|
+
spec.add_dependency "sinatra", "~> 1.4.4"
|
32
|
+
end
|
data/lib/ferver.rb
ADDED
data/lib/ferver/app.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require "sinatra"
|
2
|
+
require "json"
|
3
|
+
require "sinatra/base"
|
4
|
+
require "ferver/file_list"
|
5
|
+
|
6
|
+
module Ferver
|
7
|
+
class App < Sinatra::Base
|
8
|
+
|
9
|
+
# Config
|
10
|
+
set :inline_templates, true
|
11
|
+
set :app_file, __FILE__
|
12
|
+
|
13
|
+
# By default, serve files from current location when the gem
|
14
|
+
# binary is called.
|
15
|
+
DEFAULT_FILE_SERVER_DIR_PATH = './'
|
16
|
+
|
17
|
+
# redirect to file list
|
18
|
+
# /
|
19
|
+
get '/' do
|
20
|
+
|
21
|
+
redirect to('/files')
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# list files; repond as html or json
|
27
|
+
# /files
|
28
|
+
get '/files' do
|
29
|
+
|
30
|
+
file_list = @ferver_list.files
|
31
|
+
|
32
|
+
if request.preferred_type.to_s == "application/json"
|
33
|
+
|
34
|
+
content_type :json
|
35
|
+
file_list.to_json
|
36
|
+
|
37
|
+
else
|
38
|
+
|
39
|
+
@file_count = @ferver_list.file_count
|
40
|
+
@ferver_path = File.expand_path(get_current_ferver_path)
|
41
|
+
@file_list = file_list
|
42
|
+
|
43
|
+
erb :file_list_view
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
# download file
|
51
|
+
# /files/:id
|
52
|
+
get '/files/:id' do
|
53
|
+
|
54
|
+
id = Integer(params[:id]) rescue halt(400, "Bad request")
|
55
|
+
|
56
|
+
if @ferver_list.file_id_is_valid?(id)
|
57
|
+
|
58
|
+
file_name = @ferver_list.file_by_id(id)
|
59
|
+
|
60
|
+
file = FileList.path_for_file(get_current_ferver_path, file_name)
|
61
|
+
|
62
|
+
send_file(file, :disposition => 'attachment', :filename => File.basename(file))
|
63
|
+
|
64
|
+
else
|
65
|
+
|
66
|
+
status 404
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
# Find all files in `Ferver` directory.
|
74
|
+
# !Called before each request
|
75
|
+
#
|
76
|
+
before do
|
77
|
+
|
78
|
+
@ferver_list = FileList.new(get_current_ferver_path)
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# Return the absolute path to the directory Ferver is serving files from.
|
85
|
+
# This can be specified in Sinatra configuration;
|
86
|
+
# i.e. `Ferver::App.set :ferver_path, ferver_path` or the default if nil
|
87
|
+
#
|
88
|
+
def get_current_ferver_path
|
89
|
+
|
90
|
+
@current_ferver_path ||= begin
|
91
|
+
path = nil
|
92
|
+
|
93
|
+
if settings.respond_to?(:ferver_path) and settings.ferver_path
|
94
|
+
path = settings.ferver_path
|
95
|
+
else
|
96
|
+
path = DEFAULT_FILE_SERVER_DIR_PATH
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
__END__
|
108
|
+
|
109
|
+
@@file_list_view
|
110
|
+
<!DOCTYPE html>
|
111
|
+
<html lang="en">
|
112
|
+
<head>
|
113
|
+
<meta charset="utf-8">
|
114
|
+
<title>File List · Ferver</title>
|
115
|
+
</head>
|
116
|
+
<body>
|
117
|
+
<h3>Files served:</h3>
|
118
|
+
<ul>
|
119
|
+
<% @file_list.each_with_index do |file_name, index| %>
|
120
|
+
|
121
|
+
<li><a href="/files/<%= index %>"><%= file_name %></a></li>
|
122
|
+
|
123
|
+
<% end %>
|
124
|
+
|
125
|
+
</ul>
|
126
|
+
|
127
|
+
<p><%= @file_count %> files served from: <%= @ferver_path %></p>
|
128
|
+
|
129
|
+
<hr>
|
130
|
+
|
131
|
+
<p>Served by <a href="https://github.com/rob-murray/ferver" title="Ferver: A simple Ruby app serving files over HTTP">Ferver</a> gem v<%= Ferver::VERSION %></p>
|
132
|
+
|
133
|
+
</body>
|
134
|
+
</html>
|
135
|
+
|
136
|
+
<html>
|
137
|
+
<body>
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# A representation of Ferver's file list
|
2
|
+
#
|
3
|
+
module Ferver
|
4
|
+
class FileList
|
5
|
+
|
6
|
+
# List of files
|
7
|
+
attr_reader :files
|
8
|
+
|
9
|
+
# create a new instance with a path
|
10
|
+
#
|
11
|
+
def initialize(path)
|
12
|
+
|
13
|
+
raise ArgumentError, "No path is specified" if path.empty?
|
14
|
+
|
15
|
+
@file_path = File.expand_path(path)
|
16
|
+
|
17
|
+
find_files
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
# Return an absolute path to a `file_name` in the `directory`
|
22
|
+
#
|
23
|
+
def self.path_for_file(directory, file_name)
|
24
|
+
|
25
|
+
File.join(directory, file_name)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
# Is the file id a valid id for Ferver to serve
|
30
|
+
#
|
31
|
+
def file_id_is_valid?(file_id)
|
32
|
+
|
33
|
+
file_id < @files.size
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
# Filename by its index
|
38
|
+
#
|
39
|
+
def file_by_id(id)
|
40
|
+
|
41
|
+
@files.fetch(id)
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# Number of files in list
|
46
|
+
#
|
47
|
+
def file_count
|
48
|
+
|
49
|
+
@files.size
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
# Iterate through files in specified dir for files
|
56
|
+
#
|
57
|
+
def find_files
|
58
|
+
|
59
|
+
@files = []
|
60
|
+
|
61
|
+
Dir.foreach(@file_path) do |file|
|
62
|
+
|
63
|
+
next if file == '.' or file == '..'
|
64
|
+
|
65
|
+
file_path = FileList.path_for_file(@file_path, file)
|
66
|
+
|
67
|
+
@files << file if File.file?(file_path)
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
data/run.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
require 'ferver'
|
5
|
+
|
6
|
+
def main
|
7
|
+
|
8
|
+
# use the first argument as the file path to serve from
|
9
|
+
ferver_path = (ARGV.length == 1 && ARGV[0]) || nil
|
10
|
+
Ferver::App.set :ferver_path, ferver_path
|
11
|
+
|
12
|
+
# run!
|
13
|
+
Ferver::App.run!
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
if __FILE__ == $0
|
19
|
+
main()
|
20
|
+
end
|
21
|
+
|
data/spec/ferver_spec.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'ferver' do
|
4
|
+
include Webrat::Matchers # allow cool html matching
|
5
|
+
|
6
|
+
|
7
|
+
context "given a request to the server root" do
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
get '/'
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return redirect" do
|
14
|
+
expect(last_response).to be_redirect
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should redirect to file list" do
|
18
|
+
follow_redirect!
|
19
|
+
|
20
|
+
expect(last_response).to be_ok
|
21
|
+
expect(last_request.url).to match(/files/)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "choosing directory to serve files from" do
|
27
|
+
|
28
|
+
before {
|
29
|
+
@file_list = mock()
|
30
|
+
@file_list.stubs(:files).returns(EMPTY_FILE_LIST)
|
31
|
+
@file_list.stubs(:file_count).returns(0)
|
32
|
+
}
|
33
|
+
|
34
|
+
context "when no directory is specified" do
|
35
|
+
|
36
|
+
it "will use default directory" do
|
37
|
+
|
38
|
+
Ferver::FileList.expects(:new).with('./').returns(@file_list)
|
39
|
+
|
40
|
+
get '/files'
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when the directory passed via configuration" do
|
46
|
+
|
47
|
+
before { Ferver::App.set :ferver_path, '/foo' }
|
48
|
+
|
49
|
+
it "will use directory specified" do
|
50
|
+
Ferver::FileList.expects(:new).with('/foo').returns(@file_list)
|
51
|
+
|
52
|
+
get '/files'
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'given an empty list of files' do
|
60
|
+
|
61
|
+
before {
|
62
|
+
file_list = mock()
|
63
|
+
file_list.stubs(:files).returns(EMPTY_FILE_LIST)
|
64
|
+
file_list.stubs(:file_count).returns(0)
|
65
|
+
Ferver::FileList.stubs(:new).returns(file_list)
|
66
|
+
}
|
67
|
+
|
68
|
+
context "when no content-type is requested" do
|
69
|
+
|
70
|
+
before { get '/files' }
|
71
|
+
|
72
|
+
it "should return valid response" do
|
73
|
+
expect(last_response).to be_ok
|
74
|
+
#todo test html
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should contain no file list in response content" do
|
78
|
+
expect(last_response.body).to have_selector("li", :count => 0)
|
79
|
+
expect(last_response.body).to contain(/0 files/)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when json content-type is requested" do
|
85
|
+
|
86
|
+
before {
|
87
|
+
get '/files', {}, {"HTTP_ACCEPT" => "application/json" }
|
88
|
+
}
|
89
|
+
|
90
|
+
it "should return valid response" do
|
91
|
+
expect(last_response).to be_ok
|
92
|
+
expect(last_response.content_type).to include('application/json')
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should contain no file list in response content" do
|
96
|
+
list = JSON.parse last_response.body
|
97
|
+
expect(list).to eq(EMPTY_FILE_LIST)
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'given a list of files' do
|
105
|
+
|
106
|
+
before {
|
107
|
+
file_list = mock()
|
108
|
+
file_list.stubs(:files).returns(["file1", "file2"])
|
109
|
+
file_list.stubs(:file_count).returns(2)
|
110
|
+
Ferver::FileList.stubs(:new).returns(file_list)
|
111
|
+
}
|
112
|
+
|
113
|
+
context "when no content-type is requested" do
|
114
|
+
|
115
|
+
before { get '/files' }
|
116
|
+
|
117
|
+
it "should return valid response" do
|
118
|
+
expect(last_response).to be_ok
|
119
|
+
#todo test html
|
120
|
+
end
|
121
|
+
|
122
|
+
it "should contain no file list in response content" do
|
123
|
+
expect(last_response.body).to have_selector("li", :count => 2)
|
124
|
+
expect(last_response.body).to contain(/2 files/)
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should list filenames" do
|
128
|
+
expect(last_response.body).to have_selector("li") do |node|
|
129
|
+
|
130
|
+
expect(node.first).to have_selector("a", :content => "file1")
|
131
|
+
expect(node.last).to have_selector("a", :content => "file2")
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when json content-type is requested" do
|
139
|
+
|
140
|
+
before {
|
141
|
+
get '/files', {}, {"HTTP_ACCEPT" => "application/json" }
|
142
|
+
}
|
143
|
+
|
144
|
+
it "should return valid response" do
|
145
|
+
expect(last_response).to be_ok
|
146
|
+
expect(last_response.content_type).to include('application/json')
|
147
|
+
end
|
148
|
+
|
149
|
+
it "should contain no file list in response content" do
|
150
|
+
list = JSON.parse last_response.body
|
151
|
+
expect(list.count).to eq(2)
|
152
|
+
expect(list).to match_array(["file1", "file2"])
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
describe "downloading a file" do
|
161
|
+
|
162
|
+
before {
|
163
|
+
@file_list = mock()
|
164
|
+
@file_list.stubs(:files).returns(["file1", "file2"])
|
165
|
+
@file_list.stubs(:file_count).returns(2)
|
166
|
+
Ferver::FileList.stubs(:new).returns(@file_list)
|
167
|
+
}
|
168
|
+
|
169
|
+
context "when requesting a file out of range" do
|
170
|
+
|
171
|
+
before {
|
172
|
+
@file_list.expects(:file_id_is_valid?).with(3).returns(false)
|
173
|
+
get '/files/3'
|
174
|
+
}
|
175
|
+
|
176
|
+
it "should return not_found" do
|
177
|
+
expect(last_response).to be_not_found
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when requesting invalid file id" do
|
183
|
+
|
184
|
+
before {
|
185
|
+
@file_list.expects(:file_id_is_valid?).never
|
186
|
+
get '/files/foo'
|
187
|
+
}
|
188
|
+
|
189
|
+
it "should return not_found" do
|
190
|
+
expect(last_response).to be_bad_request
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
context "when requesting a valid file id" do
|
196
|
+
|
197
|
+
before { get '/files/0' }
|
198
|
+
|
199
|
+
xit "should return ok response" do
|
200
|
+
expect(last_response).to be_ok
|
201
|
+
end
|
202
|
+
|
203
|
+
xit "should return octet-stream content-type" do
|
204
|
+
expect(last_response.headers['Content-Type']).to eq("application/octet-stream")
|
205
|
+
end
|
206
|
+
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ferver::FileList do
|
4
|
+
|
5
|
+
describe "creating instance" do
|
6
|
+
|
7
|
+
context "when empty path argument is passed" do
|
8
|
+
|
9
|
+
it "should raise exception if no argument passed" do
|
10
|
+
expect { Ferver::FileList.new }.to raise_error(ArgumentError)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
|
15
|
+
context "when path argument is passed" do
|
16
|
+
|
17
|
+
let(:path) { '/foo' }
|
18
|
+
|
19
|
+
it "should find files in path argument" do
|
20
|
+
Dir.expects(:foreach).with(path).returns(EMPTY_FILE_LIST)
|
21
|
+
Ferver::FileList.new(path)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when path directory is empty" do
|
29
|
+
|
30
|
+
let(:file_list) { Ferver::FileList.new('/foo') }
|
31
|
+
|
32
|
+
before { Dir.stubs(:foreach).returns(EMPTY_FILE_LIST) }
|
33
|
+
|
34
|
+
it "should have zero #file_count" do
|
35
|
+
expect(file_list.file_count).to eq(0)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return empty array of files" do
|
39
|
+
expect(file_list.files).to eq(EMPTY_FILE_LIST)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when path directory contains current working dir and parent" do
|
45
|
+
|
46
|
+
let(:file_list) { Ferver::FileList.new('/foo') }
|
47
|
+
|
48
|
+
before(:each) do
|
49
|
+
Dir.stubs(:foreach).multiple_yields(".", "..", "file1")
|
50
|
+
File.stubs(:file?).returns(true)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should not count current working dir and parent" do
|
54
|
+
expect(file_list.file_count).to eq(1)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should not include current working dir and parent" do
|
58
|
+
expect(file_list.files).to eq(["file1"])
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when path directory contains file and directory" do
|
64
|
+
|
65
|
+
let(:file_list) { Ferver::FileList.new('/foo') }
|
66
|
+
|
67
|
+
before(:each) do
|
68
|
+
Dir.stubs(:foreach).multiple_yields("file1", "a_directory")
|
69
|
+
File.expects(:file?).at_most(2).returns(true, false)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should not count the directory" do
|
73
|
+
expect(file_list.file_count).to eq(1)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not include the directory" do
|
77
|
+
expect(file_list.files).to eq(["file1"])
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
context "when path directory contains valid files" do
|
83
|
+
|
84
|
+
let(:file_list) { Ferver::FileList.new('/foo') }
|
85
|
+
|
86
|
+
before {
|
87
|
+
Dir.stubs(:foreach).multiple_yields("file1", "file2")
|
88
|
+
File.stubs(:file?).returns(true)
|
89
|
+
}
|
90
|
+
|
91
|
+
it "should count all files" do
|
92
|
+
expect(file_list.file_count).to eq(2)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should list all files" do
|
96
|
+
expect(file_list.files).to eq(["file1", "file2"])
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
describe "requesting files" do
|
102
|
+
|
103
|
+
let(:file_list) { Ferver::FileList.new('/foo') }
|
104
|
+
|
105
|
+
before {
|
106
|
+
Dir.stubs(:foreach).multiple_yields("file1", "file2")
|
107
|
+
File.stubs(:file?).returns(true)
|
108
|
+
}
|
109
|
+
|
110
|
+
context "when requesting valid file_id" do
|
111
|
+
|
112
|
+
#todo: poss to redesign this
|
113
|
+
|
114
|
+
it "#file_id_is_valid? should return true for first file" do
|
115
|
+
file_list.file_id_is_valid?(0).should be_true
|
116
|
+
end
|
117
|
+
|
118
|
+
it "#file_id_is_valid? should return true for second file" do
|
119
|
+
file_list.file_id_is_valid?(1).should be_true
|
120
|
+
end
|
121
|
+
|
122
|
+
it "#file_by_id should return the correct file for the first file" do
|
123
|
+
expect(file_list.file_by_id(0)).to eq("file1")
|
124
|
+
end
|
125
|
+
|
126
|
+
it "#file_by_id should return the correct file for the second file" do
|
127
|
+
expect(file_list.file_by_id(1)).to eq("file2")
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
context "when requesting invalid file_id" do
|
133
|
+
|
134
|
+
it "should return false for invalid file_id" do
|
135
|
+
file_list.file_id_is_valid?(2).should be_false
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should raise_error if file_by_id is called" do
|
139
|
+
expect { file_list.file_by_id(2) }.to raise_error(IndexError)
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
|
147
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spork'
|
3
|
+
require 'coveralls'
|
4
|
+
|
5
|
+
# force the environment to 'test'
|
6
|
+
ENV['RACK_ENV'] = 'test'
|
7
|
+
|
8
|
+
Coveralls.wear! # this uses SimpleCov under its bonnet
|
9
|
+
|
10
|
+
Spork.prefork do
|
11
|
+
require File.join(File.dirname(__FILE__), '..', '/lib/', 'ferver', 'file_list')
|
12
|
+
require 'ferver'
|
13
|
+
|
14
|
+
require 'rubygems'
|
15
|
+
require 'sinatra'
|
16
|
+
require 'rspec'
|
17
|
+
require 'rack/test'
|
18
|
+
require 'webrat'
|
19
|
+
|
20
|
+
# test environment stuff
|
21
|
+
set :environment, :testf
|
22
|
+
set :run, false
|
23
|
+
set :raise_errors, true
|
24
|
+
set :logging, false
|
25
|
+
|
26
|
+
EMPTY_FILE_LIST = []
|
27
|
+
|
28
|
+
RSpec.configure do |conf|
|
29
|
+
conf.include Rack::Test::Methods
|
30
|
+
conf.mock_framework = :mocha
|
31
|
+
end
|
32
|
+
|
33
|
+
def app
|
34
|
+
@app ||= Ferver::App
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Spork.each_run do
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ferver
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rob Murray
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-03-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.1
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.1
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack-test
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.6.2
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.6.2
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: mocha
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: spork
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 0.9.2
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ~>
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 0.9.2
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: webrat
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ~>
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 0.7.3
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ~>
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 0.7.3
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: coveralls
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ~>
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.7.0
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ~>
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.7.0
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sinatra
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ~>
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 1.4.4
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ~>
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 1.4.4
|
139
|
+
description: Ferver is a super, simple ruby gem to serve files over http; useful as
|
140
|
+
a basic file server to quickly share files on your local network.
|
141
|
+
email:
|
142
|
+
- robmurray17@gmail.com
|
143
|
+
executables:
|
144
|
+
- ferver
|
145
|
+
extensions: []
|
146
|
+
extra_rdoc_files: []
|
147
|
+
files:
|
148
|
+
- .gitignore
|
149
|
+
- .rspec
|
150
|
+
- .ruby-version
|
151
|
+
- .travis.yml
|
152
|
+
- Gemfile
|
153
|
+
- LICENSE
|
154
|
+
- README.md
|
155
|
+
- Rakefile
|
156
|
+
- bin/ferver
|
157
|
+
- ferver.gemspec
|
158
|
+
- lib/ferver.rb
|
159
|
+
- lib/ferver/app.rb
|
160
|
+
- lib/ferver/file_list.rb
|
161
|
+
- lib/ferver/version.rb
|
162
|
+
- run.rb
|
163
|
+
- spec/ferver_spec.rb
|
164
|
+
- spec/file_list_spec.rb
|
165
|
+
- spec/spec_helper.rb
|
166
|
+
homepage: https://github.com/rob-murray/ferver
|
167
|
+
licenses:
|
168
|
+
- MIT
|
169
|
+
metadata: {}
|
170
|
+
post_install_message:
|
171
|
+
rdoc_options: []
|
172
|
+
require_paths:
|
173
|
+
- lib
|
174
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
175
|
+
requirements:
|
176
|
+
- - '>='
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: '0'
|
179
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - '>='
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
requirements: []
|
185
|
+
rubyforge_project:
|
186
|
+
rubygems_version: 2.2.2
|
187
|
+
signing_key:
|
188
|
+
specification_version: 4
|
189
|
+
summary: A simple web app to serve files over HTTP.
|
190
|
+
test_files:
|
191
|
+
- spec/ferver_spec.rb
|
192
|
+
- spec/file_list_spec.rb
|
193
|
+
- spec/spec_helper.rb
|