11# frozen_string_literal: true
22
3+ gem "rails-html-sanitizer" , ">= 1.6.0"
4+ require "rails-html-sanitizer"
5+
36module AppProfiler
47 module Viewer
58 class BaseViewer
@@ -12,6 +15,101 @@ def view(profile, params = {})
1215 def view ( _params = { } )
1316 raise NotImplementedError
1417 end
18+
19+ class BaseMiddleware
20+ class Sanitizer < Rails ::HTML ::Sanitizer . best_supported_vendor . safe_list_sanitizer
21+ self . allowed_tags = Set . new ( [
22+ "strong" , "em" , "b" , "i" , "p" , "code" , "pre" , "tt" , "samp" , "kbd" , "var" , "sub" ,
23+ "sup" , "dfn" , "cite" , "big" , "small" , "address" , "hr" , "br" , "div" , "span" , "h1" ,
24+ "h2" , "h3" , "h4" , "h5" , "h6" , "ul" , "ol" , "li" , "dl" , "dt" , "dd" , "abbr" , "acronym" ,
25+ "a" , "img" , "blockquote" , "del" , "ins" , "script" ,
26+ ] )
27+ end
28+
29+ private_constant ( :Sanitizer )
30+
31+ def self . id ( file )
32+ file . basename . to_s
33+ end
34+
35+ def initialize ( app )
36+ @app = app
37+ end
38+
39+ def call ( env )
40+ request = Rack ::Request . new ( env )
41+
42+ return index ( env ) if %r(\A /app_profiler/?\z ) . match? ( request . path_info )
43+
44+ @app . call ( env )
45+ end
46+
47+ protected
48+
49+ def id ( file )
50+ self . class . id ( file )
51+ end
52+
53+ def profile_files
54+ AppProfiler . profile_root . glob ( "**/*.json" )
55+ end
56+
57+ def render ( html )
58+ [
59+ 200 ,
60+ { "Content-Type" => "text/html" } ,
61+ [
62+ +<<~HTML ,
63+ <!doctype html>
64+ < html >
65+ < head >
66+ < title > App Profiler</ title >
67+ </ head >
68+ < body >
69+ #{ sanitizer . sanitize ( html ) }
70+ </ body>
71+ </ html>
72+ HTML
73+ ] ,
74+ ]
75+ end
76+
77+ def sanitizer
78+ @sanitizer ||= Sanitizer . new
79+ end
80+
81+ def viewer ( _env , path )
82+ raise NotImplementedError
83+ end
84+
85+ def show ( env , id )
86+ raise NotImplementedError
87+ end
88+
89+ def index ( _env )
90+ render (
91+ ( +"" ) . tap do |content |
92+ content << "<h1>Profiles</h1>"
93+ profile_files . each do |file |
94+ viewer = if file . to_s . end_with? ( AppProfiler ::VernierProfile ::FILE_EXTENSION )
95+ AppProfiler ::Viewer ::FirefoxRemoteViewer ::NAME
96+ else
97+ AppProfiler ::Viewer ::SpeedscopeRemoteViewer ::NAME
98+ end
99+ content << <<~HTML
100+ < p >
101+ < a href ="/app_profiler/ #{ viewer } /viewer/#{ id ( file ) } ">
102+ #{ id ( file ) }
103+ </ a>
104+ </ p>
105+ HTML
106+ end
107+ end
108+ )
109+ end
110+ end
111+
112+ private_constant ( :BaseMiddleware )
15113 end
16114 end
17115end
0 commit comments