Rename httpserver module to http
README.md
| 1 | - | <!-- | |
| 2 | - | SPDX-FileCopyrightText: 2021 Li Ian-Xue (b4283) <b4283@pm.me> | |
| 3 | - | SPDX-FileCopyrightText: 2025 Evgeny Pisemsky <mail@pisemsky.site> | |
| 1 | + | # guile-pastebin | |
| 4 | 2 | ||
| 5 | - | SPDX-License-Identifier: GPL-3.0-only | |
| 6 | - | --> | |
| 3 | + | Minimalist pastebin written in Guile Scheme. | |
| 7 | 4 | ||
| 8 | - | # guile-pastebin | |
| 5 | + | ## Usage | |
| 9 | 6 | ||
| 10 | - | A very simple pastebin written in Guile Scheme. | |
| 7 | + | Ensure Guile 3.0.9 (or later) is installed and execute the command: | |
| 11 | 8 | ||
| 12 | - | ## How to run | |
| 9 | + | ``` | |
| 10 | + | ./run pastebin data | |
| 11 | + | ``` | |
| 13 | 12 | ||
| 14 | - | Execute one of the following commands in the root of repository: | |
| 13 | + | Then navigate a web browser at `http://localhost:8080`. | |
| 14 | + | ||
| 15 | + | The full `pastebin` command synopsis is as follows: | |
| 15 | 16 | ||
| 16 | 17 | ``` | |
| 17 | - | guile -L modules scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 18 | - | GUILE_LOAD_PATH=modules scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 18 | + | pastebin [OPTIONS] <DATA_DIR> | |
| 19 | 19 | ``` | |
| 20 | 20 | ||
| 21 | - | Then navigate your web browser at `http://localhost:8080`. By default, | |
| 22 | - | pastebin listens on all IPv4 addresses (`0.0.0.0`) and runs on port | |
| 23 | - | `8080`. These can be changed by passing the command line options | |
| 24 | - | `--addr` and `--port`, respectively. | |
| 21 | + | `DATA_DIR` is a writable filesystem location to store pastes. | |
| 25 | 22 | ||
| 26 | - | `<DATA_DIR>` is a writable filesystem location you want to use to | |
| 27 | - | store pastes. If it doesn't exist, it will be created. | |
| 23 | + | Supported `OPTIONS` are following: | |
| 28 | 24 | ||
| 29 | - | It was tested on Guile 3.0.9. Many thanks to the Guile development | |
| 30 | - | team for such great software. | |
| 25 | + | * `--addr`: IPv4 address to listen on (default: `127.0.0.1`). | |
| 26 | + | * `--port`: port number to run pastebin on (default: `8080`). | |
| 31 | 27 | ||
| 32 | 28 | ## API | |
| 33 | 29 | ||
… | |||
| 48 | 44 | ||
| 49 | 45 | Notice the double-quotes around the parameters because `<` means IO | |
| 50 | 46 | redirection in sh. | |
| 47 | + | ||
| 48 | + | ## Acknowledgement | |
| 49 | + | ||
| 50 | + | This software was initially developed by Li Ian-Xue (b4283) at | |
| 51 | + | <https://github.com/b4284/guile-pastebin>. | |
| 52 | + | ||
| 53 | + | It is currently occasionally maintained by Evgeny Pisemsky at | |
| 54 | + | <https://repo.pisemsky.site/guile-pastebin>. | |
| 55 | + | ||
| 56 | + | ## Copying | |
| 57 | + | ||
| 58 | + | SPDX-FileCopyrightText: 2021 Li Ian-Xue (b4283) <b4283@pm.me> | |
| 59 | + | ||
| 60 | + | SPDX-FileCopyrightText: 2025 Evgeny Pisemsky <mail@pisemsky.site> | |
| 61 | + | ||
| 62 | + | SPDX-License-Identifier: GPL-3.0-only | |
modules/pastebin/http.scm unknown status 1
| 1 | + | ;;; SPDX-FileCopyrightText: 2021 Li Ian-Xue (b4283) <b4283@pm.me> | |
| 2 | + | ;;; SPDX-FileCopyrightText: 2025 Evgeny Pisemsky <mail@pisemsky.site> | |
| 3 | + | ;;; | |
| 4 | + | ;;; SPDX-License-Identifier: GPL-3.0-only | |
| 5 | + | ||
| 6 | + | (define-module (pastebin http)) | |
| 7 | + | ||
| 8 | + | (use-modules (web request) | |
| 9 | + | (web response) | |
| 10 | + | (web uri) | |
| 11 | + | (sxml simple) | |
| 12 | + | (pastebin data) | |
| 13 | + | (rnrs bytevectors) | |
| 14 | + | (ice-9 textual-ports) | |
| 15 | + | (ice-9 binary-ports) | |
| 16 | + | (ice-9 regex) | |
| 17 | + | (ice-9 match) | |
| 18 | + | (srfi srfi-1)) | |
| 19 | + | ||
| 20 | + | (export make-pastebin-handler) | |
| 21 | + | ||
| 22 | + | (define (read-parts reqbody boundary) | |
| 23 | + | (define b2 (string-append "(\r\n)?--" boundary)) | |
| 24 | + | (let A ((start 0) (parts '())) | |
| 25 | + | (let ((sm (string-match b2 reqbody start))) | |
| 26 | + | (if sm | |
| 27 | + | ;; +2 => CRLF | |
| 28 | + | (A (+ 2 (match:end sm 0)) | |
| 29 | + | (cons (substring reqbody start (match:start sm 0)) parts)) | |
| 30 | + | (cdr (reverse parts)))))) | |
| 31 | + | ||
| 32 | + | (define (get-new-pin str pin) | |
| 33 | + | (let ((crlfi (string-contains str "\r\n" pin))) | |
| 34 | + | (if crlfi crlfi (string-length str)))) | |
| 35 | + | ||
| 36 | + | (define (parse-part partstr) | |
| 37 | + | (let A ((headers '()) (pin 0)) | |
| 38 | + | (let* ((newpin (get-new-pin partstr pin)) | |
| 39 | + | (line (substring partstr pin newpin))) | |
| 40 | + | (if (string-null? line) | |
| 41 | + | (cons (reverse headers) (substring partstr (+ 2 newpin))) | |
| 42 | + | (A (cons line headers) (+ 2 newpin)))))) | |
| 43 | + | ||
| 44 | + | (define (get-content-dispo-name-from-headers headers) | |
| 45 | + | (let ((fl (find (lambda (line) (string-prefix-ci? "content-disposition: " line)) headers))) | |
| 46 | + | (if fl | |
| 47 | + | (let ((sm (string-match "name=(.*)" fl))) | |
| 48 | + | (if sm (string-trim-both (match:substring sm 1) #\") "")) | |
| 49 | + | ""))) | |
| 50 | + | ||
| 51 | + | (define (read-multipart-form-data reqbody boundary) | |
| 52 | + | (define parts (read-parts reqbody boundary)) | |
| 53 | + | (map | |
| 54 | + | (lambda (part) | |
| 55 | + | (let ((pp (parse-part part))) | |
| 56 | + | (cons (get-content-dispo-name-from-headers (car pp)) (cdr pp)))) | |
| 57 | + | parts)) | |
| 58 | + | ||
| 59 | + | (define (not-found) | |
| 60 | + | (values (build-response #:code 404) | |
| 61 | + | (lambda (port) 1))) | |
| 62 | + | ||
| 63 | + | (define (templatize title body) | |
| 64 | + | `(html (@ (lang "en")) | |
| 65 | + | (head | |
| 66 | + | (title ,title) | |
| 67 | + | (meta (@ (charset "utf-8"))) | |
| 68 | + | (meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0"))) | |
| 69 | + | (link (@ (rel "stylesheet") (href "https://unpkg.com/simpledotcss/simple.min.css")))) | |
| 70 | + | (body ,@body))) | |
| 71 | + | ||
| 72 | + | (define (list-handler pb-data-path) | |
| 73 | + | (values (build-response | |
| 74 | + | #:code 200 | |
| 75 | + | #:headers '((content-type . (text/html)))) | |
| 76 | + | (lambda (port) | |
| 77 | + | (let* ((top5 (call-with-dir-as-pb-data | |
| 78 | + | pb-data-path | |
| 79 | + | (lambda (pb-data) | |
| 80 | + | (pb-data-get-top pb-data 5)))) | |
| 81 | + | (sxml (templatize | |
| 82 | + | "Pastebin" | |
| 83 | + | `((header (h1 "Pastebin")) | |
| 84 | + | (main (section (h2 "Recent") | |
| 85 | + | ,(map (lambda (entry) | |
| 86 | + | `(article (h3 (a (@ (href ,(format #f "/raw/~a" (pb-entry-id entry))) | |
| 87 | + | (target "_blank")) | |
| 88 | + | ,(pb-entry-id entry))) | |
| 89 | + | (pre ,(pb-entry-text entry)))) | |
| 90 | + | top5)) | |
| 91 | + | (section (h2 "New") | |
| 92 | + | (form (@ (method "post") | |
| 93 | + | (enctype "multipart/form-data") | |
| 94 | + | (action "/post")) | |
| 95 | + | (fieldset (div (label (@ (for "form-text")) | |
| 96 | + | "Paste content")) | |
| 97 | + | (div (textarea (@ (id "form-text") | |
| 98 | + | (name "text")) "")) | |
| 99 | + | (div (label (@ (for "form-showurl")) | |
| 100 | + | (input (@ (type "checkbox") | |
| 101 | + | (id "form-showurl") | |
| 102 | + | (name "showUrl") | |
| 103 | + | (value "1"))) | |
| 104 | + | "Show raw URL after paste")) | |
| 105 | + | (div (input (@ (type "submit") | |
| 106 | + | (value "Submit")))))))) | |
| 107 | + | (footer (p (a (@ (href "https://repo.pisemsky.site/guile-pastebin") | |
| 108 | + | (target "_blank")) | |
| 109 | + | "Source"))))))) | |
| 110 | + | (display "<!DOCTYPE html>\n" port) | |
| 111 | + | (sxml->xml sxml port))))) | |
| 112 | + | ||
| 113 | + | (define (post-handler request request-body pb-data-path) | |
| 114 | + | (if (eq? (request-method request) 'POST) | |
| 115 | + | (let* ((headers (request-headers request)) | |
| 116 | + | (content-type-all (assq-ref headers 'content-type)) | |
| 117 | + | (content-type (if content-type-all | |
| 118 | + | (car content-type-all) | |
| 119 | + | #f)) | |
| 120 | + | (boundary (if (eq? content-type 'multipart/form-data) | |
| 121 | + | (assq-ref (cdr content-type-all) 'boundary) | |
| 122 | + | #f)) | |
| 123 | + | (reqbody-string (utf8->string request-body)) | |
| 124 | + | (form-data (if boundary | |
| 125 | + | (read-multipart-form-data reqbody-string boundary) | |
| 126 | + | #f)) | |
| 127 | + | (new-pb-data (if form-data | |
| 128 | + | (call-with-dir-as-pb-data | |
| 129 | + | pb-data-path | |
| 130 | + | (lambda (pb-data) | |
| 131 | + | (pb-data-new-entry pb-data | |
| 132 | + | (assoc-ref form-data "text")))) | |
| 133 | + | #f))) | |
| 134 | + | ||
| 135 | + | ;; determine what to respond | |
| 136 | + | (if (and new-pb-data | |
| 137 | + | (assoc-ref form-data "showUrl")) | |
| 138 | + | ||
| 139 | + | ;; show url after paste | |
| 140 | + | (values (build-response | |
| 141 | + | #:code 200 | |
| 142 | + | #:headers '((content-type . (text/plain)))) | |
| 143 | + | (lambda (port) | |
| 144 | + | (let* ((hostp (assq-ref headers 'host)) | |
| 145 | + | (proto (assq-ref headers 'x-forwarded-proto))) | |
| 146 | + | (put-string | |
| 147 | + | port | |
| 148 | + | (uri->string | |
| 149 | + | (build-uri (if (equal? proto "https") 'https 'http) | |
| 150 | + | #:host (car hostp) | |
| 151 | + | #:port (cdr hostp) | |
| 152 | + | #:path (format #f "/raw/~a\r\n" | |
| 153 | + | (pb-entry-id new-pb-data)))))))) | |
| 154 | + | ||
| 155 | + | ;; respond with 303 See Other | |
| 156 | + | (values (build-response | |
| 157 | + | #:code 303 | |
| 158 | + | #:headers `((location . ,(build-uri-reference #:path "/")))) | |
| 159 | + | (lambda (port) 1)))) | |
| 160 | + | ||
| 161 | + | ;; INVALID request: access /post without HTTP POST | |
| 162 | + | (values (build-response #:code 400) | |
| 163 | + | (lambda (port) 1)))) | |
| 164 | + | ||
| 165 | + | (define (raw-handler pb-data-path pb-id) | |
| 166 | + | (if (pb-entry-id-valid? pb-id) | |
| 167 | + | (values (build-response | |
| 168 | + | #:code 200 | |
| 169 | + | #:headers '((content-type . (text/plain)))) | |
| 170 | + | (lambda (port) | |
| 171 | + | (call-with-input-file | |
| 172 | + | ;; the file name | |
| 173 | + | (call-with-dir-as-pb-data | |
| 174 | + | pb-data-path | |
| 175 | + | (lambda (p) (pb-get-file-path p pb-id))) | |
| 176 | + | ;; the input port | |
| 177 | + | (lambda (inport) | |
| 178 | + | (let A ((inport' inport)) | |
| 179 | + | (let ((bv (get-bytevector-n inport' 4096))) | |
| 180 | + | (if (not (eof-object? bv)) | |
| 181 | + | (begin | |
| 182 | + | (put-bytevector port bv) | |
| 183 | + | (A inport'))))))))) | |
| 184 | + | (not-found))) | |
| 185 | + | ||
| 186 | + | (define (make-pastebin-handler data-path) | |
| 187 | + | (lambda (request request-body) | |
| 188 | + | (match (split-and-decode-uri-path (uri-path (request-uri request))) | |
| 189 | + | (() | |
| 190 | + | (list-handler data-path)) | |
| 191 | + | (("post") | |
| 192 | + | (post-handler request request-body data-path)) | |
| 193 | + | (("raw" pb-id) | |
| 194 | + | (raw-handler data-path pb-id)) | |
| 195 | + | (_ | |
| 196 | + | (not-found))))) |
modules/pastebin/httpserver.scm unknown status 2
| 1 | - | ;;; SPDX-FileCopyrightText: 2021 Li Ian-Xue (b4283) <b4283@pm.me> | |
| 2 | - | ;;; SPDX-FileCopyrightText: 2025 Evgeny Pisemsky <mail@pisemsky.site> | |
| 3 | - | ;;; | |
| 4 | - | ;;; SPDX-License-Identifier: GPL-3.0-only | |
| 5 | - | ||
| 6 | - | (define-module (pastebin httpserver)) | |
| 7 | - | ||
| 8 | - | (use-modules (web request) | |
| 9 | - | (web response) | |
| 10 | - | (web uri) | |
| 11 | - | (sxml simple) | |
| 12 | - | (pastebin data) | |
| 13 | - | (rnrs bytevectors) | |
| 14 | - | (ice-9 textual-ports) | |
| 15 | - | (ice-9 binary-ports) | |
| 16 | - | (ice-9 regex) | |
| 17 | - | (ice-9 match) | |
| 18 | - | (srfi srfi-1)) | |
| 19 | - | ||
| 20 | - | (export make-pastebin-handler) | |
| 21 | - | ||
| 22 | - | (define (read-parts reqbody boundary) | |
| 23 | - | (define b2 (string-append "(\r\n)?--" boundary)) | |
| 24 | - | (let A ((start 0) (parts '())) | |
| 25 | - | (let ((sm (string-match b2 reqbody start))) | |
| 26 | - | (if sm | |
| 27 | - | ;; +2 => CRLF | |
| 28 | - | (A (+ 2 (match:end sm 0)) | |
| 29 | - | (cons (substring reqbody start (match:start sm 0)) parts)) | |
| 30 | - | (cdr (reverse parts)))))) | |
| 31 | - | ||
| 32 | - | (define (get-new-pin str pin) | |
| 33 | - | (let ((crlfi (string-contains str "\r\n" pin))) | |
| 34 | - | (if crlfi crlfi (string-length str)))) | |
| 35 | - | ||
| 36 | - | (define (parse-part partstr) | |
| 37 | - | (let A ((headers '()) (pin 0)) | |
| 38 | - | (let* ((newpin (get-new-pin partstr pin)) | |
| 39 | - | (line (substring partstr pin newpin))) | |
| 40 | - | (if (string-null? line) | |
| 41 | - | (cons (reverse headers) (substring partstr (+ 2 newpin))) | |
| 42 | - | (A (cons line headers) (+ 2 newpin)))))) | |
| 43 | - | ||
| 44 | - | (define (get-content-dispo-name-from-headers headers) | |
| 45 | - | (let ((fl (find (lambda (line) (string-prefix-ci? "content-disposition: " line)) headers))) | |
| 46 | - | (if fl | |
| 47 | - | (let ((sm (string-match "name=(.*)" fl))) | |
| 48 | - | (if sm (string-trim-both (match:substring sm 1) #\") "")) | |
| 49 | - | ""))) | |
| 50 | - | ||
| 51 | - | (define (read-multipart-form-data reqbody boundary) | |
| 52 | - | (define parts (read-parts reqbody boundary)) | |
| 53 | - | (map | |
| 54 | - | (lambda (part) | |
| 55 | - | (let ((pp (parse-part part))) | |
| 56 | - | (cons (get-content-dispo-name-from-headers (car pp)) (cdr pp)))) | |
| 57 | - | parts)) | |
| 58 | - | ||
| 59 | - | (define (not-found) | |
| 60 | - | (values (build-response #:code 404) | |
| 61 | - | (lambda (port) 1))) | |
| 62 | - | ||
| 63 | - | (define (templatize title body) | |
| 64 | - | `(html (@ (lang "en")) | |
| 65 | - | (head | |
| 66 | - | (title ,title) | |
| 67 | - | (meta (@ (charset "utf-8"))) | |
| 68 | - | (meta (@ (name "viewport") (content "width=device-width, initial-scale=1.0"))) | |
| 69 | - | (link (@ (rel "stylesheet") (href "https://unpkg.com/simpledotcss/simple.min.css")))) | |
| 70 | - | (body ,@body))) | |
| 71 | - | ||
| 72 | - | (define (list-handler pb-data-path) | |
| 73 | - | (values (build-response | |
| 74 | - | #:code 200 | |
| 75 | - | #:headers '((content-type . (text/html)))) | |
| 76 | - | (lambda (port) | |
| 77 | - | (let* ((top5 (call-with-dir-as-pb-data | |
| 78 | - | pb-data-path | |
| 79 | - | (lambda (pb-data) | |
| 80 | - | (pb-data-get-top pb-data 5)))) | |
| 81 | - | (sxml (templatize | |
| 82 | - | "Pastebin" | |
| 83 | - | `((header (h1 "Pastebin")) | |
| 84 | - | (main (section (h2 "Recent") | |
| 85 | - | ,(map (lambda (entry) | |
| 86 | - | `(article (h3 (a (@ (href ,(format #f "/raw/~a" (pb-entry-id entry))) | |
| 87 | - | (target "_blank")) | |
| 88 | - | ,(pb-entry-id entry))) | |
| 89 | - | (pre ,(pb-entry-text entry)))) | |
| 90 | - | top5)) | |
| 91 | - | (section (h2 "New") | |
| 92 | - | (form (@ (method "post") | |
| 93 | - | (enctype "multipart/form-data") | |
| 94 | - | (action "/post")) | |
| 95 | - | (fieldset (div (label (@ (for "form-text")) | |
| 96 | - | "Paste content")) | |
| 97 | - | (div (textarea (@ (id "form-text") | |
| 98 | - | (name "text")) "")) | |
| 99 | - | (div (label (@ (for "form-showurl")) | |
| 100 | - | (input (@ (type "checkbox") | |
| 101 | - | (id "form-showurl") | |
| 102 | - | (name "showUrl") | |
| 103 | - | (value "1"))) | |
| 104 | - | "Show raw URL after paste")) | |
| 105 | - | (div (input (@ (type "submit") | |
| 106 | - | (value "Submit")))))))) | |
| 107 | - | (footer (p (a (@ (href "https://github.com/pisemsky/guile-pastebin") | |
| 108 | - | (target "_blank")) | |
| 109 | - | "Source"))))))) | |
| 110 | - | (display "<!DOCTYPE html>\n" port) | |
| 111 | - | (sxml->xml sxml port))))) | |
| 112 | - | ||
| 113 | - | (define (post-handler request request-body pb-data-path) | |
| 114 | - | (if (eq? (request-method request) 'POST) | |
| 115 | - | (let* ((headers (request-headers request)) | |
| 116 | - | (content-type-all (assq-ref headers 'content-type)) | |
| 117 | - | (content-type (if content-type-all | |
| 118 | - | (car content-type-all) | |
| 119 | - | #f)) | |
| 120 | - | (boundary (if (eq? content-type 'multipart/form-data) | |
| 121 | - | (assq-ref (cdr content-type-all) 'boundary) | |
| 122 | - | #f)) | |
| 123 | - | (reqbody-string (utf8->string request-body)) | |
| 124 | - | (form-data (if boundary | |
| 125 | - | (read-multipart-form-data reqbody-string boundary) | |
| 126 | - | #f)) | |
| 127 | - | (new-pb-data (if form-data | |
| 128 | - | (call-with-dir-as-pb-data | |
| 129 | - | pb-data-path | |
| 130 | - | (lambda (pb-data) | |
| 131 | - | (pb-data-new-entry pb-data | |
| 132 | - | (assoc-ref form-data "text")))) | |
| 133 | - | #f))) | |
| 134 | - | ||
| 135 | - | ;; determine what to respond | |
| 136 | - | (if (and new-pb-data | |
| 137 | - | (assoc-ref form-data "showUrl")) | |
| 138 | - | ||
| 139 | - | ;; show url after paste | |
| 140 | - | (values (build-response | |
| 141 | - | #:code 200 | |
| 142 | - | #:headers '((content-type . (text/plain)))) | |
| 143 | - | (lambda (port) | |
| 144 | - | (let* ((hostp (assq-ref headers 'host)) | |
| 145 | - | (proto (assq-ref headers 'x-forwarded-proto))) | |
| 146 | - | (put-string | |
| 147 | - | port | |
| 148 | - | (uri->string | |
| 149 | - | (build-uri (if (equal? proto "https") 'https 'http) | |
| 150 | - | #:host (car hostp) | |
| 151 | - | #:port (cdr hostp) | |
| 152 | - | #:path (format #f "/raw/~a\r\n" | |
| 153 | - | (pb-entry-id new-pb-data)))))))) | |
| 154 | - | ||
| 155 | - | ;; respond with 303 See Other | |
| 156 | - | (values (build-response | |
| 157 | - | #:code 303 | |
| 158 | - | #:headers `((location . ,(build-uri-reference #:path "/")))) | |
| 159 | - | (lambda (port) 1)))) | |
| 160 | - | ||
| 161 | - | ;; INVALID request: access /post without HTTP POST | |
| 162 | - | (values (build-response #:code 400) | |
| 163 | - | (lambda (port) 1)))) | |
| 164 | - | ||
| 165 | - | (define (raw-handler pb-data-path pb-id) | |
| 166 | - | (if (pb-entry-id-valid? pb-id) | |
| 167 | - | (values (build-response | |
| 168 | - | #:code 200 | |
| 169 | - | #:headers '((content-type . (text/plain)))) | |
| 170 | - | (lambda (port) | |
| 171 | - | (call-with-input-file | |
| 172 | - | ;; the file name | |
| 173 | - | (call-with-dir-as-pb-data | |
| 174 | - | pb-data-path | |
| 175 | - | (lambda (p) (pb-get-file-path p pb-id))) | |
| 176 | - | ;; the input port | |
| 177 | - | (lambda (inport) | |
| 178 | - | (let A ((inport' inport)) | |
| 179 | - | (let ((bv (get-bytevector-n inport' 4096))) | |
| 180 | - | (if (not (eof-object? bv)) | |
| 181 | - | (begin | |
| 182 | - | (put-bytevector port bv) | |
| 183 | - | (A inport'))))))))) | |
| 184 | - | (not-found))) | |
| 185 | - | ||
| 186 | - | (define (make-pastebin-handler data-path) | |
| 187 | - | (lambda (request request-body) | |
| 188 | - | (match (split-and-decode-uri-path (uri-path (request-uri request))) | |
| 189 | - | ||
| 190 | - | ;; URI: / -- show the top 5 paste list | |
| 191 | - | (() | |
| 192 | - | (list-handler data-path)) | |
| 193 | - | ||
| 194 | - | ;; URI: /post -- create paste | |
| 195 | - | (("post") | |
| 196 | - | (post-handler request request-body data-path)) | |
| 197 | - | ||
| 198 | - | ;; URI: /raw/<id> -- return raw content of the paste | |
| 199 | - | (("raw" pb-id) | |
| 200 | - | (raw-handler data-path pb-id)) | |
| 201 | - | ||
| 202 | - | ;; URI: * -- everything else -- show 404 error | |
| 203 | - | (_ | |
| 204 | - | (not-found))))) |
modules/pastebin/main.scm
| 5 | 5 | ||
| 6 | 6 | (define-module (pastebin main)) | |
| 7 | 7 | ||
| 8 | - | (use-modules (pastebin httpserver) | |
| 8 | + | (use-modules (pastebin http) | |
| 9 | 9 | (ice-9 getopt-long) | |
| 10 | 10 | (web server)) | |
| 11 | 11 | ||
… | |||
| 16 | 16 | (port (value #t)))) | |
| 17 | 17 | (options (getopt-long args option-spec)) | |
| 18 | 18 | (data-dir (car (option-ref options '() '()))) | |
| 19 | - | (addr-str (option-ref options 'addr "0.0.0.0")) | |
| 19 | + | (addr-str (option-ref options 'addr "127.0.0.1")) | |
| 20 | 20 | (port-str (option-ref options 'port "8080"))) | |
| 21 | 21 | (if (not (file-exists? data-dir)) | |
| 22 | 22 | (mkdir data-dir)) | |
tests/pastebin-http
| 11 | 11 | (web uri) | |
| 12 | 12 | (web request) | |
| 13 | 13 | (web response) | |
| 14 | - | (pastebin httpserver)) | |
| 14 | + | (pastebin http)) | |
| 15 | 15 | ||
| 16 | 16 | (test-begin "pastebin-http") | |
| 17 | 17 |