Move static assets to within srv
10
Makefile
@ -24,13 +24,3 @@ srv.dev-shell:
|
|||||||
srv.shell:
|
srv.shell:
|
||||||
nix-shell -A srv.shellWithBuild --arg baseConfig '(import ${CONFIG})' \
|
nix-shell -A srv.shellWithBuild --arg baseConfig '(import ${CONFIG})' \
|
||||||
--command 'cd srv/src; return'
|
--command 'cd srv/src; return'
|
||||||
|
|
||||||
# TODO static is on the way out, these aren't well supported
|
|
||||||
static.serve:
|
|
||||||
nix-shell -A static.shell --run 'cd static; static-serve'
|
|
||||||
|
|
||||||
static.depShell:
|
|
||||||
nix-shell -A static.depShell --command 'cd static; return'
|
|
||||||
|
|
||||||
static.lock:
|
|
||||||
nix-shell -A static.depShell --run 'bundler lock; bundix; rm -rf .bundle vendor'
|
|
||||||
|
20
default.nix
@ -7,7 +7,7 @@
|
|||||||
}) {},
|
}) {},
|
||||||
|
|
||||||
baseConfig ? import ./config.nix,
|
baseConfig ? import ./config.nix,
|
||||||
baseSkipServices ? [],
|
skipServices ? [],
|
||||||
|
|
||||||
}: rec {
|
}: rec {
|
||||||
|
|
||||||
@ -17,17 +17,8 @@
|
|||||||
redisListenPath = "${config.runDir}/redis";
|
redisListenPath = "${config.runDir}/redis";
|
||||||
};
|
};
|
||||||
|
|
||||||
skipServices = baseSkipServices ++ (
|
|
||||||
if baseConfig.staticProxyURL == ""
|
|
||||||
then [ "static" ]
|
|
||||||
else []
|
|
||||||
);
|
|
||||||
|
|
||||||
static = (import ./static) { inherit pkgs; };
|
|
||||||
|
|
||||||
srv = pkgs.callPackage (import ./srv) {
|
srv = pkgs.callPackage (import ./srv) {
|
||||||
inherit config;
|
inherit config;
|
||||||
staticBuild=static.build;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
redisCfg = pkgs.writeText "mediocre-blog-redisCfg" ''
|
redisCfg = pkgs.writeText "mediocre-blog-redisCfg" ''
|
||||||
@ -59,13 +50,6 @@
|
|||||||
numprocesses = 1
|
numprocesses = 1
|
||||||
'';
|
'';
|
||||||
|
|
||||||
staticCircusCfg = ''
|
|
||||||
[watcher:static]
|
|
||||||
cmd = ${static.serve}/bin/static-serve
|
|
||||||
numprocesses = 1
|
|
||||||
working_dir = ./static
|
|
||||||
'';
|
|
||||||
|
|
||||||
circusCfg = pkgs.writeText "mediocre-blog-circusCfg" ''
|
circusCfg = pkgs.writeText "mediocre-blog-circusCfg" ''
|
||||||
[circus]
|
[circus]
|
||||||
endpoint = tcp://127.0.0.1:0
|
endpoint = tcp://127.0.0.1:0
|
||||||
@ -74,8 +58,6 @@
|
|||||||
${if (!builtins.elem "srv" skipServices) then srvCircusCfg else ""}
|
${if (!builtins.elem "srv" skipServices) then srvCircusCfg else ""}
|
||||||
|
|
||||||
${if (!builtins.elem "redis" skipServices) then redisCircusCfg else ""}
|
${if (!builtins.elem "redis" skipServices) then redisCircusCfg else ""}
|
||||||
|
|
||||||
${if (!builtins.elem "static" skipServices) then staticCircusCfg else ""}
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
entrypoint = pkgs.writeScript "mediocre-blog-entrypoint" ''
|
entrypoint = pkgs.writeScript "mediocre-blog-entrypoint" ''
|
||||||
|
@ -11,7 +11,7 @@ test_cfg="(import ./config.nix) // {
|
|||||||
|
|
||||||
entrypoint=$(nix-build --no-out-link -A entrypoint \
|
entrypoint=$(nix-build --no-out-link -A entrypoint \
|
||||||
--arg baseConfig "$test_cfg" \
|
--arg baseConfig "$test_cfg" \
|
||||||
--arg baseSkipServices '["srv"]')
|
--arg skipServices '["srv"]')
|
||||||
|
|
||||||
$entrypoint &
|
$entrypoint &
|
||||||
trap "kill $!; wait; rm -rf $test_dir" EXIT
|
trap "kill $!; wait; rm -rf $test_dir" EXIT
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
stdenv,
|
stdenv,
|
||||||
|
|
||||||
config,
|
config,
|
||||||
staticBuild,
|
|
||||||
}: rec {
|
}: rec {
|
||||||
|
|
||||||
init = writeText "mediocre-blog-srv-init" ''
|
init = writeText "mediocre-blog-srv-init" ''
|
||||||
@ -26,9 +25,6 @@
|
|||||||
# pow
|
# pow
|
||||||
export MEDIOCRE_BLOG_POW_SECRET="${config.powSecret}"
|
export MEDIOCRE_BLOG_POW_SECRET="${config.powSecret}"
|
||||||
|
|
||||||
# static proxy
|
|
||||||
export MEDIOCRE_BLOG_STATIC_DIR="${staticBuild}"
|
|
||||||
|
|
||||||
# listening
|
# listening
|
||||||
export MEDIOCRE_BLOG_LISTEN_PROTO="${config.listenProto}"
|
export MEDIOCRE_BLOG_LISTEN_PROTO="${config.listenProto}"
|
||||||
export MEDIOCRE_BLOG_LISTEN_ADDR="${config.listenAddr}"
|
export MEDIOCRE_BLOG_LISTEN_ADDR="${config.listenAddr}"
|
||||||
|
@ -3,13 +3,12 @@ package http
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"embed"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
|
"github.com/mediocregopher/blog.mediocregopher.com/srv/cfg"
|
||||||
@ -22,6 +21,9 @@ import (
|
|||||||
"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
|
"github.com/mediocregopher/mediocre-go-lib/v2/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed static
|
||||||
|
var staticFS embed.FS
|
||||||
|
|
||||||
// Params are used to instantiate a new API instance. All fields are required
|
// Params are used to instantiate a new API instance. All fields are required
|
||||||
// unless otherwise noted.
|
// unless otherwise noted.
|
||||||
type Params struct {
|
type Params struct {
|
||||||
@ -45,16 +47,6 @@ type Params struct {
|
|||||||
// supported.
|
// supported.
|
||||||
ListenProto, ListenAddr string
|
ListenProto, ListenAddr string
|
||||||
|
|
||||||
// StaticDir and StaticProxy are mutually exclusive.
|
|
||||||
//
|
|
||||||
// If StaticDir is set then that directory on the filesystem will be used to
|
|
||||||
// serve the static site.
|
|
||||||
//
|
|
||||||
// Otherwise if StaticProxy is set all requests for the static site will be
|
|
||||||
// reverse-proxied there.
|
|
||||||
StaticDir string
|
|
||||||
StaticProxy *url.URL
|
|
||||||
|
|
||||||
// AuthUsers keys are usernames which are allowed to edit server-side data,
|
// AuthUsers keys are usernames which are allowed to edit server-side data,
|
||||||
// and the values are the password hash which accompanies those users. The
|
// and the values are the password hash which accompanies those users. The
|
||||||
// password hash must have been produced by NewPasswordHash.
|
// password hash must have been produced by NewPasswordHash.
|
||||||
@ -63,39 +55,14 @@ type Params struct {
|
|||||||
|
|
||||||
// SetupCfg implement the cfg.Cfger interface.
|
// SetupCfg implement the cfg.Cfger interface.
|
||||||
func (p *Params) SetupCfg(cfg *cfg.Cfg) {
|
func (p *Params) SetupCfg(cfg *cfg.Cfg) {
|
||||||
|
|
||||||
cfg.StringVar(&p.ListenProto, "listen-proto", "tcp", "Protocol to listen for HTTP requests with")
|
cfg.StringVar(&p.ListenProto, "listen-proto", "tcp", "Protocol to listen for HTTP requests with")
|
||||||
cfg.StringVar(&p.ListenAddr, "listen-addr", ":4000", "Address/path to listen for HTTP requests on")
|
cfg.StringVar(&p.ListenAddr, "listen-addr", ":4000", "Address/path to listen for HTTP requests on")
|
||||||
|
|
||||||
cfg.StringVar(&p.StaticDir, "static-dir", "", "Directory from which static files are served (mutually exclusive with -static-proxy-url)")
|
|
||||||
staticProxyURLStr := cfg.String("static-proxy-url", "", "HTTP address from which static files are served (mutually exclusive with -static-dir)")
|
|
||||||
|
|
||||||
cfg.OnInit(func(ctx context.Context) error {
|
|
||||||
if *staticProxyURLStr != "" {
|
|
||||||
var err error
|
|
||||||
if p.StaticProxy, err = url.Parse(*staticProxyURLStr); err != nil {
|
|
||||||
return fmt.Errorf("parsing -static-proxy-url: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if p.StaticDir == "" {
|
|
||||||
return errors.New("-static-dir or -static-proxy-url is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Annotate implements mctx.Annotator interface.
|
// Annotate implements mctx.Annotator interface.
|
||||||
func (p *Params) Annotate(a mctx.Annotations) {
|
func (p *Params) Annotate(a mctx.Annotations) {
|
||||||
a["listenProto"] = p.ListenProto
|
a["listenProto"] = p.ListenProto
|
||||||
a["listenAddr"] = p.ListenAddr
|
a["listenAddr"] = p.ListenAddr
|
||||||
|
|
||||||
if p.StaticProxy != nil {
|
|
||||||
a["staticProxy"] = p.StaticProxy.String()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a["staticDir"] = p.StaticDir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// API will listen on the port configured for it, and serve HTTP requests for
|
// API will listen on the port configured for it, and serve HTTP requests for
|
||||||
@ -156,15 +123,6 @@ func (a *api) Shutdown(ctx context.Context) error {
|
|||||||
|
|
||||||
func (a *api) handler() http.Handler {
|
func (a *api) handler() http.Handler {
|
||||||
|
|
||||||
var staticHandler http.Handler
|
|
||||||
if a.params.StaticDir != "" {
|
|
||||||
staticHandler = http.FileServer(http.Dir(a.params.StaticDir))
|
|
||||||
} else {
|
|
||||||
staticHandler = httputil.NewSingleHostReverseProxy(a.params.StaticProxy)
|
|
||||||
}
|
|
||||||
|
|
||||||
// sugar
|
|
||||||
|
|
||||||
requirePow := func(h http.Handler) http.Handler {
|
requirePow := func(h http.Handler) http.Handler {
|
||||||
return a.requirePowMiddleware(h)
|
return a.requirePowMiddleware(h)
|
||||||
}
|
}
|
||||||
@ -185,8 +143,6 @@ func (a *api) handler() http.Handler {
|
|||||||
|
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
mux.Handle("/", staticHandler)
|
|
||||||
|
|
||||||
{
|
{
|
||||||
apiMux := http.NewServeMux()
|
apiMux := http.NewServeMux()
|
||||||
apiMux.Handle("/pow/challenge", a.newPowChallengeHandler())
|
apiMux.Handle("/pow/challenge", a.newPowChallengeHandler())
|
||||||
@ -209,39 +165,37 @@ func (a *api) handler() http.Handler {
|
|||||||
mux.Handle("/api/", http.StripPrefix("/api", formMiddleware(apiMux)))
|
mux.Handle("/api/", http.StripPrefix("/api", formMiddleware(apiMux)))
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
mux.Handle("/posts/", http.StripPrefix("/posts",
|
||||||
v2Mux := http.NewServeMux()
|
apiutil.MethodMux(map[string]http.Handler{
|
||||||
v2Mux.Handle("/follow.html", a.renderDumbTplHandler("follow.html"))
|
"GET": a.renderPostHandler(),
|
||||||
v2Mux.Handle("/posts/", http.StripPrefix("/posts",
|
"EDIT": a.editPostHandler(),
|
||||||
apiutil.MethodMux(map[string]http.Handler{
|
"POST": authMiddleware(auther,
|
||||||
"GET": a.renderPostHandler(),
|
formMiddleware(a.postPostHandler()),
|
||||||
"EDIT": a.editPostHandler(),
|
),
|
||||||
"POST": authMiddleware(auther,
|
"DELETE": authMiddleware(auther,
|
||||||
formMiddleware(a.postPostHandler()),
|
formMiddleware(a.deletePostHandler()),
|
||||||
),
|
),
|
||||||
"DELETE": authMiddleware(auther,
|
"PREVIEW": authMiddleware(auther,
|
||||||
formMiddleware(a.deletePostHandler()),
|
formMiddleware(a.previewPostHandler()),
|
||||||
),
|
),
|
||||||
"PREVIEW": authMiddleware(auther,
|
}),
|
||||||
formMiddleware(a.previewPostHandler()),
|
))
|
||||||
),
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
v2Mux.Handle("/assets/", http.StripPrefix("/assets",
|
|
||||||
apiutil.MethodMux(map[string]http.Handler{
|
|
||||||
"GET": a.getPostAssetHandler(),
|
|
||||||
"POST": authMiddleware(auther,
|
|
||||||
formMiddleware(a.postPostAssetHandler()),
|
|
||||||
),
|
|
||||||
"DELETE": authMiddleware(auther,
|
|
||||||
formMiddleware(a.deletePostAssetHandler()),
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
))
|
|
||||||
v2Mux.Handle("/", a.renderIndexHandler())
|
|
||||||
|
|
||||||
mux.Handle("/v2/", http.StripPrefix("/v2", v2Mux))
|
mux.Handle("/assets/", http.StripPrefix("/assets",
|
||||||
}
|
apiutil.MethodMux(map[string]http.Handler{
|
||||||
|
"GET": a.getPostAssetHandler(),
|
||||||
|
"POST": authMiddleware(auther,
|
||||||
|
formMiddleware(a.postPostAssetHandler()),
|
||||||
|
),
|
||||||
|
"DELETE": authMiddleware(auther,
|
||||||
|
formMiddleware(a.deletePostAssetHandler()),
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
))
|
||||||
|
|
||||||
|
mux.Handle("/static/", http.FileServer(http.FS(staticFS)))
|
||||||
|
mux.Handle("/follow.html", a.renderDumbTplHandler("follow.html"))
|
||||||
|
mux.Handle("/", a.renderIndexHandler())
|
||||||
|
|
||||||
var globalHandler http.Handler = mux
|
var globalHandler http.Handler = mux
|
||||||
globalHandler = setCSRFMiddleware(globalHandler)
|
globalHandler = setCSRFMiddleware(globalHandler)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as utils from "/assets/utils.js";
|
import * as utils from "/static/utils.js";
|
||||||
|
|
||||||
const csrfTokenCookie = "csrf_token";
|
const csrfTokenCookie = "csrf_token";
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ const solvePow = async () => {
|
|||||||
|
|
||||||
const res = await call('/api/pow/challenge');
|
const res = await call('/api/pow/challenge');
|
||||||
|
|
||||||
const worker = new Worker('/assets/solvePow.js');
|
const worker = new Worker('/static/solvePow.js');
|
||||||
|
|
||||||
const p = new Promise((resolve, reject) => {
|
const p = new Promise((resolve, reject) => {
|
||||||
worker.postMessage({seedHex: res.seed, target: res.target});
|
worker.postMessage({seedHex: res.seed, target: res.target});
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 730 KiB After Width: | Height: | Size: 730 KiB |
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 141 KiB |
Before Width: | Height: | Size: 898 KiB After Width: | Height: | Size: 898 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
@ -1,7 +1,7 @@
|
|||||||
var midiLoaded = false;
|
var midiLoaded = false;
|
||||||
function loadMIDI() {
|
function loadMIDI() {
|
||||||
MIDI.loadPlugin({
|
MIDI.loadPlugin({
|
||||||
soundfontUrl: "/assets/trading-in-the-rain/soundfont/",
|
soundfontUrl: "/static/trading-in-the-rain/soundfont/",
|
||||||
instrument: "acoustic_grand_piano",
|
instrument: "acoustic_grand_piano",
|
||||||
onprogress: (state, progress) => {
|
onprogress: (state, progress) => {
|
||||||
console.log("MIDI loading...", progress*100, "%");
|
console.log("MIDI loading...", progress*100, "%");
|