taler-typescript-core

Wallet core logic and WebUIs for various components
Log | Files | Refs | Submodules | README | LICENSE

commit 55786cd92516c578216465a7ee5eaba5288b950d
parent f350a371605a98cdad36026dcc699ae844782584
Author: Florian Dold <dold@taler.net>
Date:   Tue, 21 Jul 2026 20:18:26 +0200

util: make codecForURLString validate its value

Diffstat:
Mpackages/taler-util/src/codec.ts | 42++++++++++++++++++++++++++++++++++++++++++
Mpackages/taler-util/src/types-taler-common.ts | 8++++++--
2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/packages/taler-util/src/codec.ts b/packages/taler-util/src/codec.ts @@ -493,6 +493,48 @@ export function codecForStringUnion<T extends Array<string>>( } /** + * Return a codec for a string that must be an absolute http(s) URL. + * + * Parsing alone is not enough for the fields this guards: they are opened by + * the browser or fetched over HTTP, and "javascript:", "data:" and "file:" + * are all perfectly well-formed URLs. + */ +export function codecForHttpUrlString( + shouldEndWithSlash?: boolean, +): Codec<string> { + return { + decode(x: any, c?: Context): string { + if (typeof x !== "string") { + throw new DecodingError( + `expected string at ${renderContext(c)} but got ${typeof x}`, + ); + } + if (shouldEndWithSlash && !x.endsWith("/")) { + throw new DecodingError( + `expected URL string that ends with slash at ${renderContext( + c, + )} but got ${x}`, + ); + } + let url: URL; + try { + url = new URL(x); + } catch (e) { + throw new DecodingError( + `expected an absolute URL at ${renderContext(c)} but got "${x}"`, + ); + } + if (url.protocol !== "http:" && url.protocol !== "https:") { + throw new DecodingError( + `expected an http(s) URL at ${renderContext(c)} but got "${x}"`, + ); + } + return x; + }, + }; +} + +/** * Return a codec for a value that must be a string. */ export function codecForStringURL(shouldEndWithSlash?: boolean): Codec<string> { diff --git a/packages/taler-util/src/types-taler-common.ts b/packages/taler-util/src/types-taler-common.ts @@ -38,6 +38,7 @@ import { codecForList, codecForMap, codecForNumber, + codecForHttpUrlString, codecForString, codecOptional, } from "./codec.js"; @@ -202,8 +203,11 @@ declare const __eddsapriv_str: unique symbol; export type EddsaPrivateKeyString = string; // & { [__eddsapriv_str]: true }; export type CoinPublicKeyString = string; -// FIXME: implement this codec -export const codecForURLString = codecForString; +/** + * Every field decoded with this is documented as an absolute URL that is + * either opened in a browser or used as the base of an HTTP request. + */ +export const codecForURLString = codecForHttpUrlString; // FIXME: implement this codec export const codecForLibtoolVersion = codecForString; // FIXME: implement this codec