Skip to content

Commit 11615fd

Browse files
ruffslSteveMacenski
authored andcommitted
Improve usability of PWAs in Dev Containers (#3576)
* Add WIP icons * Add WIP icons for gzweb * Add WIP icons for glances * Set cross origin to use credentials ensuring auth cookie is included in request header when requesting for web app manifest file thus avoiding CORS policy violations in browser when accessing forwarded codespaces ports from the web > The request for the manifest is made without credentials (even if it's on the same domain), thus if the manifest requires credentials, you must include `crossorigin="use-credentials"` in the manifest tag. - https://web.dev/add-manifest/ - https://stackoverflow.com/a/57184506/2577586 * Use ReqHost variable in templates to account for X-Forwarded-Host value in header * Delete duplicate manifest * Set id property in app manifests so we can address them independently from their start_url - https://developer.chrome.com/blog/pwa-manifest-id/ * Ensure apps are uniquely identifies by adding trailing slash to id and thus different URI directories * Refactor root landing page into nav2 app by moving page file into nav2 sub folder adding root redirect pointing to /nav2/ and updating html, markdown, manifest files respectively * Fix https detection for Caddy reverse proxies by also checking X-Forwarded-Proto in request header * Remove unnecessary files * Prune smaller images * Prune duplicate icon * Clean up html tags * Update manifest icons * Rename icons * Revert "Prune duplicate icon" This reverts commit 5710401. * Add back favicon for shortcut * Add self index for completeness and bookmarking * Simplify icon linking * Delete binary files * Fix hyperlink path * Include image files using gitattributes to track these binary files via git LFS * Add icons using git lfs * Standardized all icon paths * Use external links for icons to avoid the need for using git LFS although this is a bit of a hack * Stage any and maskable icons * Use any and masked icons * Set colors to match maskable icon colors * Update icon * Use lossless compression without removing background - https://shortpixel.com/online-image-compression * Use WebP instead of PNG for smaller file sizes - https://en.wikipedia.org/wiki/WebP * Move icons into icons folder * Use _SRV environment variables for service paths * Download media files from github during docker image build to avoid adding always online dependencies when creating or starting dev containers * Delete media icons from git repo now that we download media from anonymized URLs on github - https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/attaching-files * Add comments * Enable file browsing for non app paths for remote debugging of media and asset files * Consolidate assets into single folder * Add links for file browser paths to Server Diagnostics * Delete unused symlink * Update landing page to match manifest by including same shortcuts and start url * Patch gzweb to disable modelList avoiding 404s for thumbnails as they are hardcoded into js * Update comments * Simplify Caddyfile by reverting to symlinking but add ROOT_SRV env for custom overriding * Loop over nav2 srv folders when symlinking to generalize over folder names * Add matcher for file browsing root directory while still redirecting to nav2 app by default * Use placeholders for root variable to consolidate env default fallback settings e.g `:/srv` * Promote file browser in Nav2 app shortcuts * Fix and update SRV envs * Postpone symlinking for Nav2 web app to when post-create-command script then runs given full repo is not copied into builder stage in Dockerfile. While this could be postponed to update-content-command leaving it here avoids blowing user changes after the container has been created or modified. * Add guard to check if srv folder exists * Add refresh rate shortcuts to glances * Add file browser shortcut to nav2 * Set scope for nav2 PWA to root to allow for opening child apps inside nav2 app * Display child apps in fullscreen mode by default as users can still open them in standalone via nav2 app given the nav2 app's scope is the parent root path * Update shortcuts and landing page * Document PWA scope and installation order when using Nav2 PWA scoped as root * Revert setting scope for nav2 PWA to root path as adding file browser shortcut to nav2 PWA is not worth the trouble of having to explain installation order caveats and URL launch behavior. File browser shortcut is still accessible from inside nav2 pwa launcher but merely displays in browser preview given root / is out of scope for /nav2/ * Update server diagnostics for troubleshooting * Verify checksum of archive before extraction incase anonymized URL changes expected archive
1 parent 6ecbe81 commit 11615fd

File tree

16 files changed

+235
-146
lines changed

16 files changed

+235
-146
lines changed

.devcontainer/caddy/Caddyfile

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
# Matcher for http request scheme. E.g. "http" or "https"
99
@http_scheme {
10-
expression {http.request.scheme}=="https" || {header.X-Forwarded-Scheme}=="https"
10+
expression {http.request.scheme}=="https" || {header.X-Forwarded-Scheme}=="https" || {header.X-Forwarded-Proto}=="https"
1111
}
1212
# If any http scheme is "https", then use "wss"
1313
vars @http_scheme WsScheme "wss"
@@ -19,9 +19,9 @@
1919
header X-Forwarded-Host *
2020
}
2121
# If http headers exists, then use them
22-
vars @host_forwarded WsHost {header.X-Forwarded-Host}
22+
vars @host_forwarded ReqHost {header.X-Forwarded-Host}
2323
# Else default to host in request
24-
vars WsHost {http.request.hostport}
24+
vars ReqHost {http.request.hostport}
2525

2626
# Matcher for websocket connection upgrade requests
2727
@websockets {
@@ -37,8 +37,8 @@
3737
# E.g auto redirect websocket URL to match request scheme
3838
(redirect) {
3939
# Configure redirect to match request scheme
40-
vars LayoutUrl "/assets/nav2_foxglove_layout.json"
41-
vars DataSourceUrl "{vars.WsScheme}://{vars.WsHost}{args.0}/"
40+
vars LayoutUrl "/assets/foxglove/nav2_layout.json"
41+
vars DataSourceUrl "{vars.WsScheme}://{vars.ReqHost}{args.0}/"
4242
redir /autoconnect "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}"
4343
redir /autolayout "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}&layoutUrl={vars.LayoutUrl}"
4444
}
@@ -55,30 +55,26 @@
5555
route / {
5656
# Inject link to manifest just after <head> tag
5757
# https://developer.mozilla.org/docs/Web/Manifest
58-
replace `<head>` `<head><link rel="manifest" href="manifest.json" />`
58+
replace `<head>` `<head><link rel="manifest" href="manifest.json" crossorigin="use-credentials"/>`
5959
}
6060
# Redirect relative handle_path'ed manifest.json to /manifests directory
61-
redir /manifest.json /manifests{http.request.orig_uri.path.dir}manifest.json
61+
redir /manifest.json /assets{http.request.orig_uri.path.dir}manifest.json
6262
}
6363

6464
# Snippet for hosted web app using websockets
6565
# to serve static files and reverse proxying connections
6666
# E.g. for serving GzWeb and Foxglove web apps
6767
(app) {
68-
# Redirect implicit directory requests twards index.html
69-
redir {args.0} {args.0}/
7068
# handle and strip path prefix from redirect
7169
handle_path {args.0}/* {
7270
# Set root directory for static files
73-
root * {args.1}
74-
# Serve static files
75-
file_server
71+
root * {http.vars.root}{args.0}
7672
# Enable mobile web app features
7773
import mobile
7874
# Reverse proxy websockets to backend address
79-
reverse_proxy @websockets {args.2}
75+
reverse_proxy @websockets {args.1}
8076
# Import custom snippets
81-
import {args.3} {args.0}
77+
import {args.2} {args.0}
8278
}
8379
}
8480

@@ -88,24 +84,38 @@
8884
:8080 {
8985
# Include global matchers and variables
9086
import globals
87+
root * {$ROOT_SRV:/srv}
88+
file_server browse
9189

92-
# Handle main landing page
90+
# Handle root content
91+
# I.e. assets internal to workspace
9392
handle /* {
94-
# Use relative path for root directory
95-
root * srv
96-
file_server
97-
import mobile
98-
# Render markdown files as html
99-
templates
10093
# Template manifest.json files
10194
templates */manifest.json {
10295
mime application/json
10396
}
10497
}
10598

99+
# Handle nav2 web app
100+
# I.e. main landing page
101+
handle_path /nav2/* {
102+
root * {http.vars.root}/nav2
103+
import mobile
104+
# Render markdown files as html
105+
templates
106+
}
107+
108+
# Matcher for requests without browse query
109+
@no_browse {
110+
path /
111+
not query browse=true
112+
}
113+
# Redirect to nav2 web app by default
114+
redir @no_browse /nav2/
115+
106116
# Import app snippets for web apps
107-
import app "/gzweb" "{$GZWEB_WS}/http/client" "localhost:9090" "dummy"
108-
import app "/foxglove" "{$FOXGLOVE_WS}" "localhost:8765" "redirect"
117+
import app "/gzweb" "localhost:9090" "dummy"
118+
import app "/foxglove" "localhost:8765" "redirect"
109119

110120
# Handle glances web app
111121
redir /glances /glances/
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "Foxglove: {{placeholder "http.vars.ReqHost"}}",
3+
"short_name": "Foxglove: {{placeholder "http.vars.ReqHost"}}",
4+
"icons": [
5+
{
6+
"src": "/media/icons/foxglove/any_icon_x512.webp",
7+
"sizes": "512x512",
8+
"type": "image/webp",
9+
"purpose": "any"
10+
},
11+
{
12+
"src": "/media/icons/foxglove/maskable_icon_x512.webp",
13+
"sizes": "512x512",
14+
"type": "image/webp",
15+
"purpose": "maskable"
16+
}
17+
],
18+
"id": "/foxglove/",
19+
"start_url": "/foxglove/autoconnect",
20+
"theme_color": "#6F3BE8",
21+
"background_color": "#6F3BE8",
22+
"display": "fullscreen",
23+
"shortcuts" : [
24+
{
25+
"name": "Auto Connect",
26+
"url": "/foxglove/autoconnect",
27+
"description": "Auto connect to default data source"
28+
},
29+
{
30+
"name": "Auto Layout",
31+
"url": "/foxglove/autolayout",
32+
"description": "Auto connect using default layout"
33+
},
34+
{
35+
"name": "Manual Connect",
36+
"url": "/foxglove/",
37+
"description": "Manually connect to data source"
38+
}
39+
]
40+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "Glances: {{placeholder "http.vars.ReqHost"}}",
3+
"short_name": "Glances: {{placeholder "http.vars.ReqHost"}}",
4+
"icons": [
5+
{
6+
"src": "/media/icons/glances/any_icon_x512.webp",
7+
"sizes": "512x512",
8+
"type": "image/webp",
9+
"purpose": "any"
10+
},
11+
{
12+
"src": "/media/icons/glances/maskable_icon_x512.webp",
13+
"sizes": "512x512",
14+
"type": "image/webp",
15+
"purpose": "maskable"
16+
}
17+
],
18+
"id": "/glances/",
19+
"start_url": "/glances/",
20+
"theme_color": "#2C363F",
21+
"background_color": "#2C363F",
22+
"display": "fullscreen",
23+
"shortcuts" : [
24+
{
25+
"name": "Refresh 1sec",
26+
"url": "/glances/1",
27+
"description": "Refresh page every 1 second"
28+
},
29+
{
30+
"name": "Refresh 5sec",
31+
"url": "/glances/5",
32+
"description": "Refresh page every 5 seconds"
33+
},
34+
{
35+
"name": "Refresh 10sec",
36+
"url": "/glances/10",
37+
"description": "Refresh page every 10 seconds"
38+
}
39+
]
40+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "Gzweb: {{placeholder "http.vars.ReqHost"}}",
3+
"short_name": "Gzweb: {{placeholder "http.vars.ReqHost"}}",
4+
"icons": [
5+
{
6+
"src": "/media/icons/gzweb/any_icon_x512.webp",
7+
"sizes": "512x512",
8+
"type": "image/webp",
9+
"purpose": "any"
10+
},
11+
{
12+
"src": "/media/icons/gzweb/maskable_icon_x512.webp",
13+
"sizes": "512x512",
14+
"type": "image/webp",
15+
"purpose": "maskable"
16+
}
17+
],
18+
"id": "/gzweb/",
19+
"start_url": "/gzweb/",
20+
"theme_color": "#ffffff",
21+
"background_color": "#ffffff",
22+
"display": "fullscreen"
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "Nav2: {{placeholder "http.vars.ReqHost"}}",
3+
"short_name": "Nav2: {{placeholder "http.vars.ReqHost"}}",
4+
"icons": [
5+
{
6+
"src": "/media/icons/nav2/any_icon_x512.webp",
7+
"sizes": "512x512",
8+
"type": "image/webp",
9+
"purpose": "any"
10+
},
11+
{
12+
"src": "/media/icons/nav2/maskable_icon_x512.webp",
13+
"sizes": "512x512",
14+
"type": "image/webp",
15+
"purpose": "maskable"
16+
}
17+
],
18+
"id": "/nav2/",
19+
"start_url": "/nav2/",
20+
"theme_color": "#ffffff",
21+
"background_color": "#ffffff",
22+
"display": "standalone"
23+
}

.devcontainer/caddy/srv/index.md

Lines changed: 0 additions & 48 deletions
This file was deleted.

.devcontainer/caddy/srv/manifests/foxglove/manifest.json

Lines changed: 0 additions & 32 deletions
This file was deleted.

.devcontainer/caddy/srv/manifests/glances/manifest.json

Lines changed: 0 additions & 15 deletions
This file was deleted.

.devcontainer/caddy/srv/manifests/gzweb/manifest.json

Lines changed: 0 additions & 15 deletions
This file was deleted.

0 commit comments

Comments
 (0)