Browse Source

Allow serving web ui at arbitrary root (#348)

Previously, the web UI was hard-coded to be served at `/` but
applications which are *embedding* the ui are unlikely to host it there.

This change makes the links between the various ui pages relative,
addressing this problem.

To make sure this doesn't rot, the internal http server now serves the
ui at /ui/ (redirecting there from the root).

I think we can all agree that the ui code and JavaScript is kind of a
haphazard affair. I performed a great deal of clicking around to make
sure the semantics didn't change and interestingly spent some time
trying to fix semantics I later realized weren't actually there: I
thought that when navigating to another page from a focused search (say
`flamegraph?f=x`) the focus would be carried over. This doesn't seem to
be the case, however.

The point being, there's no test coverage and setting it up is way
beyond what I can do here. I'm happy to manually verify whatever
sequence of clicks is suggested, though.

Touches https://github.com/cockroachdb/cockroach/pull/24145.
Tobias Schottdorf 7 years ago
parent
commit
c7bd8844d7
3 changed files with 34 additions and 28 deletions
  1. 1
    1
      internal/driver/flamegraph.go
  2. 18
    18
      internal/driver/webhtml.go
  3. 15
    9
      internal/driver/webui.go

+ 1
- 1
internal/driver/flamegraph.go View File

@@ -92,7 +92,7 @@ func (ui *webInterface) flamegraph(w http.ResponseWriter, req *http.Request) {
92 92
 		return
93 93
 	}
94 94
 
95
-	ui.render(w, "/flamegraph", "flamegraph", rpt, errList, config.Labels, webArgs{
95
+	ui.render(w, "flamegraph", rpt, errList, config.Labels, webArgs{
96 96
 		FlameGraph: template.JS(b),
97 97
 		Nodes:      nodeArr,
98 98
 	})

+ 18
- 18
internal/driver/webhtml.go View File

@@ -233,7 +233,7 @@ table tr td {
233 233
 {{define "header"}}
234 234
 <div class="header">
235 235
   <div class="title">
236
-    <h1><a href="/">pprof</a></h1>
236
+    <h1><a href="./">pprof</a></h1>
237 237
   </div>
238 238
 
239 239
   <div id="view" class="menu-item">
@@ -242,12 +242,12 @@ table tr td {
242 242
       <i class="downArrow"></i>
243 243
     </div>
244 244
     <div class="submenu">
245
-      <a title="{{.Help.top}}"  href="/top" id="topbtn">Top</a>
246
-      <a title="{{.Help.graph}}" href="/" id="graphbtn">Graph</a>
247
-      <a title="{{.Help.flamegraph}}" href="/flamegraph" id="flamegraph">Flame Graph</a>
248
-      <a title="{{.Help.peek}}" href="/peek" id="peek">Peek</a>
249
-      <a title="{{.Help.list}}" href="/source" id="list">Source</a>
250
-      <a title="{{.Help.disasm}}" href="/disasm" id="disasm">Disassemble</a>
245
+      <a title="{{.Help.top}}"  href="./top" id="topbtn">Top</a>
246
+      <a title="{{.Help.graph}}" href="./" id="graphbtn">Graph</a>
247
+      <a title="{{.Help.flamegraph}}" href="./flamegraph" id="flamegraph">Flame Graph</a>
248
+      <a title="{{.Help.peek}}" href="./peek" id="peek">Peek</a>
249
+      <a title="{{.Help.list}}" href="./source" id="list">Source</a>
250
+      <a title="{{.Help.disasm}}" href="./disasm" id="disasm">Disassemble</a>
251 251
     </div>
252 252
   </div>
253 253
 
@@ -257,12 +257,12 @@ table tr td {
257 257
       <i class="downArrow"></i>
258 258
     </div>
259 259
     <div class="submenu">
260
-      <a title="{{.Help.focus}}" href="{{.BaseURL}}" id="focus">Focus</a>
261
-      <a title="{{.Help.ignore}}" href="{{.BaseURL}}" id="ignore">Ignore</a>
262
-      <a title="{{.Help.hide}}" href="{{.BaseURL}}" id="hide">Hide</a>
263
-      <a title="{{.Help.show}}" href="{{.BaseURL}}" id="show">Show</a>
260
+      <a title="{{.Help.focus}}" href="?" id="focus">Focus</a>
261
+      <a title="{{.Help.ignore}}" href="?" id="ignore">Ignore</a>
262
+      <a title="{{.Help.hide}}" href="?" id="hide">Hide</a>
263
+      <a title="{{.Help.show}}" href="?" id="show">Show</a>
264 264
       <hr>
265
-      <a title="{{.Help.reset}}" href="{{.BaseURL}}">Reset</a>
265
+      <a title="{{.Help.reset}}" href="?">Reset</a>
266 266
     </div>
267 267
   </div>
268 268
 
@@ -295,7 +295,7 @@ table tr td {
295 295
     {{.HTMLBody}}
296 296
   </div>
297 297
   {{template "script" .}}
298
-  <script>viewer({{.BaseURL}}, {{.Nodes}});</script>
298
+  <script>viewer(new URL(window.location.href), {{.Nodes}});</script>
299 299
 </body>
300 300
 </html>
301 301
 {{end}}
@@ -597,7 +597,7 @@ function viewer(baseUrl, nodes) {
597 597
   function handleKey(e) {
598 598
     if (e.keyCode != 13) return;
599 599
     window.location.href =
600
-        updateUrl(new URL({{.BaseURL}}, window.location.href), 'f');
600
+        updateUrl(new URL(window.location.href), 'f');
601 601
     e.preventDefault();
602 602
   }
603 603
 
@@ -963,7 +963,7 @@ function viewer(baseUrl, nodes) {
963 963
       bindSort('namehdr', 'Name');
964 964
     }
965 965
 
966
-    viewer({{.BaseURL}}, {{.Nodes}});
966
+    viewer(new URL(window.location.href), {{.Nodes}});
967 967
     makeTopTable({{.Total}}, {{.Top}});
968 968
   </script>
969 969
 </body>
@@ -986,7 +986,7 @@ function viewer(baseUrl, nodes) {
986 986
     {{.HTMLBody}}
987 987
   </div>
988 988
   {{template "script" .}}
989
-  <script>viewer({{.BaseURL}}, null);</script>
989
+  <script>viewer(new URL(window.location.href), null);</script>
990 990
 </body>
991 991
 </html>
992 992
 {{end}}
@@ -1007,7 +1007,7 @@ function viewer(baseUrl, nodes) {
1007 1007
     </pre>
1008 1008
   </div>
1009 1009
   {{template "script" .}}
1010
-  <script>viewer({{.BaseURL}}, null);</script>
1010
+  <script>viewer(new URL(window.location.href), null);</script>
1011 1011
 </body>
1012 1012
 </html>
1013 1013
 {{end}}
@@ -1044,7 +1044,7 @@ function viewer(baseUrl, nodes) {
1044 1044
     <div id="flamegraphdetails" class="flamegraph-details"></div>
1045 1045
   </div>
1046 1046
   {{template "script" .}}
1047
-  <script>viewer({{.BaseURL}}, {{.Nodes}});</script>
1047
+  <script>viewer(new URL(window.location.href), {{.Nodes}});</script>
1048 1048
   <script>{{template "d3script" .}}</script>
1049 1049
   <script>{{template "d3tipscript" .}}</script>
1050 1050
   <script>{{template "d3flamegraphscript" .}}</script>

+ 15
- 9
internal/driver/webui.go View File

@@ -69,7 +69,6 @@ func (ec *errorCatcher) PrintErr(args ...interface{}) {
69 69
 
70 70
 // webArgs contains arguments passed to templates in webhtml.go.
71 71
 type webArgs struct {
72
-	BaseURL    string
73 72
 	Title      string
74 73
 	Errors     []string
75 74
 	Total      int64
@@ -172,7 +171,15 @@ func defaultWebServer(args *plugin.HTTPServerArgs) error {
172 171
 		}
173 172
 		h.ServeHTTP(w, req)
174 173
 	})
175
-	s := &http.Server{Handler: handler}
174
+
175
+	// We serve the ui at /ui/ and redirect there from the root. This is done
176
+	// to surface any problems with serving the ui at a non-root early. See:
177
+	//
178
+	// https://github.com/google/pprof/pull/348
179
+	mux := http.NewServeMux()
180
+	mux.Handle("/ui/", http.StripPrefix("/ui", handler))
181
+	mux.Handle("/", http.RedirectHandler("/ui/", http.StatusTemporaryRedirect))
182
+	s := &http.Server{Handler: mux}
176 183
 	return s.Serve(ln)
177 184
 }
178 185
 
@@ -248,11 +255,10 @@ func (ui *webInterface) makeReport(w http.ResponseWriter, req *http.Request,
248 255
 }
249 256
 
250 257
 // render generates html using the named template based on the contents of data.
251
-func (ui *webInterface) render(w http.ResponseWriter, baseURL, tmpl string,
258
+func (ui *webInterface) render(w http.ResponseWriter, tmpl string,
252 259
 	rpt *report.Report, errList, legend []string, data webArgs) {
253 260
 	file := getFromLegend(legend, "File: ", "unknown")
254 261
 	profile := getFromLegend(legend, "Type: ", "unknown")
255
-	data.BaseURL = baseURL
256 262
 	data.Title = file + " " + profile
257 263
 	data.Errors = errList
258 264
 	data.Total = rpt.Total()
@@ -297,7 +303,7 @@ func (ui *webInterface) dot(w http.ResponseWriter, req *http.Request) {
297 303
 		nodes = append(nodes, n.Info.Name)
298 304
 	}
299 305
 
300
-	ui.render(w, "/", "graph", rpt, errList, legend, webArgs{
306
+	ui.render(w, "graph", rpt, errList, legend, webArgs{
301 307
 		HTMLBody: template.HTML(string(svg)),
302 308
 		Nodes:    nodes,
303 309
 	})
@@ -332,7 +338,7 @@ func (ui *webInterface) top(w http.ResponseWriter, req *http.Request) {
332 338
 		nodes = append(nodes, item.Name)
333 339
 	}
334 340
 
335
-	ui.render(w, "/top", "top", rpt, errList, legend, webArgs{
341
+	ui.render(w, "top", rpt, errList, legend, webArgs{
336 342
 		Top:   top,
337 343
 		Nodes: nodes,
338 344
 	})
@@ -354,7 +360,7 @@ func (ui *webInterface) disasm(w http.ResponseWriter, req *http.Request) {
354 360
 	}
355 361
 
356 362
 	legend := report.ProfileLabels(rpt)
357
-	ui.render(w, "/disasm", "plaintext", rpt, errList, legend, webArgs{
363
+	ui.render(w, "plaintext", rpt, errList, legend, webArgs{
358 364
 		TextBody: out.String(),
359 365
 	})
360 366
 
@@ -378,7 +384,7 @@ func (ui *webInterface) source(w http.ResponseWriter, req *http.Request) {
378 384
 	}
379 385
 
380 386
 	legend := report.ProfileLabels(rpt)
381
-	ui.render(w, "/source", "sourcelisting", rpt, errList, legend, webArgs{
387
+	ui.render(w, "sourcelisting", rpt, errList, legend, webArgs{
382 388
 		HTMLBody: template.HTML(body.String()),
383 389
 	})
384 390
 }
@@ -399,7 +405,7 @@ func (ui *webInterface) peek(w http.ResponseWriter, req *http.Request) {
399 405
 	}
400 406
 
401 407
 	legend := report.ProfileLabels(rpt)
402
-	ui.render(w, "/peek", "plaintext", rpt, errList, legend, webArgs{
408
+	ui.render(w, "plaintext", rpt, errList, legend, webArgs{
403 409
 		TextBody: out.String(),
404 410
 	})
405 411
 }