tvl-depot/users/Profpatsch/blog/default.nix
Profpatsch d4f4b0f6d4 docs(users/Profpatsch/blog): document symbols
… and clean up the import list a little.

Change-Id: I7a116e9bbf01731267795b5327fecf98f0c7c3e4
Reviewed-on: https://cl.tvl.fyi/c/depot/+/3286
Tested-by: BuildkiteCI
Reviewed-by: Profpatsch <mail@profpatsch.de>
2021-11-13 00:57:28 +00:00

241 lines
7.4 KiB
Nix
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{ depot, pkgs, lib, ... }:
let
bins = depot.nix.getBins pkgs.lowdown [ "lowdown" ]
// depot.nix.getBins pkgs.cdb [ "cdbget" "cdbmake" "cdbdump" ]
// depot.nix.getBins pkgs.coreutils [ "mv" "cat" "printf" "test" ]
// depot.nix.getBins pkgs.s6-networking [ "s6-tcpserver" ]
// depot.nix.getBins pkgs.time [ "time" ]
;
# /
toplevel = [
{
route = [ "notes" ];
name = "Notes";
page = router;
}
];
# /notes/*
notes = [
{
route = [ "notes" "preventing-oom" ];
name = "Preventing OOM";
page = renderNote "preventing-oom" ./notes/preventing-oom.md;
}
{
route = [ "notes" "rust-string-conversions" ];
name = "Converting between different String types in Rust";
page = renderNote "rust-string-conversions" ./notes/rust-string-conversions.md;
}
];
# convert a note to html via lowdown
renderNote = name: note: depot.nix.runExecline "${name}.html" {} [
"importas" "out" "out"
bins.lowdown "-s" "-Thtml" "-o" "$out" note
];
# all notes with `route` converted to an absolute path
notesFullRoute = lib.pipe notes [
(map (x@{route, ...}: x // { route = mkRoute route; }))
];
# a cdb from route to a netencoded version of data for each route
router = lib.pipe notesFullRoute [
(map (x: {
name = x.route;
value = depot.users.Profpatsch.netencode.gen.dwim x;
}))
lib.listToAttrs
(cdbMake "notes-router")
];
# look up a route by path ($1)
router-lookup = depot.nix.writeExecline "router-lookup" { readNArgs = 1; } [
cdbLookup router "$1"
];
runExeclineStdout = name: args: cmd: depot.nix.runExecline name args ([
"importas" "-ui" "out" "out"
"redirfd" "-w" "1" "$out"
] ++ cmd);
index = runExeclineStdout "index" {
stdin = depot.users.Profpatsch.netencode.gen.dwim notesFullRoute;
} [
"withstdinas" "-in" "TEMPLATE_DATA"
"pipeline" [
bins.printf ''
<ul>
{{#.}}
<li><a href="{{route}}">{{name}}<a></li>
{{/.}}
</ul>
''
]
depot.users.Profpatsch.netencode.netencode-mustache
];
arglibNetencode = val: depot.nix.writeExecline "arglib-netencode" { } [
"export" "ARGLIB_NETENCODE" (depot.users.Profpatsch.netencode.gen.dwim val)
"$@"
];
# A simple http server that serves the site. Yes, its horrible.
notes-server = { port }: depot.nix.writeExecline "blog-server" {} [
(depot.users.Profpatsch.lib.runInEmptyEnv [ "PATH" ])
bins.s6-tcpserver "127.0.0.1" port
bins.time "--format=time: %es" "--"
runOr return400
"pipeline" [
(arglibNetencode {
what = "request";
})
depot.users.Profpatsch.read-http
]
depot.users.Profpatsch.netencode.record-splice-env
runOr return500
"importas" "-i" "path" "path"
"if" [ depot.tools.eprintf "GET \${path}\n" ]
runOr return404
"backtick" "-ni" "TEMPLATE_DATA" [
"ifelse" [ bins.test "$path" "=" "/notes" ]
[ "export" "content-type" "text/html"
"export" "serve-file" index
depot.users.Profpatsch.netencode.env-splice-record
]
# TODO: ignore potential query arguments. See 404 message
"pipeline" [ router-lookup "$path" ]
depot.users.Profpatsch.netencode.record-splice-env
"importas" "-ui" "page" "page"
"export" "content-type" "text/html"
"export" "serve-file" "$page"
depot.users.Profpatsch.netencode.env-splice-record
]
runOr return500
"if" [
"pipeline" [ bins.printf ''
HTTP/1.1 200 OK
Content-Type: {{{content-type}}}; charset=UTF-8
Connection: close
'' ]
depot.users.Profpatsch.netencode.netencode-mustache
]
"pipeline" [ "importas" "t" "TEMPLATE_DATA" bins.printf "%s" "$t" ]
depot.users.Profpatsch.netencode.record-splice-env
"importas" "-ui" "serve-file" "serve-file"
bins.cat "$serve-file"
];
# run argv or $1 if argv returns a failure status code.
runOr = depot.nix.writeExecline "run-or" { readNArgs = 1; } [
"foreground" [ "$@" ]
"importas" "?" "?"
"ifelse" [ bins.test "$?" "-eq" "0" ]
[]
"if" [ depot.tools.eprintf "runOr: exited \${?}, running \${1}\n" ]
"$1"
];
return400 = depot.nix.writeExecline "return400" {} [
bins.printf "%s" ''
HTTP/1.1 400 Bad Request
Content-Type: text/plain; charset=UTF-8
Connection: close
''
];
return404 = depot.nix.writeExecline "return404" {} [
bins.printf "%s" ''
HTTP/1.1 404 Not Found
Content-Type: text/plain; charset=UTF-8
Connection: close
This page doesnt exist! Query arguments are not handled at the moment.
''
];
return500 = depot.nix.writeExecline "return500" {} [
bins.printf "%s" ''
HTTP/1.1 500 Internal Server Error
Content-Type: text/plain; charset=UTF-8
Connection: close
Encountered an internal server error. Please try again.
''
];
capture-stdin = depot.nix.writers.rustSimple {
name = "capture-stdin";
dependencies = [ depot.users.Profpatsch.execline.exec-helpers ];
} ''
extern crate exec_helpers;
use std::io::Read;
fn main() {
let (args, prog) = exec_helpers::args_for_exec("capture-stdin", 1);
let valname = &args[1];
let mut v : Vec<u8> = vec![];
std::io::stdin().lock().read_to_end(&mut v).unwrap();
exec_helpers::exec_into_args("capture-stdin", prog, vec![(valname, v)]);
}
'';
# go from a list of path elements to an absolute route string
mkRoute = route: "/" + lib.concatMapStringsSep "/" urlencodeAscii route;
# urlencodes, but only ASCII characters
# https://en.wikipedia.org/wiki/Percent-encoding
urlencodeAscii = urlPiece:
let
raw = [ "!" "#" "$" "%" "&" "'" "(" ")" "*" "+" "," "/" ":" ";" "=" "?" "@" "[" "]" ];
enc = [ "%21" "%23" "%24" "%25" "%26" "%27" "%28" "%29" "%2A" "%2B" "%2C" "%2F" "%3A" "%3B" "%3D" "%3F" "%40" "%5B" "%5D" ];
rest = [ "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S" "T" "U" "V" "W" "X" "Y" "Z" "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "k" "l" "m" "n" "o" "p" "q" "r" "s" "t" "u" "v" "w" "x" "y" "z" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "-" "_" "." "~" ];
in
assert lib.assertMsg (lib.all (c: builtins.elem c (raw ++ rest)) (lib.stringToCharacters urlPiece))
"urlencodeAscii: the urlPiece must only contain valid url ASCII characters, was: ${urlPiece}";
builtins.replaceStrings raw enc urlPiece;
# create a cdb record entry, as required by the cdbmake tool
cdbRecord = key: val:
"+${toString (builtins.stringLength key)},${toString (builtins.stringLength val)}:"
+ "${key}->${val}\n";
# create a full cdbmake input from an attribute set of keys to values (strings)
cdbRecords =
with depot.nix.yants;
defun [ (attrs (either drv string)) string ]
(attrs:
(lib.concatStrings (lib.mapAttrsToList cdbRecord attrs)) + "\n");
# run cdbmake on a list of key/value pairs (strings
cdbMake = name: attrs: depot.nix.runExecline "${name}.cdb" {
stdin = cdbRecords attrs;
} [
"importas" "out" "out"
depot.users.Profpatsch.lib.eprint-stdin
"if" [ bins.cdbmake "db" "tmp" ]
bins.mv "db" "$out"
];
# look up a key ($2) in the given cdb ($1)
cdbLookup = depot.nix.writeExecline "cdb-lookup" { readNArgs = 2; } [
# cdb ($1) on stdin
"redirfd" "-r" "0" "$1"
# key ($2) lookup
bins.cdbget "$2"
];
in depot.nix.utils.drvTargets {
inherit
router
notes-server
index
router-lookup
;
}