rack-webprofiler 0.1.0.pre.alpha1

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.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +27 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +34 -0
  6. data/.rubocop_todo.yml +0 -0
  7. data/.travis.yml +23 -0
  8. data/CHANGELOG.md +39 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Gemfile +15 -0
  11. data/LICENSE +21 -0
  12. data/README.md +94 -0
  13. data/Rakefile +17 -0
  14. data/bin/ci-prepare +16 -0
  15. data/bin/console +10 -0
  16. data/bin/setup +8 -0
  17. data/examples/README.md +56 -0
  18. data/examples/rack/config.ru +52 -0
  19. data/examples/sinatra/app.rb +37 -0
  20. data/examples/sinatra/config.ru +3 -0
  21. data/lib/rack/templates/404.erb +1 -0
  22. data/lib/rack/templates/assets/rwpt.css +9 -0
  23. data/lib/rack/templates/assets/rwpt.js +0 -0
  24. data/lib/rack/templates/async.erb +120 -0
  25. data/lib/rack/templates/panel/index.erb +29 -0
  26. data/lib/rack/templates/panel/layout.erb +17 -0
  27. data/lib/rack/templates/panel/show.erb +19 -0
  28. data/lib/rack/templates/profiler.erb +70 -0
  29. data/lib/rack/web_profiler/auto_configure/rails.rb +12 -0
  30. data/lib/rack/web_profiler/collector/debug_collector.rb +31 -0
  31. data/lib/rack/web_profiler/collector/erb_collector.rb +0 -0
  32. data/lib/rack/web_profiler/collector/performance_collector.rb +1 -0
  33. data/lib/rack/web_profiler/collector/rack/rack_collector.rb +23 -0
  34. data/lib/rack/web_profiler/collector/rack/request_collector.rb +33 -0
  35. data/lib/rack/web_profiler/collector/rails/active_record_collector.rb +25 -0
  36. data/lib/rack/web_profiler/collector/rails/logger_collector.rb +22 -0
  37. data/lib/rack/web_profiler/collector/rails/rails_collector.rb +25 -0
  38. data/lib/rack/web_profiler/collector/rails/request_collector.rb +50 -0
  39. data/lib/rack/web_profiler/collector/ruby_collector.rb +46 -0
  40. data/lib/rack/web_profiler/collector/sinatra/request_collector.rb +38 -0
  41. data/lib/rack/web_profiler/collector/sinatra/sinatra_collector.rb +25 -0
  42. data/lib/rack/web_profiler/collector/time_collector.rb +23 -0
  43. data/lib/rack/web_profiler/collector.rb +142 -0
  44. data/lib/rack/web_profiler/collectors.rb +88 -0
  45. data/lib/rack/web_profiler/config.rb +61 -0
  46. data/lib/rack/web_profiler/controller.rb +125 -0
  47. data/lib/rack/web_profiler/engine.rb +109 -0
  48. data/lib/rack/web_profiler/erb.rb +9 -0
  49. data/lib/rack/web_profiler/model/collection_record.rb +45 -0
  50. data/lib/rack/web_profiler/model.rb +35 -0
  51. data/lib/rack/web_profiler/request.rb +14 -0
  52. data/lib/rack/web_profiler/router.rb +71 -0
  53. data/lib/rack/web_profiler/version.rb +5 -0
  54. data/lib/rack/web_profiler.rb +70 -0
  55. data/lib/rack/webprofiler.rb +1 -0
  56. data/rack-webprofiler.gemspec +38 -0
  57. metadata +198 -0
