Top Level Namespace

Defined Under Namespace

Modules: Fsws

Instance Method Summary collapse

Instance Method Details

#allowed?(path) ⇒ Boolean

Returns:

  • (Boolean)


85
86
87
88
# File 'lib/fsws/server.rb', line 85

def allowed?(path)
  target = File.absolute_path(path)
  return target.start_with?(File.absolute_path(Dir.pwd))
end

#erb(view, vars) ⇒ Object



72
73
74
75
# File 'lib/fsws/server.rb', line 72

def erb(view, vars)
  ERB.new(File.read(File.join(File.dirname(__FILE__), "views/#{view}.erb")))
    .result(OpenStruct.new(vars).instance_eval { binding })
end

#error(env) ⇒ Object



77
78
79
# File 'lib/fsws/server.rb', line 77

def error(env)
  return 404, nil, erb('404', path: env['REQUEST_PATH'])
end

#include(file) ⇒ Object



90
91
92
# File 'lib/fsws/server.rb', line 90

def include(file)
  File.read(File.join(File.dirname(__FILE__), file))
end

#mime_typesObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/fsws/server.rb', line 6

def mime_types
  return @mime_types if @mime_types

  @mime_types = {}

  path = File.join(File.dirname(__FILE__), 'mime.types')
  File.open(path, 'r') do |file|
    file.each_line do |line|
      if line =~ /^\s*([\w\/.-]+)\s*((\w+\s*)+);\s*$/
        mime_type = $1.strip
        extensions = $2.strip.split.map(&:strip).map(&:downcase)
        for ext in extensions
          @mime_types[ext] = mime_type.downcase
        end
      end
    end
  end

  @mime_types
end

#redirect(path) ⇒ Object



81
82
83
# File 'lib/fsws/server.rb', line 81

def redirect(path)
  return 301, { 'Location' => path }, nil
end

#serve(env) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/fsws/server.rb', line 27

def serve(env)
  path = env['REQUEST_PATH'] || ''
  path = '/' if path.empty?
  path = '.' + path

  return error(env) if !allowed?(path)

  return serve_file(path) || serve_dir(path) || error(env)
end

#serve_dir(path) ⇒ Object



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/fsws/server.rb', line 47

def serve_dir(path)
  return nil if !File.directory? path

  for file in %w(index.html index.htm)
    index = File.join(path, file)
    page = serve_file(index)
    return page if page
  end

  return redirect(path + '/') if !path.end_with?('/')

  dirs, files = Dir.entries(path).partition { |e| File.directory?(File.join(path, e)) }
  dirs.delete('.')
  dirs.delete('..') if path == './'
  dirs.sort!
  files.sort!

  target_path = Pathname.new(File.absolute_path(path))
  current_path = Pathname.new(File.absolute_path(Dir.pwd))
  pwd = Pathname.new('/' + target_path.relative_path_from(current_path).to_s).cleanpath.to_s
  pwd += '/' if pwd[-1] != '/'

  return 200, { 'Content-Type' => 'text/html' }, erb('listing', dirs: dirs, files: files, pwd: pwd)
end

#serve_file(path) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/fsws/server.rb', line 37

def serve_file(path)
  return nil if !File.file? path

  ext = File.extname(path)
  ext = ext[1...ext.length]
  mime_type = mime_types[ext] || 'text/plain'

  return 200, { 'Content-Type' => mime_type }, File.open(path, 'rb').read
end