Merge pull request #5610 from bluesky-social/static_asset_cdn
Serve static assets from a CDN host if provided
This commit is contained in:
@@ -87,6 +87,13 @@ func run(args []string) {
|
|||||||
Value: cli.NewStringSlice("https://bsky.app", "https://main.bsky.dev", "https://app.staging.bsky.dev"),
|
Value: cli.NewStringSlice("https://bsky.app", "https://main.bsky.dev", "https://app.staging.bsky.dev"),
|
||||||
EnvVars: []string{"CORS_ALLOWED_ORIGINS"},
|
EnvVars: []string{"CORS_ALLOWED_ORIGINS"},
|
||||||
},
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "static-cdn-host",
|
||||||
|
Usage: "scheme, hostname, and port of static content CDN, don't end with a slash",
|
||||||
|
Required: false,
|
||||||
|
Value: "",
|
||||||
|
EnvVars: []string{"STATIC_CDN_HOST"},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,12 +41,13 @@ type Server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
debug bool
|
debug bool
|
||||||
httpAddress string
|
httpAddress string
|
||||||
appviewHost string
|
appviewHost string
|
||||||
ogcardHost string
|
ogcardHost string
|
||||||
linkHost string
|
linkHost string
|
||||||
ipccHost string
|
ipccHost string
|
||||||
|
staticCDNHost string
|
||||||
}
|
}
|
||||||
|
|
||||||
func serve(cctx *cli.Context) error {
|
func serve(cctx *cli.Context) error {
|
||||||
@@ -58,6 +59,8 @@ func serve(cctx *cli.Context) error {
|
|||||||
ipccHost := cctx.String("ipcc-host")
|
ipccHost := cctx.String("ipcc-host")
|
||||||
basicAuthPassword := cctx.String("basic-auth-password")
|
basicAuthPassword := cctx.String("basic-auth-password")
|
||||||
corsOrigins := cctx.StringSlice("cors-allowed-origins")
|
corsOrigins := cctx.StringSlice("cors-allowed-origins")
|
||||||
|
staticCDNHost := cctx.String("static-cdn-host")
|
||||||
|
staticCDNHost = strings.TrimSuffix(staticCDNHost, "/")
|
||||||
|
|
||||||
// Echo
|
// Echo
|
||||||
e := echo.New()
|
e := echo.New()
|
||||||
@@ -94,12 +97,13 @@ func serve(cctx *cli.Context) error {
|
|||||||
echo: e,
|
echo: e,
|
||||||
xrpcc: xrpcc,
|
xrpcc: xrpcc,
|
||||||
cfg: &Config{
|
cfg: &Config{
|
||||||
debug: debug,
|
debug: debug,
|
||||||
httpAddress: httpAddress,
|
httpAddress: httpAddress,
|
||||||
appviewHost: appviewHost,
|
appviewHost: appviewHost,
|
||||||
ogcardHost: ogcardHost,
|
ogcardHost: ogcardHost,
|
||||||
linkHost: linkHost,
|
linkHost: linkHost,
|
||||||
ipccHost: ipccHost,
|
ipccHost: ipccHost,
|
||||||
|
staticCDNHost: staticCDNHost,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -333,15 +337,21 @@ func (srv *Server) Shutdown() error {
|
|||||||
return srv.httpd.Shutdown(ctx)
|
return srv.httpd.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewTemplateContext returns a new pongo2 context with some default values.
|
||||||
|
func (srv *Server) NewTemplateContext() pongo2.Context {
|
||||||
|
return pongo2.Context{
|
||||||
|
"staticCDNHost": srv.cfg.staticCDNHost,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (srv *Server) errorHandler(err error, c echo.Context) {
|
func (srv *Server) errorHandler(err error, c echo.Context) {
|
||||||
code := http.StatusInternalServerError
|
code := http.StatusInternalServerError
|
||||||
if he, ok := err.(*echo.HTTPError); ok {
|
if he, ok := err.(*echo.HTTPError); ok {
|
||||||
code = he.Code
|
code = he.Code
|
||||||
}
|
}
|
||||||
c.Logger().Error(err)
|
c.Logger().Error(err)
|
||||||
data := pongo2.Context{
|
data := srv.NewTemplateContext()
|
||||||
"statusCode": code,
|
data["statusCode"] = code
|
||||||
}
|
|
||||||
c.Render(code, "error.html", data)
|
c.Render(code, "error.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,18 +395,18 @@ func (srv *Server) LinkProxyMiddleware(url *url.URL) echo.MiddlewareFunc {
|
|||||||
|
|
||||||
// handler for endpoint that have no specific server-side handling
|
// handler for endpoint that have no specific server-side handling
|
||||||
func (srv *Server) WebGeneric(c echo.Context) error {
|
func (srv *Server) WebGeneric(c echo.Context) error {
|
||||||
data := pongo2.Context{}
|
data := srv.NewTemplateContext()
|
||||||
return c.Render(http.StatusOK, "base.html", data)
|
return c.Render(http.StatusOK, "base.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) WebHome(c echo.Context) error {
|
func (srv *Server) WebHome(c echo.Context) error {
|
||||||
data := pongo2.Context{}
|
data := srv.NewTemplateContext()
|
||||||
return c.Render(http.StatusOK, "home.html", data)
|
return c.Render(http.StatusOK, "home.html", data)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (srv *Server) WebPost(c echo.Context) error {
|
func (srv *Server) WebPost(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
data := pongo2.Context{}
|
data := srv.NewTemplateContext()
|
||||||
|
|
||||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||||
rkeyParam := c.Param("rkey")
|
rkeyParam := c.Param("rkey")
|
||||||
@@ -471,7 +481,7 @@ func (srv *Server) WebPost(c echo.Context) error {
|
|||||||
func (srv *Server) WebStarterPack(c echo.Context) error {
|
func (srv *Server) WebStarterPack(c echo.Context) error {
|
||||||
req := c.Request()
|
req := c.Request()
|
||||||
ctx := req.Context()
|
ctx := req.Context()
|
||||||
data := pongo2.Context{}
|
data := srv.NewTemplateContext()
|
||||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||||
rkeyParam := c.Param("rkey")
|
rkeyParam := c.Param("rkey")
|
||||||
@@ -509,7 +519,7 @@ func (srv *Server) WebStarterPack(c echo.Context) error {
|
|||||||
|
|
||||||
func (srv *Server) WebProfile(c echo.Context) error {
|
func (srv *Server) WebProfile(c echo.Context) error {
|
||||||
ctx := c.Request().Context()
|
ctx := c.Request().Context()
|
||||||
data := pongo2.Context{}
|
data := srv.NewTemplateContext()
|
||||||
|
|
||||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||||
handleOrDIDParam := c.Param("handleOrDID")
|
handleOrDIDParam := c.Param("handleOrDID")
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
<!-- Hello Humans! API docs at https://atproto.com -->
|
<!-- Hello Humans! API docs at https://atproto.com -->
|
||||||
|
|
||||||
<link rel="preload" as="font" type="font/ttf" href="/static/media/InterVariable.c9f788f6e7ebaec75d7c.ttf">
|
<link rel="preload" as="font" type="font/ttf" href="{{ staticCDNHost }}/static/media/InterVariable.c9f788f6e7ebaec75d7c.ttf">
|
||||||
<link rel="preload" as="font" type="font/ttf" href="/static/media/InterVariable-Italic.55d6a3f35e9b605ba6f4.ttf">
|
<link rel="preload" as="font" type="font/ttf" href="{{ staticCDNHost }}/static/media/InterVariable-Italic.55d6a3f35e9b605ba6f4.ttf">
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/**
|
/**
|
||||||
@@ -26,14 +26,14 @@
|
|||||||
*/
|
*/
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'InterVariable';
|
font-family: 'InterVariable';
|
||||||
src: url(/static/media/InterVariable.c9f788f6e7ebaec75d7c.ttf) format('truetype');
|
src: url("{{ staticCDNHost }}/static/media/InterVariable.c9f788f6e7ebaec75d7c.ttf") format('truetype');
|
||||||
font-weight: 300 1000;
|
font-weight: 300 1000;
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
}
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'InterVariableItalic';
|
font-family: 'InterVariableItalic';
|
||||||
src: url(/static/media/InterVariable-Italic.55d6a3f35e9b605ba6f4.ttf) format('truetype');
|
src: url("{{ staticCDNHost }}/static/media/InterVariable-Italic.55d6a3f35e9b605ba6f4.ttf") format('truetype');
|
||||||
font-weight: 300 1000;
|
font-weight: 300 1000;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
@@ -78,10 +78,10 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
{% include "scripts.html" %}
|
{% include "scripts.html" %}
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/static/apple-touch-icon.png">
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ staticCDNHost }}/static/apple-touch-icon.png">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" href="/static/favicon-32x32.png">
|
<link rel="icon" type="image/png" sizes="32x32" href="{{ staticCDNHost }}/static/favicon-32x32.png">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" href="/static/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ staticCDNHost }}/static/favicon-16x16.png">
|
||||||
<link rel="mask-icon" href="/static/safari-pinned-tab.svg" color="#1185fe">
|
<link rel="mask-icon" href="{{ staticCDNHost }}/static/safari-pinned-tab.svg" color="#1185fe">
|
||||||
<meta name="theme-color">
|
<meta name="theme-color">
|
||||||
<meta name="application-name" content="Bluesky">
|
<meta name="application-name" content="Bluesky">
|
||||||
<meta name="generator" content="bskyweb">
|
<meta name="generator" content="bskyweb">
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ const outputFile = entrypoints
|
|||||||
const ext = path.extname(file)
|
const ext = path.extname(file)
|
||||||
|
|
||||||
if (ext === '.js') {
|
if (ext === '.js') {
|
||||||
return `<script defer="defer" src="/static/js/${file}"></script>`
|
return `<script defer="defer" src="{{ staticCDNHost }}/static/js/${file}"></script>`
|
||||||
}
|
}
|
||||||
if (ext === '.css') {
|
if (ext === '.css') {
|
||||||
return `<link rel="stylesheet" href="/static/css/${file}">`
|
return `<link rel="stylesheet" href="{{ staticCDNHost }}/static/css/${file}">`
|
||||||
}
|
}
|
||||||
|
|
||||||
return ''
|
return ''
|
||||||
|
|||||||
Reference in New Issue
Block a user