@@ -0,0 +1,142 @@
1
+ require "docile"
2
+
3
+ module Rack
4
+
5
+ # Collector
6
+ class WebProfiler::Collector
7
+ autoload :RubyCollector, "rack/web_profiler/collector/ruby_collector"
8
+ autoload :TimeCollector, "rack/web_profiler/collector/time_collector"
9
+
10
+ module Rack
11
+ autoload :RackCollector, "rack/web_profiler/collector/rack/rack_collector"
12
+ autoload :RequestCollector, "rack/web_profiler/collector/rack/request_collector"
13
+ end
14
+
15
+ module Rails
16
+ autoload :ActiveRecordCollector, "rack/web_profiler/collector/rails/active_record_collector"
17
+ autoload :LoggerCollector, "rack/web_profiler/collector/rails/logger_collector"
18
+ autoload :RailsCollector, "rack/web_profiler/collector/rails/rails_collector"
19
+ autoload :RequestCollector, "rack/web_profiler/collector/rails/request_collector"
20
+ end
21
+
22
+ module Sinatra
23
+ autoload :RequestCollector, "rack/web_profiler/collector/sinatra/request_collector"
24
+ autoload :SinatraCollector, "rack/web_profiler/collector/sinatra/sinatra_collector"
25
+ end
26
+
27
+ # DSL
28
+ module DSL
29
+ def self.included(base)
30
+ base.extend(ClassMethods)
31
+ base.class_eval do
32
+ @definition = Definition.new
33
+ @definition.position = 1
34
+ @definition.is_enabled = true
35
+ @definition.klass = self
36
+ end
37
+ end
38
+
39
+ module ClassMethods
40
+ attr_reader :definition
41
+
42
+ def icon(icon = nil); definition.icon = icon; end
43
+ def collector_name(name = nil); definition.name = name; end
44
+ def position(position = nil); definition.position = position.to_i; end
45
+ def collect(&block); definition.collect = block; end
46
+
47
+ def template(template = nil, type: :file)
48
+ template = get_data_contents(template) if type == :DATA
49
+ definition.template = template
50
+ end
51
+
52
+ def is_enabled?(is_enabled = true)
53
+ definition.is_enabled = Proc.new if block_given?
54
+ definition.is_enabled = is_enabled
55
+ end
56
+
57
+ private
58
+
59
+ def get_data_contents(path)
60
+ data = ""
61
+ ::File.open(path, "rb") do |f|
62
+ begin
63
+ line = f.gets
64
+ end until line.nil? || /^__END__$/ === line
65
+ data << line while line = f.gets
66
+ end
67
+ data
68
+ end
69
+ end
70
+ end
71
+
72
+ # Definition
73
+ #
74
+ # Collector definition.
75
+ class Definition
76
+ attr_accessor :icon, :name, :position, :collect, :template, :is_enabled, :klass
77
+ attr_reader :data_storage
78
+
79
+ # Collect the data who the Collector need.
80
+ #
81
+ # @param request [Rack::WebProfiler::Request]
82
+ # @param response [Rack::Response]
83
+ #
84
+ # @return [Rack::WebProfiler::Collector::DSL::DataStorage]
85
+ def collect!(request, response)
86
+ @data_storage = Docile.dsl_eval(DataStorage.new, request, response, &collect)
87
+ end
88
+
89
+ # Is the collector enabled.
90
+ #
91
+ # @return [Boolean]
92
+ def is_enabled?
93
+ return !!@is_enabled.call if @is_enabled.is_a?(Proc)
94
+ !!@is_enabled
95
+ end
96
+ end
97
+
98
+ # DataStorage
99
+ #
100
+ # Used to store datas who Collector needs.
101
+ #
102
+ # @todo do DataStorage compatible with Marshal
103
+ class DataStorage
104
+ attr_reader :datas
105
+
106
+ def initialize
107
+ @datas = Hash.new
108
+ @status = nil
109
+ end
110
+
111
+ # Store a value.
112
+ #
113
+ # @param k [String, Symbol]
114
+ # @param v
115
+ def store(k, v)
116
+ # @todo check data format (must be compatible with Marshal)
117
+ @datas[k.to_sym] = v
118
+ end
119
+
120
+ # Status.
121
+ #
122
+ # @param v [Symbol, nil]
123
+ #
124
+ # @return [Symbol, nil]
125
+ def status(v = nil)
126
+ # @todo check status?
127
+ @status = v.to_sym unless v.nil?
128
+ @status
129
+ end
130
+
131
+ # Transform DataStorage to an Hash
132
+ #
133
+ # @return [Hash<Symbol, Object>]
134
+ def to_h
135
+ {
136
+ datas: @datas,
137
+ status: @status
138
+ }
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,88 @@
1
+ module Rack
2
+
3
+ # Collectors.
4
+ #
5
+ # Container of Collector objects.
6
+ class WebProfiler::Collectors
7
+
8
+ # Initialize.
9
+ def initialize
10
+ @collectors = {}
11
+ @sorted_collectors = {}
12
+ end
13
+
14
+ # Get a collector definition by his name.
15
+ #
16
+ # @param name [String]
17
+ #
18
+ # @return [Rack::WebProfiler::Collector::DSL::Definition, nil]
19
+ def definition_by_name(name)
20
+ name = name.to_sym
21
+ @sorted_collectors[name] unless @sorted_collectors[name].nil?
22
+ end
23
+
24
+ # Returns all collectors definition.
25
+ #
26
+ # @return [Hash<Symbol, Rack::WebProfiler::Collector::DSL::Definition>]
27
+ def all
28
+ @sorted_collectors
29
+ end
30
+
31
+ # Add a collector.
32
+ #
33
+ # @param collector_class [Class]
34
+ #
35
+ # @raise [ArgumentError] if `collector_class' is not a Class or is not an instance of Rack::WebProfiler::Collector::DSL
36
+ # or a collector with this name is already registrered.
37
+ def add_collector(collector_class)
38
+ unless collector_class.is_a? Class
39
+ raise ArgumentError, "`collector_class' must be a class"
40
+ end
41
+
42
+ unless collector_class.included_modules.include?(Rack::WebProfiler::Collector::DSL)
43
+ raise ArgumentError, "#{collector_class.class.name} must be an instance of \"Rack::WebProfiler::Collector::DSL\""
44
+ end
45
+
46
+ definition = collector_class.definition
47
+
48
+ if definition_by_name(definition.name)
49
+ raise ArgumentError, "A collector with name \“#{definition.name}\" already exists"
50
+ end
51
+
52
+ return false unless definition.is_enabled?
53
+
54
+ @collectors[collector_class] = definition
55
+
56
+ sort_collectors!
57
+ end
58
+
59
+ # Remove a collector.
60
+ #
61
+ # @param collector_class [Class]
62
+ #
63
+ # @raise [ArgumentError] if `collector_class' is not a Class or if this collector is not registered.
64
+ def remove_collector(collector_class)
65
+ unless collector_class.is_a? Class
66
+ raise ArgumentError, "`collector_class' must be a class"
67
+ end
68
+
69
+ unless @collectors[collector_class]
70
+ raise ArgumentError, "No collector found with class \“#{collector_class}\""
71
+ end
72
+
73
+ @collectors.delete(collector_class)
74
+
75
+ sort_collectors!
76
+ end
77
+
78
+ private
79
+
80
+ # Sort collectors by definition name.
81
+ def sort_collectors!
82
+ @sorted_collectors = {}
83
+
84
+ tmp = @collectors.sort_by { |_klass, definition| definition.position }
85
+ tmp.each { |_k, v| @sorted_collectors[v.name.to_sym] = v }
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,61 @@
1
+ require "fileutils"
2
+
3
+ module Rack
4
+ # Config
5
+ class WebProfiler::Config
6
+ attr_accessor :collectors, :tmp_dir
7
+
8
+ DEFAULT_COLLECTORS = [
9
+ # Commons
10
+ Rack::WebProfiler::Collector::RubyCollector,
11
+ Rack::WebProfiler::Collector::TimeCollector,
12
+
13
+ # Rack
14
+ # Rack::WebProfiler::Collector::Rack::RackCollector,
15
+ Rack::WebProfiler::Collector::Rack::RequestCollector,
16
+
17
+ # Rails
18
+ # Rack::WebProfiler::Collector::Rails::ActiveRecordCollector,
19
+ # Rack::WebProfiler::Collector::Rails::LoggerCollector,
20
+ Rack::WebProfiler::Collector::Rails::RailsCollector,
21
+ Rack::WebProfiler::Collector::Rails::RequestCollector,
22
+
23
+ # Sinatra
24
+ Rack::WebProfiler::Collector::Sinatra::RequestCollector,
25
+ Rack::WebProfiler::Collector::Sinatra::SinatraCollector,
26
+ ].freeze
27
+ def initialize
28
+ @collectors = Rack::WebProfiler::Collectors.new
29
+
30
+ load_defaults!
31
+ end
32
+
33
+ # Setup the configuration
34
+ #
35
+ # @param [block] block
36
+ def build!
37
+ unless block_given?
38
+ # @todo raise an Exception if no block given
39
+ end
40
+ instance_eval(&Proc.new)
41
+ end
42
+
43
+ # protected
44
+
45
+ def tmp_dir
46
+ FileUtils.mkdir_p @tmp_dir
47
+ @tmp_dir
48
+ end
49
+
50
+ private
51
+
52
+ def load_defaults!
53
+ # Add default collectors
54
+ DEFAULT_COLLECTORS.each do |collector_class|
55
+ @collectors.add_collector(collector_class)
56
+ end
57
+
58
+ @tmp_dir = Dir.tmpdir
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,125 @@
1
+ require "erb"
2
+ require "json"
3
+
4
+ module Rack
5
+ # Controller
6
+ #
7
+ # Generate the views of the WebProfiler.
8
+ class WebProfiler::Controller
9
+ # Initialize
10
+ #
11
+ # @param request [Rack::WebProfiler::Request]
12
+ def initialize(request)
13
+ @request = request
14
+ @contents_for = {}
15
+ end
16
+
17
+ # List the webprofiler history.
18
+ def index
19
+ @collections = Rack::WebProfiler::Model::CollectionRecord.order(Sequel.desc(:created_at))
20
+ .limit(20)
21
+
22
+ erb "panel/index.erb", layout: "panel/layout.erb"
23
+ end
24
+
25
+ # Show the webprofiler panel.
26
+ def show(token)
27
+ @collection = Rack::WebProfiler::Model::CollectionRecord[token: token]
28
+ return error404 if @collection.nil?
29
+
30
+ @collectors = Rack::WebProfiler.config.collectors.all
31
+
32
+ # @todo return json if request.content_type ask json (same for xml?)
33
+ # @example json {} if @request.media_type.include? "json"
34
+
35
+ erb "panel/show.erb", layout: "panel/layout.erb"
36
+ end
37
+
38
+ # Print the webprofiler toolbar
39
+ def show_toolbar(token)
40
+ @collection = Rack::WebProfiler::Model::CollectionRecord[token: token]
41
+ return erb nil, status: 404 if @collection.nil?
42
+
43
+ @collectors = Rack::WebProfiler.config.collectors.all
44
+ # @todo process the callector views
45
+ # @collectors = Rack::WebProfiler::Collector.render_tabs(@record)
46
+
47
+ erb "profiler.erb"
48
+ end
49
+
50
+ # Clean the webprofiler.
51
+ def delete
52
+ Rack::WebProfiler::Model.clean
53
+
54
+ redirect WebProfiler::Router.url_for_profiler
55
+ end
56
+
57
+ private
58
+
59
+ def redirect(path)
60
+ Rack::Response.new([], 302, {
61
+ "Location" => "#{@request.base_url}#{path}",
62
+ })
63
+ end
64
+
65
+ # Render a HTML reponse from an ERB template.
66
+ #
67
+ # @param path [String] Path to the ERB template
68
+ #
69
+ # @return [Rack::Response]
70
+ def erb(path, layout: nil, status: 200)
71
+ content = ""
72
+
73
+ unless path.nil?
74
+ templates = [read_template(path)]
75
+ templates << read_template(layout) unless layout.nil?
76
+
77
+ content = templates.inject(nil) do |prev, temp|
78
+ _render_erb(temp) { prev }
79
+ end
80
+ end
81
+
82
+ Rack::Response.new(content, status, {
83
+ "Content-Type" => "text/html",
84
+ })
85
+ end
86
+
87
+ # Render a JSON response from an Array or a Hash.
88
+ #
89
+ # @param data [Array, Hash] Data
90
+ #
91
+ # @return [Rack::Response]
92
+ def json(data = {})
93
+ Rack::Response.new(data.to_json, 200, {
94
+ "Content-Type" => "application/json",
95
+ })
96
+ end
97
+
98
+ def error404
99
+ erb "404.erb", layout: "panel/layout.erb", status: 404
100
+ end
101
+
102
+ def _render_erb(template)
103
+ ERB.new(template).result(binding)
104
+ end
105
+
106
+ def partial(path)
107
+ return "" if path.nil?
108
+ ERB.new(read_template(path)).result(binding)
109
+ end
110
+
111
+ def render_collector(path, data)
112
+ @data = data
113
+ return "" if path.nil?
114
+ ERB.new(read_template(path)).result(binding)
115
+ end
116
+
117
+ def read_template(template)
118
+ unless template.empty?
119
+ path = ::File.expand_path("../../templates/#{template}", __FILE__)
120
+ return ::File.read(path) if ::File.exist?(path)
121
+ end
122
+ template
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,109 @@
1
+ module Rack
2
+ #
3
+ class WebProfiler::Engine
4
+ class << self
5
+ # Process
6
+ #
7
+ # @param request [Rack::WebProfiler::Request]
8
+ # @param body
9
+ # @param status
10
+ # @param headers
11
+ #
12
+ # @return [Rack::Response]
13
+ def process(request, body, status, headers)
14
+ response = Rack::Response.new(body, status, headers)
15
+ record = collect!(request, response)
16
+
17
+ return response if !headers[CONTENT_TYPE].nil? and !headers[CONTENT_TYPE].include? "text/html"
18
+
19
+ @token = record.token
20
+ @url = WebProfiler::Router.url_for_toolbar(record.token)
21
+
22
+ response = Rack::Response.new([], status, headers)
23
+
24
+ response.header["X-RackWebProfiler-Token"] = @token
25
+ response.header["X-RackWebProfiler-Url"] = @url
26
+
27
+ if defined? Rails and body.is_a? ActionDispatch::Response::RackBody
28
+ body = body.body
29
+ end
30
+
31
+ if body.is_a? Array
32
+ body.each { |fragment| response.write inject(fragment) }
33
+ elsif body.is_a? String
34
+ response.write inject(body)
35
+ end
36
+
37
+ response
38
+ end
39
+
40
+ private
41
+
42
+ # Collect
43
+ #
44
+ # @param request
45
+ # @param response
46
+ def collect!(request, response)
47
+ processor = Processor.new(request, response)
48
+ processor.save!
49
+
50
+ processor.record
51
+ end
52
+
53
+ # Inject the webprofiler
54
+ #
55
+ # @param body [String]
56
+ def inject(body)
57
+ body.gsub(%r{</body>}, template.result(binding) + "</body>")
58
+ end
59
+
60
+ # Get the javascript code template to inject.
61
+ #
62
+ # @return [String]
63
+ def template
64
+ @template ||= ERB.new(::File.read(::File.expand_path("../../templates/async.erb", __FILE__)))
65
+ end
66
+
67
+ class Processor
68
+ attr_reader :record
69
+
70
+ def initialize(request, response)
71
+ @collectors = {}
72
+ @request = request.clone.freeze
73
+ @response = response.clone.freeze
74
+ @record = nil
75
+ end
76
+
77
+ def save!
78
+ create_record!
79
+ save_collected_datas!
80
+
81
+ @record.save
82
+ end
83
+
84
+ private
85
+
86
+ def create_record!
87
+ @record ||= WebProfiler::Model::CollectionRecord.create({
88
+ url: @request.path,
89
+ ip: @request.ip,
90
+ http_method: @request.request_method,
91
+ http_status: @response.status,
92
+ content_type: @response.content_type,
93
+ datas: {},
94
+ })
95
+ end
96
+
97
+ def save_collected_datas!
98
+ datas = {}
99
+
100
+ Rack::WebProfiler.config.collectors.all.each do |name, definition|
101
+ datas[name.to_sym] = definition.collect!(@request, @response).to_h
102
+ end
103
+
104
+ @record.datas = datas
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,9 @@
1
+ module Rack
2
+ class WebProfiler
3
+ # ERB
4
+ class ERB
5
+ def initialize(template, layout: nil)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,45 @@
1
+ module Rack
2
+ #
3
+ class WebProfiler::Model::CollectionRecord < Sequel::Model(Rack::WebProfiler::Model.database)
4
+ # Plugins
5
+ plugin :schema
6
+ plugin :hook_class_methods
7
+ plugin :serialization
8
+ plugin :timestamps
9
+
10
+ # Attributes:
11
+ # - id
12
+ # - token
13
+ # - ip
14
+ # - url
15
+ # - http_method
16
+ # - http_status
17
+ # - content_type
18
+ # - datas
19
+ # - created_at
20
+ set_schema do
21
+ primary_key :id
22
+
23
+ varchar :token, unique: true, empty: false
24
+ varchar :url, empty: false
25
+ varchar :ip, empty: false
26
+ varchar :http_method, empty: false
27
+ integer :http_status
28
+ varchar :content_type
29
+ string :datas, text: true, empty: false
30
+ datetime :created_at
31
+ end
32
+ create_table unless table_exists?
33
+
34
+ # Serialization
35
+ serialize_attributes :marshal, :datas
36
+
37
+ # Hooks
38
+ before_create :before_create
39
+
40
+ def before_create
41
+ token = Time.now.to_f.to_s.delete(".").to_i
42
+ self.token = token.to_s(36)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,35 @@
1
+ require "sequel"
2
+
3
+ module Rack
4
+ # Model
5
+ class WebProfiler::Model
6
+ autoload :CollectionRecord, "rack/web_profiler/model/collection_record"
7
+
8
+ class << self
9
+ # Get the WebProfiler database.
10
+ #
11
+ # @return [Sequel::SQLite::Database]
12
+ def database
13
+ @db ||= Sequel.connect("sqlite://#{db_file_path}", timeout: 50)
14
+ end
15
+
16
+ # Remove the database content.
17
+ def clean
18
+ return unless ::File.exist?(db_file_path)
19
+
20
+ ::File.delete(db_file_path)
21
+ @db = nil
22
+ @db_file_path = nil
23
+ end
24
+
25
+ private
26
+
27
+ # Returns the db file path.
28
+ #
29
+ # @return [String]
30
+ def db_file_path
31
+ @db_file_path ||= ::File.join(WebProfiler.config.tmp_dir, "rack-webprofiler.db")
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,14 @@
1
+ module Rack
2
+ #
3
+ class WebProfiler::Request < Rack::Request
4
+ attr_reader :runtime
5
+
6
+ def start_runtime!
7
+ @request_start ||= Time.now.to_f
8
+ end
9
+
10
+ def save_runtime!
11
+ @runtime ||= Time.now.to_f - @request_start
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,71 @@
1
+ module Rack
2
+ # Router
3
+ #
4
+ # Show WebProfiler page if the request path match with one
5
+ # of the webprofiler routes.
6
+ class WebProfiler::Router
7
+ BASE_PATH = "/_rwpt".freeze
8
+
9
+ class << self
10
+ # Get response for given request.
11
+ #
12
+ # @param request [Rack::WebProfiler::Request]
13
+ #
14
+ # @return [Rack::Reponse, false]
15
+ def response_for(request)
16
+ @request = request
17
+ path = Rack::Utils.unescape(request.path_info)
18
+
19
+ # Stop process if the request path does not start
20
+ # by the BASE_PATH
21
+ return false unless path.start_with?(BASE_PATH)
22
+
23
+ path.slice!(BASE_PATH)
24
+
25
+ route(request, path)
26
+ end
27
+
28
+ # Route!
29
+ def route(request, path)
30
+ controller = WebProfiler::Controller.new(request)
31
+
32
+ if request.get? && path =~ %r{^\/toolbar\/([a-z0-9]*)(\/)?$}
33
+ controller.show_toolbar(Regexp.last_match(1))
34
+ elsif request.get? && path =~ %r{^\/clean(\/)?$}
35
+ controller.delete
36
+ elsif request.get? && path =~ %r{^(\/)?$}
37
+ controller.index
38
+ elsif request.get? && path =~ %r{^\/([a-z0-9]*)(\/)?$}
39
+ controller.show(Regexp.last_match(1))
40
+ else
41
+ false
42
+ end
43
+ end
44
+
45
+ # Get url for toobar.
46
+ #
47
+ # @param token [String]
48
+ #
49
+ # @return [String]
50
+ def url_for_toolbar(token)
51
+ "#{@request.script_name}#{BASE_PATH}/toolbar/#{token}"
52
+ end
53
+
54
+ # Get url for the webprofiler.
55
+ #
56
+ # @param token [String, nil]
57
+ #
58
+ # @return [String]
59
+ def url_for_profiler(token = nil)
60
+ "#{@request.script_name}#{BASE_PATH}/#{token}"
61
+ end
62
+
63
+ # Get url to clean webprofiler.
64
+ #
65
+ # @return [String]
66
+ def url_for_clean_profiler
67
+ "#{@request.script_name}#{BASE_PATH}/clean"
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ module Rack
2
+ class WebProfiler
3
+ VERSION = "0.1.0-alpha1".freeze
4
+ end
5
+ end