Constrain urls

Evgeny PisemskySun Feb 23 11:45:15+0300 2025

2439613

Constrain urls

README.md

1414
Execute one of the following commands in the root of repository:
1515
1616
```
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>
1919
```
2020
2121
Then navigate your web browser at `http://localhost:8080`. By default,

3131
3232
## API
3333
34+
- `/` -- show top 5 paste list
3435
- `/post` -- create paste
3536
  - method: POST only
3637
  - type: `multipart/form-data`

3940
    - `showUrl=1` -- to show the raw URL after paste
4041
- `/raw/<ID>` -- get paste content
4142
  - method: GET only
42-
- Anything else -- show top 5 paste list
4343
4444
## Paste a file from command line
4545

4848
4949
Notice the double-quotes around the parameters because `<` means IO
5050
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

5656
       (cons (get-content-dispo-name-from-headers (car pp)) (cdr pp))))
5757
   parts))
5858
59+
(define (not-found)
60+
  (values (build-response #:code 404)
61+
          (lambda (port) 1)))
62+
5963
(define (templatize title body)
6064
  `(html (@ (lang "en"))
6165
         (head

6569
          (link (@ (rel "stylesheet") (href "https://unpkg.com/simpledotcss/simple.min.css"))))
6670
         (body ,@body)))
6771
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+
68108
(define (post-handler request request-body pb-data-path)
69109
  (if (eq? (request-method request) 'POST)
70110
      (let* ((headers (request-headers request))

135175
                            (begin
136176
                              (put-bytevector port bv)
137177
                              (A inport')))))))))
138-
      (values (build-response #:code 404)
139-
              (lambda (port) 1))))
178+
      (not-found)))
140179
141180
(define (make-pastebin-handler data-path)
142181
  (lambda (request request-body)
143182
    (match (split-and-decode-uri-path (uri-path (request-uri request)))
144183
184+
      ;; URI: / -- show the top 5 paste list
185+
      (()
186+
       (list-handler data-path))
187+
145188
      ;; URI: /post -- create paste
146-
      (("post" . _)
189+
      (("post")
147190
       (post-handler request request-body data-path))
148191
149192
      ;; URI: /raw/<id> -- return raw content of the paste
150193
      (("raw" pb-id)
151194
       (raw-handler data-path pb-id))
152195
153-
      ;; URI: * -- everything else -- show the top 5 paste list
196+
      ;; URI: * -- everything else -- show 404 error
154197
      (_
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)))))