Constrain urls
README.md
| 14 | 14 | Execute one of the following commands in the root of repository: | |
| 15 | 15 | ||
| 16 | 16 | ``` | |
| 17 | - | guile -L modules --no-auto-compile scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 18 | - | GUILE_LOAD_PATH=modules GUILE_AUTO_COMPILE=0 scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 17 | + | guile -L modules scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 18 | + | GUILE_LOAD_PATH=modules scripts/pastebin [OPTIONS] <DATA_DIR> | |
| 19 | 19 | ``` | |
| 20 | 20 | ||
| 21 | 21 | Then navigate your web browser at `http://localhost:8080`. By default, | |
… | |||
| 31 | 31 | ||
| 32 | 32 | ## API | |
| 33 | 33 | ||
| 34 | + | - `/` -- show top 5 paste list | |
| 34 | 35 | - `/post` -- create paste | |
| 35 | 36 | - method: POST only | |
| 36 | 37 | - type: `multipart/form-data` | |
… | |||
| 39 | 40 | - `showUrl=1` -- to show the raw URL after paste | |
| 40 | 41 | - `/raw/<ID>` -- get paste content | |
| 41 | 42 | - method: GET only | |
| 42 | - | - Anything else -- show top 5 paste list | |
| 43 | 43 | ||
| 44 | 44 | ## Paste a file from command line | |
| 45 | 45 | ||
… | |||
| 48 | 48 | ||
| 49 | 49 | Notice the double-quotes around the parameters because `<` means IO | |
| 50 | 50 | redirection in sh. | |
| 51 | - | ||
| 52 | - | ## Reverse Proxy | |
| 53 | - | ||
| 54 | - | It may be desirable to setup a reverse proxy on Apache Httpd (also a memo | |
| 55 | - | for myself), so you don't have to expose the 8080 or whatever port: | |
| 56 | - | ||
| 57 | - | ``` | |
| 58 | - | <Location "/pastebin"> | |
| 59 | - | ProxyPass "http://your_address:8080" | |
| 60 | - | ProxyPassReverse "http://your_address:8080" | |
| 61 | - | ProxyHTMLEnable On | |
| 62 | - | ProxyHTMLDocType "<!DOCTYPE html>" | |
| 63 | - | ProxyHTMLURLMap "/" "/pastebin/" | |
| 64 | - | </Location> | |
| 65 | - | ``` | |
modules/pastebin/httpserver.scm
| 56 | 56 | (cons (get-content-dispo-name-from-headers (car pp)) (cdr pp)))) | |
| 57 | 57 | parts)) | |
| 58 | 58 | ||
| 59 | + | (define (not-found) | |
| 60 | + | (values (build-response #:code 404) | |
| 61 | + | (lambda (port) 1))) | |
| 62 | + | ||
| 59 | 63 | (define (templatize title body) | |
| 60 | 64 | `(html (@ (lang "en")) | |
| 61 | 65 | (head | |
… | |||
| 65 | 69 | (link (@ (rel "stylesheet") (href "https://unpkg.com/simpledotcss/simple.min.css")))) | |
| 66 | 70 | (body ,@body))) | |
| 67 | 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 | + | (p (label "Paste content" | |
| 96 | + | (textarea (@ (name "text")) ""))) | |
| 97 | + | (p (label (input (@ (type "checkbox") | |
| 98 | + | (name "showUrl") | |
| 99 | + | (value "1"))) | |
| 100 | + | "Show raw URL after paste")) | |
| 101 | + | (input (@ (type "submit")))))) | |
| 102 | + | (footer (p (a (@ (href "https://github.com/pisemsky/guile-pastebin") | |
| 103 | + | (target "_blank")) | |
| 104 | + | "Source code"))))))) | |
| 105 | + | (display "<!DOCTYPE html>\n" port) | |
| 106 | + | (sxml->xml sxml port))))) | |
| 107 | + | ||
| 68 | 108 | (define (post-handler request request-body pb-data-path) | |
| 69 | 109 | (if (eq? (request-method request) 'POST) | |
| 70 | 110 | (let* ((headers (request-headers request)) | |
… | |||
| 135 | 175 | (begin | |
| 136 | 176 | (put-bytevector port bv) | |
| 137 | 177 | (A inport'))))))))) | |
| 138 | - | (values (build-response #:code 404) | |
| 139 | - | (lambda (port) 1)))) | |
| 178 | + | (not-found))) | |
| 140 | 179 | ||
| 141 | 180 | (define (make-pastebin-handler data-path) | |
| 142 | 181 | (lambda (request request-body) | |
| 143 | 182 | (match (split-and-decode-uri-path (uri-path (request-uri request))) | |
| 144 | 183 | ||
| 184 | + | ;; URI: / -- show the top 5 paste list | |
| 185 | + | (() | |
| 186 | + | (list-handler data-path)) | |
| 187 | + | ||
| 145 | 188 | ;; URI: /post -- create paste | |
| 146 | - | (("post" . _) | |
| 189 | + | (("post") | |
| 147 | 190 | (post-handler request request-body data-path)) | |
| 148 | 191 | ||
| 149 | 192 | ;; URI: /raw/<id> -- return raw content of the paste | |
| 150 | 193 | (("raw" pb-id) | |
| 151 | 194 | (raw-handler data-path pb-id)) | |
| 152 | 195 | ||
| 153 | - | ;; URI: * -- everything else -- show the top 5 paste list | |
| 196 | + | ;; URI: * -- everything else -- show 404 error | |
| 154 | 197 | (_ | |
| 155 | - | (values (build-response | |
| 156 | - | #:code 200 | |
| 157 | - | #:headers '((content-type . (text/html)))) | |
| 158 | - | ||
| 159 | - | (lambda (port) | |
| 160 | - | (let* ((top5 (call-with-dir-as-pb-data | |
| 161 | - | data-path | |
| 162 | - | (lambda (pb-data) (pb-data-get-top pb-data 5)))) | |
| 163 | - | (sxml (templatize | |
| 164 | - | "Pastebin" | |
| 165 | - | `((header (h1 "Pastebin")) | |
| 166 | - | (main (section (h2 "Recent") | |
| 167 | - | ,(map (lambda (entry) | |
| 168 | - | `(article (h3 (a (@ (href ,(format #f "/raw/~a" (pb-entry-id entry))) | |
| 169 | - | (target "_blank")) | |
| 170 | - | ,(pb-entry-id entry))) | |
| 171 | - | (pre ,(pb-entry-text entry)))) | |
| 172 | - | top5)) | |
| 173 | - | (section (h2 "New") | |
| 174 | - | (form (@ (method "post") | |
| 175 | - | (enctype "multipart/form-data") | |
| 176 | - | (action "/post")) | |
| 177 | - | (p (label "Paste content" | |
| 178 | - | (textarea (@ (name "text")) ""))) | |
| 179 | - | (p (label (input (@ (type "checkbox") | |
| 180 | - | (name "showUrl") | |
| 181 | - | (value "1"))) | |
| 182 | - | "Show raw URL after paste")) | |
| 183 | - | (input (@ (type "submit")))))) | |
| 184 | - | (footer (p (a (@ (href "https://github.com/pisemsky/guile-pastebin") | |
| 185 | - | (target "_blank")) | |
| 186 | - | "Source code"))))))) | |
| 187 | - | (display "<!DOCTYPE html>\n" port) | |
| 188 | - | (sxml->xml sxml port)))))))) | |
| 198 | + | (not-found))))) | |