Class: Publicious

Inherits:
Object
  • Object
show all
Defined in:
lib/publicious.rb

Constant Summary collapse

FILE_METHODS =
%w(GET HEAD).freeze
@@logger =
Logger.new($stdout)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(app) ⇒ Publicious

Returns a new instance of Publicious.



17
18
19
20
# File 'lib/publicious.rb', line 17

def initialize(app)
  @app = app
  yield if block_given?
end

Class Method Details

.add_engines_public_paths!Object



77
78
79
80
81
# File 'lib/publicious.rb', line 77

def self.add_engines_public_paths!
  ::Rails::Engine.subclasses.map { |klass|
    klass.config.paths.public.paths.first
  }.flatten.compact.reject { |path| path =~ /publicious/}
end

.allowed_dirsObject



65
66
67
# File 'lib/publicious.rb', line 65

def self.allowed_dirs
  %w(stylesheets javascripts images)
end

.public_pathsObject



69
70
71
72
73
74
75
# File 'lib/publicious.rb', line 69

def self.public_paths
  @public_paths ||= begin
    paths = []
    paths += add_engines_public_paths! if defined?(::Rails::Engine)
    paths
  end
end

Instance Method Details

#call(env) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/publicious.rb', line 26

def call(env)
  
  request = Rack::Request.new(env)
  return @app.call(env) unless FILE_METHODS.include?(request.request_method)

  if request.path_info =~  %r{^\/(#{klass.allowed_dirs.join("|")})}
    file_name = nil
    path = nil

    klass.public_paths.detect do |pub_path|
      path = pub_path
      fp   = File.join(pub_path, request.path_info)
      file_name = fp if File.file?(fp)
    end

    return respond_not_found! unless file_name

    # Make sure pricks aren't ../../config/database.yml ing us
    respond_not_found! unless file_name.gsub(%r[^#{path}], "") == request.path_info
    
    klass.logger.info "Publicious middleware served #{request.path_info} with #{file_name}"
    Rack::Response.new(
      File.open(file_name),
      200,'Content-Type' => content_type_for_file(file_name)
    ).finish
  else
    @app.call(env)
  end
end

#content_type_for_file(name) ⇒ Object



60
61
62
63
# File 'lib/publicious.rb', line 60

def content_type_for_file(name)
  file_name = File.basename(name).split(".").last.to_s
  Mime::Type.lookup_by_extension(file_name).to_s
end

#klassObject



22
23
24
# File 'lib/publicious.rb', line 22

def klass
  self.class
end

#respond_not_found!Object



56
57
58
# File 'lib/publicious.rb', line 56

def respond_not_found!
  Rack::Response.new("Not Found", 404).finish
end