Skip to content

Commit 1edb1bb

Browse files
committed
Serve TensorBoard at /flags
1 parent 0334a6c commit 1edb1bb

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

tensorboard/plugins/core/core_plugin.py

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@
4545
# transition to 'text/javascript'.
4646
JS_MIMETYPES = ["text/javascript", "application/javascript"]
4747
JS_CACHE_EXPIRATION_IN_SECS = 86400
48+
# Th paths that the application should be served at
49+
# Note that paths other than "/" should NOT end in '/' because trailing '/'
50+
# characters are removed by the serving logic in tensorboard/backend/application.py
51+
APP_PATHS = ["/", "/flags"]
4852

4953

5054
class CorePlugin(base_plugin.TBPlugin):
@@ -109,17 +113,34 @@ def get_resource_apps(self):
109113
content = zip_.read(path)
110114
# Opt out of gzipping index.html
111115
if path == "index.html":
112-
apps["/" + path] = functools.partial(
113-
self._serve_index, content
114-
)
116+
for app_path in APP_PATHS:
117+
path_with_slash = (
118+
app_path
119+
if app_path.endswith("/")
120+
else app_path + "/"
121+
)
122+
apps[path_with_slash + path] = functools.partial(
123+
self._serve_index, content, app_path
124+
)
115125
continue
116126

117127
gzipped_asset_bytes = _gzip(content)
118128
wsgi_app = functools.partial(
119129
self._serve_asset, path, gzipped_asset_bytes
120130
)
121-
apps["/" + path] = wsgi_app
122-
apps["/"] = apps["/index.html"]
131+
for app_path in APP_PATHS:
132+
path_with_slash = (
133+
app_path
134+
if app_path.endswith("/")
135+
else app_path + "/"
136+
)
137+
apps[path_with_slash + path] = wsgi_app
138+
for app_path in APP_PATHS:
139+
if app_path.endswith("/"):
140+
apps[app_path] = apps[app_path + "index.html"]
141+
else:
142+
apps[app_path] = apps[app_path + "/index.html"]
143+
apps[app_path] = apps[app_path]
123144
return apps
124145

125146
@wrappers.Request.application
@@ -151,21 +172,23 @@ def _serve_asset(self, path, gzipped_asset_bytes, request):
151172
)
152173

153174
@wrappers.Request.application
154-
def _serve_index(self, index_asset_bytes, request):
175+
def _serve_index(self, index_asset_bytes, content_path, request):
155176
"""Serves index.html content.
156177
157178
Note that we opt out of gzipping index.html to write preamble before the
158179
resource content. This inflates the resource size from 2x kiB to 1xx
159180
kiB, but we require an ability to flush preamble with the HTML content.
160181
"""
182+
if not request.path.endswith("/"):
183+
return utils.redirect(request.path + "/")
161184
relpath = (
162185
posixpath.relpath(self._path_prefix, request.script_root)
163186
if self._path_prefix
164187
else "."
165188
)
166189
meta_header = (
167-
'<!doctype html><meta name="tb-relative-root" content="%s/">'
168-
% relpath
190+
'<!doctype html><meta name="tb-relative-root" content="%s%s">'
191+
% (relpath, content_path)
169192
)
170193
content = meta_header.encode("utf-8") + index_asset_bytes
171194
# By passing content_encoding, disallow gzipping. Bloats the content

tensorboard/webapp/app_routing/programmatical_navigation_types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,17 @@ export interface NavigateToExperiments {
4040
resetNamespacedState?: boolean;
4141
}
4242

43+
export interface NavigateToFlags {
44+
routeKind: RouteKind.FLAGS;
45+
routeParams: {},
46+
resetNamespacedState?: boolean;
47+
}
48+
4349
export type ProgrammaticalNavigation =
4450
| NavigateToExperiment
4551
| NavigateToCompare
46-
| NavigateToExperiments;
52+
| NavigateToExperiments
53+
| NavigateToFlags;
4754

4855
export interface NavigationLambda {
4956
actionCreator: ActionCreator<string, Creator>;

0 commit comments

Comments
 (0)