diff options
| author | Jakob L. Kreuze | 2026-07-10 16:05:16 -0400 |
|---|---|---|
| committer | Jakob L. Kreuze | 2026-07-10 16:05:16 -0400 |
| commit | d6472d2ee6a5a3f4b85a0cf4aec269915e4929d9 (patch) | |
| tree | 17724373c33981f18c0f7bef3efba6d012e160ae | |
| parent | 5a298f0550cf6eab5b8be7784d3f76695cf59bec (diff) | |
Regex transformation for router
| -rw-r--r-- | tests/router.scm | 33 | ||||
| -rw-r--r-- | weeb/router.scm | 38 |
2 files changed, 71 insertions, 0 deletions
diff --git a/tests/router.scm b/tests/router.scm new file mode 100644 index 0000000..5bdbd51 --- /dev/null +++ b/tests/router.scm @@ -0,0 +1,33 @@ +(use-modules (srfi srfi-11) + (srfi srfi-64) + (weeb router)) + +;; Private imports for testing purposes. +(define uri-template->regexp-string + (@@ (weeb router) uri-template->regexp-string)) + +(test-runner-current (test-runner-simple)) + +(test-begin "weeb-router") + +(test-group "simple static route" + (let-values (((re vars) (uri-template->regexp-string "/health"))) + (test-equal "/health" re) + (test-equal '() vars))) + +(test-group "single variable route" + (let-values (((re vars) (uri-template->regexp-string "/user/:id:"))) + (test-equal "/user/([^/]+)" re) + (test-equal '(id) vars))) + +(test-group "multiple variables with trailing slash" + (let-values (((re vars) (uri-template->regexp-string "/org/:org_id:/user/:user_id:/"))) + (test-equal "/org/([^/]+)/user/([^/]+)" re) + (test-equal '(org_id user_id) vars))) + +(test-group "middle variables" + (let-values (((re vars) (uri-template->regexp-string "/api/:version:/data"))) + (test-equal "/api/([^/]+)/data" re) + (test-equal '(version) vars))) + +(test-end) diff --git a/weeb/router.scm b/weeb/router.scm new file mode 100644 index 0000000..8c4b502 --- /dev/null +++ b/weeb/router.scm @@ -0,0 +1,38 @@ +;;; Weeb --- Web microframework for GNU Guile +;;; Copyright © 2026 Jakob Kreuze <zerodaysfordays@sdf.org> +;;; +;;; This file is part of Weeb. +;;; +;;; Weeb is free software: you can redistribute it and/or modify it +;;; under the terms of the GNU Affero General Public License as +;;; published by the Free Software Foundation, either version 3 of the +;;; License, or (at your option) any later version. +;;; +;;; Weeb is distributed in the hope that it will be useful, but WITHOUT +;;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +;;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General +;;; Public License for more details. +;;; +;;; You should have received a copy of the GNU Affero General Public +;;; License along with Weeb. If not, see <https://www.gnu.org/licenses/>. + +(define-module (weeb router) + #:use-module (ice-9 regex) + #:use-module (weeb struct) + #:export (define-router)) + +(define (uri-template->regexp-string template) + ;; TODO: Assert that the first character is a slash. + (define trailing-slash? (string-match ".*/$" template)) + (define components + (map (lambda (component) + (let ((variable-match (string-match ":(.*):" component))) + (if variable-match + (list (string->symbol (match:substring variable-match 1)) "([^/]+)") + (list #f component)))) + (string-split (if trailing-slash? + (substring template 1 (- (string-length template) 1)) + (substring template 1)) + #\/))) + (values (string-append "/" (string-join (map cadr components) "/")) + (filter symbol? (map car components)))) |