78 lines
No EOL
3.1 KiB
Nix
78 lines
No EOL
3.1 KiB
Nix
let
|
|
lib = import <nixpkgs/lib>;
|
|
|
|
allowedEndpointKeys = [ "type" "listenPort" "content" ];
|
|
allowedContentKeys = [ "host" "port" ];
|
|
|
|
ensureNoUnknownKeys = context: obj: allowedKeys:
|
|
let
|
|
unknown = builtins.filter (key: !(lib.elem key allowedKeys)) (builtins.attrNames obj);
|
|
in
|
|
if unknown != [] then
|
|
throw "${context} contains unknown keys: ${builtins.concatStringsSep ", " unknown}"
|
|
else
|
|
obj;
|
|
|
|
ensurePort = value:
|
|
builtins.isInt value && value > 0 && value <= 65535;
|
|
|
|
validateEndpointShape = index: endpoint:
|
|
let
|
|
_ = if builtins.isAttrs endpoint then null else throw "Endpoint at index ${toString index} must be an attrset.";
|
|
__ = ensureNoUnknownKeys "Endpoint at index ${toString index}" endpoint allowedEndpointKeys;
|
|
typeValue =
|
|
if endpoint ? type && builtins.isString endpoint.type then
|
|
endpoint.type
|
|
else
|
|
throw "Endpoint at index ${toString index} must define type as a string.";
|
|
_type =
|
|
if lib.elem typeValue [ "forwarding" "proxy" ] then
|
|
null
|
|
else
|
|
throw "Endpoint at index ${toString index} type must be 'forwarding' or 'proxy'.";
|
|
_listenPort =
|
|
if endpoint ? listenPort && ensurePort endpoint.listenPort then
|
|
null
|
|
else
|
|
throw "Endpoint at index ${toString index} must define listenPort as int in range 1..65535.";
|
|
contentValue =
|
|
if endpoint ? content then
|
|
endpoint.content
|
|
else
|
|
throw "Endpoint at index ${toString index} must define content.";
|
|
_content =
|
|
let
|
|
_attrs = if builtins.isAttrs contentValue then null else throw "Endpoint at index ${toString index} must define content as an attrset.";
|
|
____ = ensureNoUnknownKeys "Endpoint content at index ${toString index}" contentValue allowedContentKeys;
|
|
in
|
|
if !(contentValue ? port) || !ensurePort contentValue.port then
|
|
throw "Endpoint at index ${toString index} must define content.port as int in range 1..65535."
|
|
else if typeValue == "proxy" && (!(contentValue ? host) || !builtins.isString contentValue.host || contentValue.host == "") then
|
|
throw "Proxy endpoint at index ${toString index} must define content.host as non-empty string."
|
|
else if typeValue == "forwarding" && contentValue ? host then
|
|
throw "Forwarding endpoint at index ${toString index} must not define content.host."
|
|
else
|
|
null;
|
|
in
|
|
endpoint;
|
|
|
|
validateEndpointsShape = endpoints:
|
|
if !builtins.isList endpoints then
|
|
throw "config/endpoints.nix must evaluate to a list of endpoint attrsets."
|
|
else
|
|
lib.imap0 validateEndpointShape endpoints;
|
|
|
|
validateUniqueHostPath = endpoints:
|
|
let
|
|
keyFor = endpoint: toString endpoint.listenPort;
|
|
keys = map keyFor endpoints;
|
|
in
|
|
if builtins.length keys == builtins.length (lib.unique keys) then
|
|
endpoints
|
|
else
|
|
throw "Duplicate listenPort detected in config/endpoints.nix.";
|
|
in
|
|
{
|
|
getValidatedEndpoints = endpoints:
|
|
validateUniqueHostPath (validateEndpointsShape endpoints);
|
|
} |