Skip to content

Commit 71eecb3

Browse files
authored
chore: embed build info in the html to reduce requests (#6605)
This will reduce a request on every page load of Coder!
1 parent 74be9c6 commit 71eecb3

File tree

3 files changed

+39
-9
lines changed

3 files changed

+39
-9
lines changed

site/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<meta property="og:type" content="website" />
1717
<meta property="csp-nonce" content="{{ .CSP.Nonce }}" />
1818
<meta property="csrf-token" content="{{ .CSRF.Token }}" />
19+
<meta property="build-info" content="{{ .BuildInfo }}" />
1920
<!-- We need to set data-react-helmet to be able to override it in the workspace page -->
2021
<link
2122
rel="alternate icon"

site/site.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import (
66
"crypto/sha1" //#nosec // Not used for cryptography.
77
_ "embed"
88
"encoding/hex"
9+
"encoding/json"
910
"errors"
1011
"fmt"
12+
"html"
1113
htmltemplate "html/template"
1214
"io"
1315
"io/fs"
@@ -28,6 +30,7 @@ import (
2830
"golang.org/x/sync/singleflight"
2931
"golang.org/x/xerrors"
3032

33+
"github.com/coder/coder/buildinfo"
3134
"github.com/coder/coder/coderd/httpapi"
3235
"github.com/coder/coder/codersdk"
3336
)
@@ -102,10 +105,20 @@ func Handler(siteFS fs.FS, binFS http.FileSystem, binHashes map[string]string) h
102105
})))
103106
mux.Handle("/", http.FileServer(http.FS(siteFS))) // All other non-html static files.
104107

108+
buildInfo := codersdk.BuildInfoResponse{
109+
ExternalURL: buildinfo.ExternalURL(),
110+
Version: buildinfo.Version(),
111+
}
112+
buildInfoResponse, err := json.Marshal(buildInfo)
113+
if err != nil {
114+
panic("failed to marshal build info: " + err.Error())
115+
}
116+
105117
return secureHeaders(&handler{
106-
fs: siteFS,
107-
htmlFiles: files,
108-
h: mux,
118+
fs: siteFS,
119+
htmlFiles: files,
120+
h: mux,
121+
buildInfoJSON: html.EscapeString(string(buildInfoResponse)),
109122
})
110123
}
111124

@@ -117,8 +130,9 @@ type handler struct {
117130
// scripts, and that nonce is passed through a template.
118131
// We only do this for html files to reduce the amount of in memory caching
119132
// of duplicate files as `fs`.
120-
htmlFiles *htmlTemplates
121-
h http.Handler
133+
htmlFiles *htmlTemplates
134+
h http.Handler
135+
buildInfoJSON string
122136
}
123137

124138
// filePath returns the filepath of the requested file.
@@ -138,8 +152,9 @@ func (h *handler) exists(filePath string) bool {
138152
}
139153

140154
type htmlState struct {
141-
CSP cspState
142-
CSRF csrfState
155+
CSP cspState
156+
CSRF csrfState
157+
BuildInfo string
143158
}
144159

145160
type cspState struct {
@@ -184,7 +199,8 @@ func (h *handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
184199
reqFile := filePath(req.URL.Path)
185200
state := htmlState{
186201
// Token is the CSRF token for the given request
187-
CSRF: csrfState{Token: nosurf.Token(req)},
202+
CSRF: csrfState{Token: nosurf.Token(req)},
203+
BuildInfo: h.buildInfoJSON,
188204
}
189205

190206
// First check if it's a file we have in our templates

site/src/xServices/buildInfo/buildInfoXService.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,20 @@ export const buildInfoMachine = createMachine(
5353
},
5454
{
5555
services: {
56-
getBuildInfo: API.getBuildInfo,
56+
getBuildInfo: async () => {
57+
// Build info is injected by the Coder server into the HTML document.
58+
const buildInfo = document.querySelector("meta[property=build-info]")
59+
if (buildInfo) {
60+
const rawContent = buildInfo.getAttribute("content")
61+
try {
62+
return JSON.parse(rawContent as string)
63+
} catch (ex) {
64+
// Ignore this and fetch as normal!
65+
}
66+
}
67+
68+
return API.getBuildInfo()
69+
},
5770
},
5871
actions: {
5972
assignBuildInfo: assign({

0 commit comments

Comments
 (0)