diff options
| author | Jakob L. Kreuze | 2026-07-12 13:10:26 -0400 |
|---|---|---|
| committer | Jakob L. Kreuze | 2026-07-12 16:06:29 -0400 |
| commit | af5bfb83713b269b53dfa98a0941df81fee67e92 (patch) | |
| tree | 3b5c34367ea2c9734c6f5f9786d1b843061bdd58 /weeb | |
| parent | 7cec907b8bad9973222d3a261167f62d44a8be8b (diff) | |
Implement `parse-form-urlencoded'
Diffstat (limited to 'weeb')
| -rw-r--r-- | weeb/main.scm | 10 | ||||
| -rw-r--r-- | weeb/request.scm | 28 |
2 files changed, 35 insertions, 3 deletions
diff --git a/weeb/main.scm b/weeb/main.scm index 7487f19..b6e47ec 100644 --- a/weeb/main.scm +++ b/weeb/main.scm @@ -110,6 +110,11 @@ (match-lambda ("GET" 'GET) ("POST" 'POST))) + (define (strip-query-string uri) + (let ((match-object (string-match "^(/.*)\\?" uri))) + (if match-object + (match:substring match-object 1) + uri))) ;; According to RFC 9110, header names must be treated as case-insensitive. (define headers (filter-map @@ -125,8 +130,9 @@ #f))) (environ))) (let* ((method (string->method (getenv "REQUEST_METHOD"))) - (uri (getenv "REQUEST_URI"))) - (make-struct <request> method uri '() headers (fcgi-read)))) + (query (parse-form-urlencoded (getenv "QUERY_STRING"))) + (uri (strip-query-string (getenv "REQUEST_URI")))) + (make-struct <request> method uri query headers (fcgi-read)))) (define (handle-errors thunk) (catch #t diff --git a/weeb/request.scm b/weeb/request.scm index 42cd933..3d18b0a 100644 --- a/weeb/request.scm +++ b/weeb/request.scm @@ -17,8 +17,34 @@ ;;; License along with Weeb. If not, see <https://www.gnu.org/licenses/>. (define-module (weeb request) + #:use-module (ice-9 match) #:use-module (weeb struct) - #:export (<request>)) + #:export (<request> + urldecode + parse-form-urlencoded)) (define-struct <request> method uri parameters headers body) + +(define (urldecode str) + (let loop ((i 0) (acc "")) + (cond + ((>= i (string-length str)) acc) + ((char=? (string-ref str i) #\+) + (loop (+ i 1) (string-append acc " "))) + ((and (char=? (string-ref str i) #\%) + (<= (+ i 2) (string-length str))) + (let* ((hex-part (substring str (+ i 1) (+ i 3))) + (code (string->number hex-part 16))) + (if code + (loop (+ i 3) (string-append acc (string (integer->char code)))) + (loop (+ i 1) (string-append acc (string (string-ref str i))))))) + (else + (loop (+ i 1) (string-append acc (string (string-ref str i)))))))) + +(define (parse-form-urlencoded encoded) + (map (lambda (encoded-pair) + (match (map urldecode (string-split encoded-pair #\=)) + ((key value) `(,key . ,value)))) + (filter (lambda (x) (not (zero? (string-length x)))) + (string-split encoded #\&)))) |