# Snippet for global matchers and variables
# to logically expression request conditions
# E.g. for conditionally changing redirects
(globals) {
	# Use gzip compression for all responses
	encode gzip

	# Matcher for http request scheme. E.g. "http" or "https"
	@http_scheme {
		expression {http.request.scheme}=="https" || {header.X-Forwarded-Scheme}=="https" || {header.X-Forwarded-Proto}=="https"
	}
	# If any http scheme is "https", then use "wss"
	vars @http_scheme WsScheme "wss"
	# Else default to "ws"
	vars WsScheme "ws"

	# Matcher for forwarded request headers
	@host_forwarded {
		header X-Forwarded-Host *
	}
	# If http headers exists, then use them
	vars @host_forwarded ReqHost {header.X-Forwarded-Host}
	# Else default to host in request
	vars ReqHost {http.request.hostport}

	# Matcher for websocket connection upgrade requests
	@websockets {
		# Avoid case sensitivity issues when matching field values
		# E.g. when values are rewritten by Codespace port forwarding
		header_regexp Connection (?i)(Upgrade)
		header Upgrade websocket
	}
}

# Snippet for redirect with given URL queries values
# to simplify remote development with web apps
# E.g auto redirect websocket URL to match request scheme
(redirect) {
	# Configure redirect to match request scheme
	vars LayoutUrl "/assets/foxglove/nav2_layout.json"
	vars DataSourceUrl "{vars.WsScheme}://{vars.ReqHost}{args.0}/"
	redir /autoconnect "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}"
	redir /autolayout "{args.0}/?ds=foxglove-websocket&ds.url={vars.DataSourceUrl}&layoutUrl={vars.LayoutUrl}"
}

# Snippet for dummy imports
(dummy) {
}

# Snippet for enabling mobile web app features
# to improve user experience on small screen devices
# E.g. for enabling fullscreen mode on iOS and Android
(mobile) {
	# Match for directory redirects to index.html
	route / {
		# Inject link to manifest just after <head> tag
		# https://developer.mozilla.org/docs/Web/Manifest
		replace `<head>` `<head><link rel="manifest" href="manifest.json" crossorigin="use-credentials"/>`
	}
	# Redirect relative handle_path'ed manifest.json to /manifests directory
	redir /manifest.json /assets{http.request.orig_uri.path.dir}manifest.json
}

# Snippet for hosted web app using websockets
# to serve static files and reverse proxying connections
# E.g. for serving GzWeb and Foxglove web apps
(app) {
	# handle and strip path prefix from redirect
	handle_path {args.0}/* {
		# Set root directory for static files
		root * {http.vars.root}{args.0}
		# Enable mobile web app features
		import mobile
		# Reverse proxy websockets to backend address
		reverse_proxy @websockets {args.1}
		# Import custom snippets
		import {args.2} {args.0}
	}
}

# Listen for http requests on port 8080
# regardless of hostname or domain address
# E.g. whatever Codespaces assigns to host
:8080 {
	# Include global matchers and variables
	import globals
	root * {$ROOT_SRV:/srv}
	file_server browse

	# Handle root content
	# I.e. assets internal to workspace
	handle /* {
		# Template manifest.json files
		templates */manifest.json {
			mime application/json
		}
	}

	# Handle nav2 web app
	# I.e. main landing page
	handle_path /nav2/* {
		root * {http.vars.root}/nav2
		import mobile
		# Render markdown files as html
		templates
	}

	# Matcher for requests without browse query
	@no_browse {
		path /
		not query browse=true
	}
	# Redirect to nav2 web app by default
	redir @no_browse /nav2/

	# Import app snippets for web apps
	import app "/gzweb" "localhost:9090" "dummy"
	import app "/foxglove" "localhost:8765" "redirect"

	# Handle glances web app
	redir /glances /glances/
	handle_path /glances/* {
		import mobile
		# Reverse proxy to glances backend
		reverse_proxy * "localhost:61208"
	}

	# For debugging
	# log {
	# 	output file /var/log/caddy/server.log
	# }
}
