fsws 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f73f7d600ada971ab9a245db6619ec40b3561985
4
- data.tar.gz: 3f6fad23ce1215d98cd04ca1a2ffaa4e3b06a6eb
3
+ metadata.gz: 536cf5feffaefd138c6906d9ba6fec29076bc2ec
4
+ data.tar.gz: ba945954383e7e92d6742f7ba1d027363a47c26a
5
5
  SHA512:
6
- metadata.gz: 9b32d1e07442141fe549cdd2dbf72d77a034789d72f7258687289c711f4af97bf7dff6cc5d5ca45656639e8820f84677af11293d867c02cbaef0bccb49de2114
7
- data.tar.gz: e689250545a13671c6ad190088209d30acbcfaa785d86338121bbbe1fe911bd52f87259c0f60433a7f9f585382305fe88ee31e539b56ab60681749b47daca913
6
+ metadata.gz: 6925e5d61f2f5067deb603ab68279ee003ecfbd47b0f73e9a98d2472e1f52d3902904b9c457fa44aa4a6648f49e2bc3715eddafd4126ff419c1c76ba729daf2c
7
+ data.tar.gz: 898960b151928a1473fdd5075b6227c03f08579eb5eba6070ae18f51701e4f2dca79e50e3fe3fe03fc1cdf07b83bf8d2f38eed69ac5b214d6cd91a25d3284eae
data/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2014 Chris Schmich
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Chris Schmich
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,46 +1,50 @@
1
- # fsws
2
-
3
- A simple Ruby-based file system web server for serving static files from a directory on OSX, Windows, or Linux.
4
-
5
- It is intended for use in development for viewing statically-generated sites such as documentation (YARD), blogs (Jekyll), code coverage reports (SimpleCov), profiling reports, etc.
6
-
7
- <br>
8
- <div style="text-align:center" align="center">
9
- <img src="https://github.com/schmich/fsws/raw/master/assets/demo.gif" />
10
- </div>
11
- <br>
12
-
13
- Alternatives include `python -m SimpleHTTPServer`, nginx, and Apache.
14
-
15
- ## Usage
16
-
17
- Start a web server for files in the current directory:
18
-
19
- ```
20
- $ gem install fsws
21
- $ fsws
22
- ```
23
-
24
- Specify a port:
25
-
26
- ```
27
- $ fsws -p 777
28
- ```
29
-
30
- Allow external connections:
31
-
32
- ```
33
- $ fsws -h 0.0.0.0
34
- ```
35
-
36
- Serve files from another directory:
37
-
38
- ```
39
- $ fsws -d ../foo
40
- ```
41
-
42
- ## License
43
-
44
- Copyright &copy; 2014 Chris Schmich
45
- <br />
46
- MIT License. See [LICENSE](LICENSE) for details.
1
+ # fsws
2
+
3
+ A simple Ruby-based file system web server for serving static files from a directory on OSX, Windows, or Linux.
4
+
5
+ It is intended for use in development for viewing statically-generated sites such as documentation (YARD), blogs (Jekyll), code coverage reports (SimpleCov), profiling reports, etc.
6
+
7
+
8
+ [![Gem Version](https://badge.fury.io/rb/fsws.svg)](http://rubygems.org/gems/fsws)
9
+ [![Dependency Status](https://gemnasium.com/schmich/fsws.svg)](https://gemnasium.com/schmich/fsws)
10
+
11
+ <br>
12
+ <div style="text-align:center" align="center">
13
+ <img src="https://github.com/schmich/fsws/raw/master/assets/demo.gif" />
14
+ </div>
15
+ <br>
16
+
17
+ Alternatives include `python -m SimpleHTTPServer`, nginx, and Apache.
18
+
19
+ ## Usage
20
+
21
+ Start a web server for files in the current directory:
22
+
23
+ ```
24
+ $ gem install fsws
25
+ $ fsws
26
+ ```
27
+
28
+ Specify a port:
29
+
30
+ ```
31
+ $ fsws -p 777
32
+ ```
33
+
34
+ Allow external connections:
35
+
36
+ ```
37
+ $ fsws -i 0.0.0.0
38
+ ```
39
+
40
+ Serve files from another directory:
41
+
42
+ ```
43
+ $ fsws -d ../foo
44
+ ```
45
+
46
+ ## License
47
+
48
+ Copyright &copy; 2014 Chris Schmich
49
+ <br />
50
+ MIT License. See [LICENSE](LICENSE) for details.
data/bin/fsws CHANGED
@@ -1,6 +1,6 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'fsws'
4
- require 'fsws/cli'
5
-
6
- Fsws::CommandLine.start(ARGV)
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fsws'
4
+ require 'fsws/cli'
5
+
6
+ Fsws::CommandLine.start(ARGV)
data/lib/fsws/cli.rb CHANGED
@@ -1,84 +1,89 @@
1
- require 'rack'
2
- require 'webrick'
3
- require 'thor'
4
- require 'launchy'
5
-
6
- module Fsws
7
- class CommandLine < Thor
8
- desc '[-d <directory>] [-h <host>] [-p <port>] [-B]', 'Start server.'
9
- long_desc <<-DESC
10
- [-d|--dir <directory>] [-h|--host <host>] [-p|--port <port>] [-B|--no-browser]
11
- DESC
12
- option :port, type: :numeric, aliases: :p
13
- option :host, type: :string, aliases: :h
14
- option :dir, type: :string, aliases: :d
15
- option :'no-browser', type: :boolean, aliases: :B
16
- option :version, type: :boolean, aliases: :v
17
- def start
18
- if options[:version]
19
- version
20
- return
21
- end
22
-
23
- dir = options[:dir]
24
- browser = !options[:'no-browser']
25
- port = options[:port] || 9001
26
- interface = options[:host] || '127.0.0.1'
27
-
28
- if dir
29
- path = File.absolute_path(dir)
30
- if Dir.exist?(path)
31
- Dir.chdir(path)
32
- else
33
- $stderr.puts "Directory does not exist: #{normalize(path)}."
34
- exit 1
35
- end
36
- end
37
-
38
- if Signal.list.key? 'QUIT'
39
- Signal.trap('QUIT') do
40
- puts 'Stopping...'
41
- Rack::Handler::WEBrick.shutdown
42
- end
43
- end
44
-
45
- if Signal.list.key? 'INT'
46
- Signal.trap('INT') do
47
- puts 'Stopping...'
48
- Rack::Handler::WEBrick.shutdown
49
- end
50
- end
51
-
52
- puts ">> Serving #{normalize(Dir.pwd)}"
53
- puts ">> Listening on #{interface}:#{port}"
54
- puts ">> Ctrl+C to stop"
55
-
56
- rd, wr = IO.pipe
57
- opts = {
58
- BindAddress: interface,
59
- Port: port,
60
- Logger: WEBrick::Log.new(wr),
61
- AccessLog: []
62
- }
63
-
64
- Rack::Handler::WEBrick.run(Fsws::server, opts) do
65
- if browser
66
- Launchy.open("http://localhost:#{port}")
67
- end
68
- end
69
- end
70
-
71
- desc '-v|--version', 'Print version.'
72
- def version
73
- puts "fsws #{Fsws::VERSION}"
74
- end
75
-
76
- private
77
-
78
- def normalize(path)
79
- path.gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
80
- end
81
-
82
- default_task :start
83
- end
84
- end
1
+ require 'rack'
2
+ require 'webrick'
3
+ require 'thor'
4
+ require 'launchy'
5
+
6
+ module Fsws
7
+ class CommandLine < Thor
8
+ desc '[-d <directory>] [-i <interface>] [-p <port>] [-B]', 'Start server.'
9
+ long_desc <<-DESC
10
+ [-d|--dir <directory>] [-i|--interface <interface>] [-p|--port <port>] [-B|--no-browser]
11
+ DESC
12
+ option :port, type: :numeric, aliases: :p, default: 9001, lazy_default: 9001
13
+ option :interface, type: :string, aliases: :i, default: '127.0.0.1', lazy_default: '127.0.0.1'
14
+ option :dir, type: :string, aliases: :d
15
+ option :'no-browser', type: :boolean, aliases: :B
16
+ option :version, type: :boolean, aliases: :v
17
+ def start
18
+ if options[:version]
19
+ return version
20
+ end
21
+
22
+ puts "options = #{options}"
23
+
24
+ dir = options[:dir]
25
+ browser = !options[:'no-browser']
26
+ port = options[:port]
27
+ interface = options[:interface]
28
+
29
+ if interface == '*'
30
+ interface = '0.0.0.0'
31
+ end
32
+
33
+ if dir
34
+ path = File.absolute_path(dir)
35
+ if Dir.exist?(path)
36
+ Dir.chdir(path)
37
+ else
38
+ $stderr.puts "Directory does not exist: #{normalize(path)}."
39
+ exit 1
40
+ end
41
+ end
42
+
43
+ if Signal.list.key? 'QUIT'
44
+ Signal.trap('QUIT') do
45
+ puts 'Stopping...'
46
+ Rack::Handler::WEBrick.shutdown
47
+ end
48
+ end
49
+
50
+ if Signal.list.key? 'INT'
51
+ Signal.trap('INT') do
52
+ puts 'Stopping...'
53
+ Rack::Handler::WEBrick.shutdown
54
+ end
55
+ end
56
+
57
+ puts ">> Serving #{normalize(Dir.pwd)}"
58
+ puts ">> Listening on #{interface}:#{port}"
59
+ puts ">> Ctrl+C to stop"
60
+
61
+ rd, wr = IO.pipe
62
+ opts = {
63
+ BindAddress: interface,
64
+ Port: port,
65
+ Logger: WEBrick::Log.new(wr),
66
+ AccessLog: []
67
+ }
68
+
69
+ Rack::Handler::WEBrick.run(Fsws::server, opts) do
70
+ if browser
71
+ Launchy.open("http://localhost:#{port}")
72
+ end
73
+ end
74
+ end
75
+
76
+ desc '-v|--version', 'Print version.'
77
+ def version
78
+ puts "fsws #{Fsws::VERSION}"
79
+ end
80
+
81
+ private
82
+
83
+ def normalize(path)
84
+ path.gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
85
+ end
86
+
87
+ default_task :start
88
+ end
89
+ end
data/lib/fsws/mime.types CHANGED
@@ -1,110 +1,110 @@
1
- # From https://github.com/h5bp/server-configs-nginx/blob/master/mime.types
2
- types {
3
-
4
- # Audio
5
- audio/midi mid midi kar;
6
- audio/mp4 aac f4a f4b m4a;
7
- audio/mpeg mp3;
8
- audio/ogg oga ogg;
9
- audio/x-realaudio ra;
10
- audio/x-wav wav;
11
-
12
- # Images
13
- image/bmp bmp;
14
- image/gif gif;
15
- image/jpeg jpeg jpg;
16
- image/png png;
17
- image/tiff tif tiff;
18
- image/vnd.wap.wbmp wbmp;
19
- image/webp webp;
20
- image/x-icon ico cur;
21
- image/x-jng jng;
22
-
23
- # JavaScript
24
- application/javascript js;
25
- application/json json;
26
-
27
- # Manifest files
28
- application/x-web-app-manifest+json webapp;
29
- text/cache-manifest manifest appcache;
30
-
31
- # Microsoft Office
32
- application/msword doc;
33
- application/vnd.ms-excel xls;
34
- application/vnd.ms-powerpoint ppt;
35
- application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
36
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
37
- application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
38
-
39
- # Video
40
- video/3gpp 3gpp 3gp;
41
- video/mp4 mp4 m4v f4v f4p;
42
- video/mpeg mpeg mpg;
43
- video/ogg ogv;
44
- video/quicktime mov;
45
- video/webm webm;
46
- video/x-flv flv;
47
- video/x-mng mng;
48
- video/x-ms-asf asx asf;
49
- video/x-ms-wmv wmv;
50
- video/x-msvideo avi;
51
-
52
- # Web feeds
53
- application/xml atom rdf rss xml;
54
-
55
- # Web fonts
56
- application/font-woff woff;
57
- application/font-woff2 woff2;
58
- application/vnd.ms-fontobject eot;
59
- application/x-font-ttf ttc ttf;
60
- font/opentype otf;
61
- image/svg+xml svg svgz;
62
-
63
- # Other
64
- application/java-archive jar war ear;
65
- application/mac-binhex40 hqx;
66
- application/pdf pdf;
67
- application/postscript ps eps ai;
68
- application/rtf rtf;
69
- application/vnd.wap.wmlc wmlc;
70
- application/xhtml+xml xhtml;
71
- application/vnd.google-earth.kml+xml kml;
72
- application/vnd.google-earth.kmz kmz;
73
- application/x-7z-compressed 7z;
74
- application/x-chrome-extension crx;
75
- application/x-opera-extension oex;
76
- application/x-xpinstall xpi;
77
- application/x-cocoa cco;
78
- application/x-java-archive-diff jardiff;
79
- application/x-java-jnlp-file jnlp;
80
- application/x-makeself run;
81
- application/x-perl pl pm;
82
- application/x-pilot prc pdb;
83
- application/x-rar-compressed rar;
84
- application/x-redhat-package-manager rpm;
85
- application/x-sea sea;
86
- application/x-shockwave-flash swf;
87
- application/x-stuffit sit;
88
- application/x-tcl tcl tk;
89
- application/x-x509-ca-cert der pem crt;
90
- application/x-bittorrent torrent;
91
- application/zip zip;
92
-
93
- application/octet-stream bin exe dll;
94
- application/octet-stream deb;
95
- application/octet-stream dmg;
96
- application/octet-stream iso img;
97
- application/octet-stream msi msp msm;
98
- application/octet-stream safariextz;
99
-
100
- text/css css;
101
- text/html html htm shtml;
102
- text/mathml mml;
103
- text/plain txt;
104
- text/vnd.sun.j2me.app-descriptor jad;
105
- text/vnd.wap.wml wml;
106
- text/vtt vtt;
107
- text/x-component htc;
108
- text/x-vcard vcf;
109
-
110
- }
1
+ # From https://github.com/h5bp/server-configs-nginx/blob/master/mime.types
2
+ types {
3
+
4
+ # Audio
5
+ audio/midi mid midi kar;
6
+ audio/mp4 aac f4a f4b m4a;
7
+ audio/mpeg mp3;
8
+ audio/ogg oga ogg;
9
+ audio/x-realaudio ra;
10
+ audio/x-wav wav;
11
+
12
+ # Images
13
+ image/bmp bmp;
14
+ image/gif gif;
15
+ image/jpeg jpeg jpg;
16
+ image/png png;
17
+ image/tiff tif tiff;
18
+ image/vnd.wap.wbmp wbmp;
19
+ image/webp webp;
20
+ image/x-icon ico cur;
21
+ image/x-jng jng;
22
+
23
+ # JavaScript
24
+ application/javascript js;
25
+ application/json json;
26
+
27
+ # Manifest files
28
+ application/x-web-app-manifest+json webapp;
29
+ text/cache-manifest manifest appcache;
30
+
31
+ # Microsoft Office
32
+ application/msword doc;
33
+ application/vnd.ms-excel xls;
34
+ application/vnd.ms-powerpoint ppt;
35
+ application/vnd.openxmlformats-officedocument.wordprocessingml.document docx;
36
+ application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx;
37
+ application/vnd.openxmlformats-officedocument.presentationml.presentation pptx;
38
+
39
+ # Video
40
+ video/3gpp 3gpp 3gp;
41
+ video/mp4 mp4 m4v f4v f4p;
42
+ video/mpeg mpeg mpg;
43
+ video/ogg ogv;
44
+ video/quicktime mov;
45
+ video/webm webm;
46
+ video/x-flv flv;
47
+ video/x-mng mng;
48
+ video/x-ms-asf asx asf;
49
+ video/x-ms-wmv wmv;
50
+ video/x-msvideo avi;
51
+
52
+ # Web feeds
53
+ application/xml atom rdf rss xml;
54
+
55
+ # Web fonts
56
+ application/font-woff woff;
57
+ application/font-woff2 woff2;
58
+ application/vnd.ms-fontobject eot;
59
+ application/x-font-ttf ttc ttf;
60
+ font/opentype otf;
61
+ image/svg+xml svg svgz;
62
+
63
+ # Other
64
+ application/java-archive jar war ear;
65
+ application/mac-binhex40 hqx;
66
+ application/pdf pdf;
67
+ application/postscript ps eps ai;
68
+ application/rtf rtf;
69
+ application/vnd.wap.wmlc wmlc;
70
+ application/xhtml+xml xhtml;
71
+ application/vnd.google-earth.kml+xml kml;
72
+ application/vnd.google-earth.kmz kmz;
73
+ application/x-7z-compressed 7z;
74
+ application/x-chrome-extension crx;
75
+ application/x-opera-extension oex;
76
+ application/x-xpinstall xpi;
77
+ application/x-cocoa cco;
78
+ application/x-java-archive-diff jardiff;
79
+ application/x-java-jnlp-file jnlp;
80
+ application/x-makeself run;
81
+ application/x-perl pl pm;
82
+ application/x-pilot prc pdb;
83
+ application/x-rar-compressed rar;
84
+ application/x-redhat-package-manager rpm;
85
+ application/x-sea sea;
86
+ application/x-shockwave-flash swf;
87
+ application/x-stuffit sit;
88
+ application/x-tcl tcl tk;
89
+ application/x-x509-ca-cert der pem crt;
90
+ application/x-bittorrent torrent;
91
+ application/zip zip;
92
+
93
+ application/octet-stream bin exe dll;
94
+ application/octet-stream deb;
95
+ application/octet-stream dmg;
96
+ application/octet-stream iso img;
97
+ application/octet-stream msi msp msm;
98
+ application/octet-stream safariextz;
99
+
100
+ text/css css;
101
+ text/html html htm shtml;
102
+ text/mathml mml;
103
+ text/plain txt;
104
+ text/vnd.sun.j2me.app-descriptor jad;
105
+ text/vnd.wap.wml wml;
106
+ text/vtt vtt;
107
+ text/x-component htc;
108
+ text/x-vcard vcf;
109
+
110
+ }
data/lib/fsws/server.rb CHANGED
@@ -1,101 +1,101 @@
1
- require 'rack'
2
- require 'erb'
3
- require 'pathname'
4
- require 'ostruct'
5
-
6
- def mime_types
7
- return @mime_types if @mime_types
8
-
9
- @mime_types = {}
10
-
11
- path = File.join(File.dirname(__FILE__), 'mime.types')
12
- File.open(path, 'r') do |file|
13
- file.each_line do |line|
14
- if line =~ /^\s*([\w\/.-]+)\s*((\w+\s*)+);\s*$/
15
- mime_type = $1.strip
16
- extensions = $2.strip.split.map(&:strip).map(&:downcase)
17
- for ext in extensions
18
- @mime_types[ext] = mime_type.downcase
19
- end
20
- end
21
- end
22
- end
23
-
24
- @mime_types
25
- end
26
-
27
- def serve(env)
28
- path = env['REQUEST_PATH'] || ''
29
- path = '/' if path.empty?
30
- path = '.' + path
31
-
32
- return error(env) if !allowed?(path)
33
-
34
- return serve_file(path) || serve_dir(path) || error(env)
35
- end
36
-
37
- def serve_file(path)
38
- return nil if !File.file? path
39
-
40
- ext = File.extname(path)
41
- ext = ext[1...ext.length]
42
- mime_type = mime_types[ext] || 'text/plain'
43
-
44
- return 200, { 'Content-Type' => mime_type }, File.open(path, 'rb').read
45
- end
46
-
47
- def serve_dir(path)
48
- return nil if !File.directory? path
49
-
50
- for file in %w(index.html index.htm)
51
- index = File.join(path, file)
52
- page = serve_file(index)
53
- return page if page
54
- end
55
-
56
- return redirect(path + '/') if !path.end_with?('/')
57
-
58
- dirs, files = Dir.entries(path).partition { |e| File.directory?(File.join(path, e)) }
59
- dirs.delete('.')
60
- dirs.delete('..') if path == './'
61
- dirs.sort!
62
- files.sort!
63
-
64
- target_path = Pathname.new(File.absolute_path(path))
65
- current_path = Pathname.new(File.absolute_path(Dir.pwd))
66
- pwd = Pathname.new('/' + target_path.relative_path_from(current_path).to_s).cleanpath.to_s
67
- pwd += '/' if pwd[-1] != '/'
68
-
69
- return 200, { 'Content-Type' => 'text/html' }, erb('listing', dirs: dirs, files: files, pwd: pwd)
70
- end
71
-
72
- def erb(view, vars)
73
- ERB.new(File.read(File.join(File.dirname(__FILE__), "views/#{view}.erb")))
74
- .result(OpenStruct.new(vars).instance_eval { binding })
75
- end
76
-
77
- def error(env)
78
- return 404, nil, erb('404', path: env['REQUEST_PATH'])
79
- end
80
-
81
- def redirect(path)
82
- return 301, { 'Location' => path }, nil
83
- end
84
-
85
- def allowed?(path)
86
- target = File.absolute_path(path)
87
- return target.start_with?(File.absolute_path(Dir.pwd))
88
- end
89
-
90
- def include(file)
91
- File.read(File.join(File.dirname(__FILE__), file))
92
- end
93
-
94
- module Fsws
95
- def self.server
96
- Proc.new do |env|
97
- code, headers, body = serve(env)
98
- [code.to_s, headers, [body]]
99
- end
100
- end
101
- end
1
+ require 'rack'
2
+ require 'erb'
3
+ require 'pathname'
4
+ require 'ostruct'
5
+
6
+ def mime_types
7
+ return @mime_types if @mime_types
8
+
9
+ @mime_types = {}
10
+
11
+ path = File.join(File.dirname(__FILE__), 'mime.types')
12
+ File.open(path, 'r') do |file|
13
+ file.each_line do |line|
14
+ if line =~ /^\s*([\w\/.-]+)\s*((\w+\s*)+);\s*$/
15
+ mime_type = $1.strip
16
+ extensions = $2.strip.split.map(&:strip).map(&:downcase)
17
+ for ext in extensions
18
+ @mime_types[ext] = mime_type.downcase
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ @mime_types
25
+ end
26
+
27
+ def serve(env)
28
+ path = env['REQUEST_PATH'] || ''
29
+ path = '/' if path.empty?
30
+ path = '.' + path
31
+
32
+ return error(env) if !allowed?(path)
33
+
34
+ return serve_file(path) || serve_dir(path) || error(env)
35
+ end
36
+
37
+ def serve_file(path)
38
+ return nil if !File.file? path
39
+
40
+ ext = File.extname(path)
41
+ ext = ext[1...ext.length]
42
+ mime_type = mime_types[ext] || 'text/plain'
43
+
44
+ return 200, { 'Content-Type' => mime_type }, File.open(path, 'rb').read
45
+ end
46
+
47
+ def serve_dir(path)
48
+ return nil if !File.directory? path
49
+
50
+ for file in %w(index.html index.htm)
51
+ index = File.join(path, file)
52
+ page = serve_file(index)
53
+ return page if page
54
+ end
55
+
56
+ return redirect(path + '/') if !path.end_with?('/')
57
+
58
+ dirs, files = Dir.entries(path).partition { |e| File.directory?(File.join(path, e)) }
59
+ dirs.delete('.')
60
+ dirs.delete('..') if path == './'
61
+ dirs.sort!
62
+ files.sort!
63
+
64
+ target_path = Pathname.new(File.absolute_path(path))
65
+ current_path = Pathname.new(File.absolute_path(Dir.pwd))
66
+ pwd = Pathname.new('/' + target_path.relative_path_from(current_path).to_s).cleanpath.to_s
67
+ pwd += '/' if pwd[-1] != '/'
68
+
69
+ return 200, { 'Content-Type' => 'text/html' }, erb('listing', dirs: dirs, files: files, pwd: pwd)
70
+ end
71
+
72
+ def erb(view, vars)
73
+ ERB.new(File.read(File.join(File.dirname(__FILE__), "views/#{view}.erb")))
74
+ .result(OpenStruct.new(vars).instance_eval { binding })
75
+ end
76
+
77
+ def error(env)
78
+ return 404, nil, erb('404', path: env['REQUEST_PATH'])
79
+ end
80
+
81
+ def redirect(path)
82
+ return 301, { 'Location' => path }, nil
83
+ end
84
+
85
+ def allowed?(path)
86
+ target = File.absolute_path(path)
87
+ return target.start_with?(File.absolute_path(Dir.pwd))
88
+ end
89
+
90
+ def include(file)
91
+ File.read(File.join(File.dirname(__FILE__), file))
92
+ end
93
+
94
+ module Fsws
95
+ def self.server
96
+ Proc.new do |env|
97
+ code, headers, body = serve(env)
98
+ [code.to_s, headers, [body]]
99
+ end
100
+ end
101
+ end
data/lib/fsws/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Fsws
2
- VERSION = '1.1.0'
3
- end
1
+ module Fsws
2
+ VERSION = '2.0.0'
3
+ end
@@ -1,11 +1,11 @@
1
- <html>
2
- <head>
3
- <title>404 Not Found</title>
4
- <style type="text/css">
5
- <%= include 'views/style.css' %>
6
- </style>
7
- </head>
8
- <body>
9
- <h1>404 Not Found: <%= path %></h1>
10
- </body>
11
- </html>
1
+ <html>
2
+ <head>
3
+ <title>404 Not Found</title>
4
+ <style type="text/css">
5
+ <%= include 'views/style.css' %>
6
+ </style>
7
+ </head>
8
+ <body>
9
+ <h1>404 Not Found: <%= path %></h1>
10
+ </body>
11
+ </html>
@@ -1,33 +1,33 @@
1
- <html>
2
- <head>
3
- <title>Index of <%= pwd %></title>
4
- <style type="text/css">
5
- <%= include 'views/style.css' %>
6
- </style>
7
- </head>
8
- <body>
9
- <%
10
- parts = pwd.split('/').map { |p| p + '/' }
11
- parts = ['/'] if parts.empty?
12
- paths = parts.inject([]) { |acc, part| acc << ((acc.last || '') + part) }
13
- paths = paths.zip(parts)
14
- %>
15
- <h1>
16
- Index of <% paths.each { |path| %><a href="<%= path.first %>"><%= path.last %></a><% } %>
17
- </h1>
18
- <% if !dirs.empty? %>
19
- <ul>
20
- <% for dir in dirs %>
21
- <li><a href="<%= dir %>/"><%= dir %>/</a></li>
22
- <% end %>
23
- </ul>
24
- <% end %>
25
- <% if !files.empty? %>
26
- <ul>
27
- <% for file in files %>
28
- <li><a href="<%= file %>"><%= file %></a></li>
29
- <% end %>
30
- </ul>
31
- <% end %>
32
- </body>
33
- </html>
1
+ <html>
2
+ <head>
3
+ <title>Index of <%= pwd %></title>
4
+ <style type="text/css">
5
+ <%= include 'views/style.css' %>
6
+ </style>
7
+ </head>
8
+ <body>
9
+ <%
10
+ parts = pwd.split('/').map { |p| p + '/' }
11
+ parts = ['/'] if parts.empty?
12
+ paths = parts.inject([]) { |acc, part| acc << ((acc.last || '') + part) }
13
+ paths = paths.zip(parts)
14
+ %>
15
+ <h1>
16
+ Index of <% paths.each { |path| %><a href="<%= path.first %>"><%= path.last %></a><% } %>
17
+ </h1>
18
+ <% if !dirs.empty? %>
19
+ <ul>
20
+ <% for dir in dirs %>
21
+ <li><a href="<%= dir %>/"><%= dir %>/</a></li>
22
+ <% end %>
23
+ </ul>
24
+ <% end %>
25
+ <% if !files.empty? %>
26
+ <ul>
27
+ <% for file in files %>
28
+ <li><a href="<%= file %>"><%= file %></a></li>
29
+ <% end %>
30
+ </ul>
31
+ <% end %>
32
+ </body>
33
+ </html>
@@ -1,42 +1,42 @@
1
- body {
2
- font: 20px Consolas, Monaco, monospace;
3
- }
4
- a {
5
- text-decoration: none;
6
- color: #555;
7
- padding: 15px;
8
- }
9
- a:hover {
10
- background: #e7e7f3;
11
- color: #048;
12
- }
13
- h1 {
14
- margin-bottom: 10px;
15
- }
16
- h1 a {
17
- color: #000;
18
- display: inline;
19
- background: inherit;
20
- padding: 0;
21
- margin: 0;
22
- }
23
- h1 a:hover {
24
- background: inherit;
25
- color: #47b;
26
- }
27
- body {
28
- margin: 10px;
29
- }
30
- ul {
31
- list-style-type: none;
32
- margin: 0;
33
- padding: 0;
34
- }
35
- li {
36
- background: #f3f3f3;
37
- margin-bottom: 5px;
38
- padding: 0;
39
- }
40
- li a {
41
- display: block;
42
- }
1
+ body {
2
+ font: 20px Consolas, Monaco, monospace;
3
+ }
4
+ a {
5
+ text-decoration: none;
6
+ color: #555;
7
+ padding: 15px;
8
+ }
9
+ a:hover {
10
+ background: #e7e7f3;
11
+ color: #048;
12
+ }
13
+ h1 {
14
+ margin-bottom: 10px;
15
+ }
16
+ h1 a {
17
+ color: #000;
18
+ display: inline;
19
+ background: inherit;
20
+ padding: 0;
21
+ margin: 0;
22
+ }
23
+ h1 a:hover {
24
+ background: inherit;
25
+ color: #47b;
26
+ }
27
+ body {
28
+ margin: 10px;
29
+ }
30
+ ul {
31
+ list-style-type: none;
32
+ margin: 0;
33
+ padding: 0;
34
+ }
35
+ li {
36
+ background: #f3f3f3;
37
+ margin-bottom: 5px;
38
+ padding: 0;
39
+ }
40
+ li a {
41
+ display: block;
42
+ }
data/lib/fsws.rb CHANGED
@@ -1,2 +1,2 @@
1
- require 'fsws/server'
2
- require 'fsws/version'
1
+ require 'fsws/server'
2
+ require 'fsws/version'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fsws
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Schmich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-09 00:00:00.000000000 Z
11
+ date: 2014-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -75,10 +75,6 @@ executables:
75
75
  extensions: []
76
76
  extra_rdoc_files: []
77
77
  files:
78
- - LICENSE
79
- - README.md
80
- - bin/fsws
81
- - lib/fsws.rb
82
78
  - lib/fsws/cli.rb
83
79
  - lib/fsws/mime.types
84
80
  - lib/fsws/server.rb
@@ -86,6 +82,10 @@ files:
86
82
  - lib/fsws/views/404.erb
87
83
  - lib/fsws/views/listing.erb
88
84
  - lib/fsws/views/style.css
85
+ - lib/fsws.rb
86
+ - bin/fsws
87
+ - README.md
88
+ - LICENSE
89
89
  homepage: https://github.com/schmich/fsws
90
90
  licenses:
91
91
  - MIT
@@ -106,9 +106,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  version: '0'
107
107
  requirements: []
108
108
  rubyforge_project:
109
- rubygems_version: 2.3.0
109
+ rubygems_version: 2.0.14
110
110
  signing_key:
111
111
  specification_version: 4
112
112
  summary: Ruby file system web server.
113
113
  test_files: []
114
- has_rdoc: