forked from cadence/breezewiki
		
	Replace thread-let with thread-utils
This commit is contained in:
		
							parent
							
								
									5fa6e2fb9e
								
							
						
					
					
						commit
						501dcaa3fc
					
				
					 9 changed files with 255 additions and 215 deletions
				
			
		|  | @ -4,8 +4,6 @@ | ||||||
| (provide | (provide | ||||||
|  ; help make a nested if. if/in will gain the same false form of its containing if/out. |  ; help make a nested if. if/in will gain the same false form of its containing if/out. | ||||||
|  if/out |  if/out | ||||||
|  ; let, but the value for each variable is evaluated within a thread |  | ||||||
|  thread-let |  | ||||||
|  ; cond, but values can be defined between conditions |  ; cond, but values can be defined between conditions | ||||||
|  cond/var |  cond/var | ||||||
|  ; wrap sql statements into lambdas so they can be executed during migration |  ; wrap sql statements into lambdas so they can be executed during migration | ||||||
|  | @ -25,7 +23,6 @@ | ||||||
| 
 | 
 | ||||||
|   (provide |   (provide | ||||||
|    transform-if/out |    transform-if/out | ||||||
|    transform-thread-let |  | ||||||
|    transform/out-cond/var) |    transform/out-cond/var) | ||||||
| 
 | 
 | ||||||
|   (define (transform-if/out stx) |   (define (transform-if/out stx) | ||||||
|  | @ -51,26 +48,6 @@ | ||||||
|           [#t node]))) |           [#t node]))) | ||||||
|     (datum->syntax stx (cons 'if result))) |     (datum->syntax stx (cons 'if result))) | ||||||
| 
 | 
 | ||||||
|   (define (transform-thread-let stx) |  | ||||||
|     (define tree (cdr (syntax->datum stx))) |  | ||||||
|     (define defs (car tree)) |  | ||||||
|     (define forms (cdr tree)) |  | ||||||
|     (when (eq? (length forms) 0) |  | ||||||
|       (error (format "thread-let: bad syntax (need some forms to execute after the threads)~n  forms: ~a" forms))) |  | ||||||
|     (define counter (build-list (length defs) values)) |  | ||||||
|     (datum->syntax |  | ||||||
|      stx |  | ||||||
|      `(let ([chv (build-vector ,(length defs) (λ (_) (make-channel)))]) |  | ||||||
|         ,@(map (λ (n) |  | ||||||
|                  (define def (list-ref defs n)) |  | ||||||
|                  `(thread (λ () (channel-put (vector-ref chv ,n) (let _ () ,@(cdr def)))))) |  | ||||||
|                counter) |  | ||||||
|         (let ,(map (λ (n) |  | ||||||
|                      (define def (list-ref defs n)) |  | ||||||
|                      `(,(car def) (channel-get (vector-ref chv ,n)))) |  | ||||||
|                    counter) |  | ||||||
|           ,@forms)))) |  | ||||||
| 
 |  | ||||||
|   (define (transform/out-cond/var stx) |   (define (transform/out-cond/var stx) | ||||||
|     (define tree (transform-cond/var (cdr (syntax->datum stx)))) |     (define tree (transform-cond/var (cdr (syntax->datum stx)))) | ||||||
|     (datum->syntax |     (datum->syntax | ||||||
|  | @ -119,35 +96,6 @@ | ||||||
|   (check-equal? (if/out #t (if/in #f 'yes) 'no) 'no) |   (check-equal? (if/out #t (if/in #f 'yes) 'no) 'no) | ||||||
|   (check-equal? (if/out #f (if/in #f 'yes) 'no) 'no)) |   (check-equal? (if/out #f (if/in #f 'yes) 'no) 'no)) | ||||||
| 
 | 
 | ||||||
| (define-syntax (thread-let stx) |  | ||||||
|   (transform-thread-let stx)) |  | ||||||
| (module+ test |  | ||||||
|   ; check that it is transformed as expected |  | ||||||
|   (check-syntax-equal? |  | ||||||
|    (transform-thread-let |  | ||||||
|     #'(thread-let ([a (hey "this is a")] |  | ||||||
|                    [b (hey "this is b")]) |  | ||||||
|                   (list a b))) |  | ||||||
|    #'(let ([chv (build-vector 2 (λ (_) (make-channel)))]) |  | ||||||
|        (thread (λ () (channel-put (vector-ref chv 0) (let _ () (hey "this is a"))))) |  | ||||||
|        (thread (λ () (channel-put (vector-ref chv 1) (let _ () (hey "this is b"))))) |  | ||||||
|        (let ([a (channel-get (vector-ref chv 0))] |  | ||||||
|              [b (channel-get (vector-ref chv 1))]) |  | ||||||
|          (list a b)))) |  | ||||||
|   ; check that they actually execute concurrently |  | ||||||
|   (define ch (make-channel)) |  | ||||||
|   (check-equal? (thread-let ([a (begin |  | ||||||
|                                   (channel-put ch 'a) |  | ||||||
|                                   (channel-get ch))] |  | ||||||
|                              [b (begin0 |  | ||||||
|                                     (channel-get ch) |  | ||||||
|                                   (channel-put ch 'b))]) |  | ||||||
|                             (list a b)) |  | ||||||
|                 '(b a)) |  | ||||||
|   ; check that it assigns the correct value to the correct variable |  | ||||||
|   (check-equal? (thread-let ([a (sleep 0) 'a] [b 'b]) (list a b)) |  | ||||||
|                 '(a b))) |  | ||||||
| 
 |  | ||||||
| (define-syntax (cond/var stx) | (define-syntax (cond/var stx) | ||||||
|   (transform/out-cond/var stx)) |   (transform/out-cond/var stx)) | ||||||
| (module+ test | (module+ test | ||||||
|  |  | ||||||
							
								
								
									
										72
									
								
								lib/thread-utils.rkt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								lib/thread-utils.rkt
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | #lang racket/base | ||||||
|  | (require (prefix-in easy: net/http-easy) | ||||||
|  |          "../src/data.rkt" | ||||||
|  |          "xexpr-utils.rkt") | ||||||
|  | 
 | ||||||
|  | (provide | ||||||
|  |  thread-values) | ||||||
|  | 
 | ||||||
|  | (module+ test | ||||||
|  |   (require rackunit)) | ||||||
|  | 
 | ||||||
|  | (define (thread-values . thunks) | ||||||
|  |   (parameterize-break #t | ||||||
|  |     (define the-exn (box #f)) | ||||||
|  |     (define original-thread (current-thread)) | ||||||
|  |     (define (break e) | ||||||
|  |       (when (box-cas! the-exn #f e) | ||||||
|  |         (break-thread original-thread)) | ||||||
|  |       (sleep 0)) | ||||||
|  |     (define-values (threads channels) | ||||||
|  |       (for/fold ([ts null] | ||||||
|  |                  [chs null] | ||||||
|  |                  #:result (values (reverse ts) (reverse chs))) | ||||||
|  |                 ([th thunks]) | ||||||
|  |         (define ch (make-channel)) | ||||||
|  |         (define t | ||||||
|  |           (thread (λ () | ||||||
|  |                     (with-handlers ([exn? break]) | ||||||
|  |                       (channel-put ch (th)))))) | ||||||
|  |         (values (cons t ts) (cons ch chs)))) | ||||||
|  |     (apply | ||||||
|  |      values | ||||||
|  |      (with-handlers ([exn:break? (λ (_) | ||||||
|  |                                    (for ([t threads]) (kill-thread t)) | ||||||
|  |                                    (if (unbox the-exn) | ||||||
|  |                                        (raise (unbox the-exn)) | ||||||
|  |                                        (error 'thread-values "a thread broke, but without reporting its exception")))]) | ||||||
|  |        (for/list ([ch channels]) | ||||||
|  |          (channel-get ch)))))) | ||||||
|  | 
 | ||||||
|  | (module+ test | ||||||
|  |   ; check that they actually execute concurrently | ||||||
|  |   (define ch (make-channel)) | ||||||
|  |   (check-equal? (let-values ([(a b) | ||||||
|  |                               (thread-values | ||||||
|  |                                (λ () | ||||||
|  |                                  (begin | ||||||
|  |                                    (channel-put ch 'a) | ||||||
|  |                                    (channel-get ch))) | ||||||
|  |                                (λ () | ||||||
|  |                                  (begin0 | ||||||
|  |                                      (channel-get ch) | ||||||
|  |                                    (channel-put ch 'b))))]) | ||||||
|  |                   (list a b)) | ||||||
|  |                 '(b a)) | ||||||
|  |   ; check that it assigns the correct value to the correct variable | ||||||
|  |   (check-equal? (let-values ([(a b) | ||||||
|  |                               (thread-values | ||||||
|  |                                (λ () (sleep 0) 'a) | ||||||
|  |                                (λ () 'b))]) | ||||||
|  |                   (list a b)) | ||||||
|  |                 '(a b)) | ||||||
|  |   ; check that exceptions are passed to the original thread, and other threads are killed | ||||||
|  |   ;; TODO: if the other thread was making an HTTP request, could it be left stuck open by the kill? | ||||||
|  |   (check-equal? (let* ([x "!"] | ||||||
|  |                        [res | ||||||
|  |                         (with-handlers ([exn:fail:user? (λ (e) (exn-message e))]) | ||||||
|  |                           (thread-values | ||||||
|  |                            (λ () (sleep 0) (set! x "?") (println "this side effect should not happen")) | ||||||
|  |                            (λ () (raise-user-error "catch me"))))]) | ||||||
|  |                   (string-append res x)) | ||||||
|  |                 "catch me!")) | ||||||
|  | @ -277,8 +277,8 @@ | ||||||
|   ; check that noscript images are removed |   ; check that noscript images are removed | ||||||
|   (check-equal? ((query-selector (λ (t a c) (eq? t 'noscript)) transformed)) #f) |   (check-equal? ((query-selector (λ (t a c) (eq? t 'noscript)) transformed)) #f) | ||||||
|   ; benchmark |   ; benchmark | ||||||
|   (when (file-exists? "../misc/Frog.html") |   (when (file-exists? "../storage/Frog.html") | ||||||
|     (with-input-from-file "../misc/Frog.html" |     (with-input-from-file "../storage/Frog.html" | ||||||
|       (λ () |       (λ () | ||||||
|         (define tree (html->xexp (current-input-port))) |         (define tree (html->xexp (current-input-port))) | ||||||
|         (time (length (update-tree-wiki tree "minecraft"))))))) |         (time (length (update-tree-wiki tree "minecraft"))))))) | ||||||
|  |  | ||||||
|  | @ -201,13 +201,16 @@ | ||||||
|            ,(if (config-true? 'instance_is_official) |            ,(if (config-true? 'instance_is_official) | ||||||
|                 (let ([balloon '(img (@ (src "/static/three-balloons.png") (class "bw-balloon") (title "Image Source: pngimg.com/image/4955 | License: CC BY-NC 4.0 | Modifications: Resized") (width "52") (height "56")))] |                 (let ([balloon '(img (@ (src "/static/three-balloons.png") (class "bw-balloon") (title "Image Source: pngimg.com/image/4955 | License: CC BY-NC 4.0 | Modifications: Resized") (width "52") (height "56")))] | ||||||
|                       [extension-eligible? |                       [extension-eligible? | ||||||
|                        (and req (let* ([ua-pair (assq 'user-agent (request-headers req))] |                        (cond/var | ||||||
|                                        [ua (string-downcase (cdr ua-pair))]) |                         [(not req) #f] | ||||||
|  |                         (var ua-pair (assq 'user-agent (request-headers req))) | ||||||
|  |                         [(not ua-pair) #f] | ||||||
|  |                         (var ua (string-downcase (cdr ua-pair))) | ||||||
|                         ;; everyone pretends to be chrome, so we do it in reverse |                         ;; everyone pretends to be chrome, so we do it in reverse | ||||||
|                         ;; this excludes common browsers that don't support the extension |                         ;; this excludes common browsers that don't support the extension | ||||||
|                                   (and (not (string-contains? ua "edge/")) |                         [#t (and (not (string-contains? ua "edge/")) | ||||||
|                                  (not (string-contains? ua "edg/")) |                                  (not (string-contains? ua "edg/")) | ||||||
|                                        (not (string-contains? ua "mobile")))))]) |                                  (not (string-contains? ua "mobile")))])]) | ||||||
|                   `(div (@ (class "bw-top-banner")) |                   `(div (@ (class "bw-top-banner")) | ||||||
|                         ,balloon |                         ,balloon | ||||||
|                         (div |                         (div | ||||||
|  |  | ||||||
|  | @ -28,7 +28,7 @@ | ||||||
|     (hash-set! wikis-hash (symbol->string wikiname) w))) |     (hash-set! wikis-hash (symbol->string wikiname) w))) | ||||||
| (module+ test | (module+ test | ||||||
|   (check-equal? (cadr (hash-ref wikis-hash "gallowmere")) |   (check-equal? (cadr (hash-ref wikis-hash "gallowmere")) | ||||||
|                 "Gallowmere Historia")) |                 "MediEvil Wiki")) | ||||||
| 
 | 
 | ||||||
| (define (parse-table table) | (define (parse-table table) | ||||||
|   (define rows (query-selector (λ (t a c) (eq? t 'tr)) table)) |   (define rows (query-selector (λ (t a c) (eq? t 'tr)) table)) | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
|          "data.rkt" |          "data.rkt" | ||||||
|          "page-wiki.rkt" |          "page-wiki.rkt" | ||||||
|          "../lib/syntax.rkt" |          "../lib/syntax.rkt" | ||||||
|  |          "../lib/thread-utils.rkt" | ||||||
|          "../lib/url-utils.rkt" |          "../lib/url-utils.rkt" | ||||||
|          "whole-utils.rkt" |          "whole-utils.rkt" | ||||||
|          "../lib/xexpr-utils.rkt") |          "../lib/xexpr-utils.rkt") | ||||||
|  | @ -69,8 +70,10 @@ | ||||||
|    (define origin (format "https://~a.fandom.com" wikiname)) |    (define origin (format "https://~a.fandom.com" wikiname)) | ||||||
|    (define source-url (format "~a/wiki/~a" origin prefixed-category)) |    (define source-url (format "~a/wiki/~a" origin prefixed-category)) | ||||||
| 
 | 
 | ||||||
|    (thread-let |    (define-values (members-data page-data siteinfo) | ||||||
|     ([members-data (define dest-url |      (thread-values | ||||||
|  |       (λ () | ||||||
|  |         (define dest-url | ||||||
|           (format "~a/api.php?~a" |           (format "~a/api.php?~a" | ||||||
|                   origin |                   origin | ||||||
|                   (params->query `(("action" . "query") |                   (params->query `(("action" . "query") | ||||||
|  | @ -81,8 +84,9 @@ | ||||||
|                                    ("format" . "json"))))) |                                    ("format" . "json"))))) | ||||||
|         (log-outgoing dest-url) |         (log-outgoing dest-url) | ||||||
|         (define dest-res (easy:get dest-url #:timeouts timeouts)) |         (define dest-res (easy:get dest-url #:timeouts timeouts)) | ||||||
|                    (easy:response-json dest-res)] |         (easy:response-json dest-res)) | ||||||
|      [page-data (define dest-url |       (λ () | ||||||
|  |         (define dest-url | ||||||
|           (format "~a/api.php?~a" |           (format "~a/api.php?~a" | ||||||
|                   origin |                   origin | ||||||
|                   (params->query `(("action" . "parse") |                   (params->query `(("action" . "parse") | ||||||
|  | @ -92,8 +96,9 @@ | ||||||
|                                    ("format" . "json"))))) |                                    ("format" . "json"))))) | ||||||
|         (log-outgoing dest-url) |         (log-outgoing dest-url) | ||||||
|         (define dest-res (easy:get dest-url #:timeouts timeouts)) |         (define dest-res (easy:get dest-url #:timeouts timeouts)) | ||||||
|                 (easy:response-json dest-res)] |         (easy:response-json dest-res)) | ||||||
|      [siteinfo (siteinfo-fetch wikiname)]) |       (λ () | ||||||
|  |         (siteinfo-fetch wikiname)))) | ||||||
| 
 | 
 | ||||||
|    (define title (preprocess-html-wiki (jp "/parse/title" page-data prefixed-category))) |    (define title (preprocess-html-wiki (jp "/parse/title" page-data prefixed-category))) | ||||||
|    (define page-html (preprocess-html-wiki (jp "/parse/text" page-data ""))) |    (define page-html (preprocess-html-wiki (jp "/parse/text" page-data ""))) | ||||||
|  | @ -117,7 +122,7 @@ | ||||||
|     #:code 200 |     #:code 200 | ||||||
|     #:headers (build-headers always-headers) |     #:headers (build-headers always-headers) | ||||||
|     (λ (out) |     (λ (out) | ||||||
|        (write-html body out)))))) |       (write-html body out))))) | ||||||
| (module+ test | (module+ test | ||||||
|   (check-not-false ((query-selector (attribute-selector 'href "/test/wiki/Ankle_Monitor") |   (check-not-false ((query-selector (attribute-selector 'href "/test/wiki/Ankle_Monitor") | ||||||
|                                     (generate-results-page |                                     (generate-results-page | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
|          "data.rkt" |          "data.rkt" | ||||||
|          "page-wiki.rkt" |          "page-wiki.rkt" | ||||||
|          "../lib/syntax.rkt" |          "../lib/syntax.rkt" | ||||||
|  |          "../lib/thread-utils.rkt" | ||||||
|          "../lib/url-utils.rkt" |          "../lib/url-utils.rkt" | ||||||
|          "whole-utils.rkt" |          "whole-utils.rkt" | ||||||
|          "../lib/xexpr-utils.rkt") |          "../lib/xexpr-utils.rkt") | ||||||
|  | @ -108,8 +109,10 @@ | ||||||
|    (define origin (format "https://~a.fandom.com" wikiname)) |    (define origin (format "https://~a.fandom.com" wikiname)) | ||||||
|    (define source-url (format "~a/wiki/~a" origin prefixed-title)) |    (define source-url (format "~a/wiki/~a" origin prefixed-title)) | ||||||
| 
 | 
 | ||||||
|    (thread-let |    (define-values (media-detail siteinfo) | ||||||
|     ([media-detail (define dest-url |      (thread-values | ||||||
|  |       (λ () | ||||||
|  |         (define dest-url | ||||||
|           (format "~a/wikia.php?~a" |           (format "~a/wikia.php?~a" | ||||||
|                   origin |                   origin | ||||||
|                   (params->query `(("format" . "json") ("controller" . "Lightbox") |                   (params->query `(("format" . "json") ("controller" . "Lightbox") | ||||||
|  | @ -117,8 +120,9 @@ | ||||||
|                                                        ("fileTitle" . ,prefixed-title))))) |                                                        ("fileTitle" . ,prefixed-title))))) | ||||||
|         (log-outgoing dest-url) |         (log-outgoing dest-url) | ||||||
|         (define dest-res (easy:get dest-url #:timeouts timeouts)) |         (define dest-res (easy:get dest-url #:timeouts timeouts)) | ||||||
|                    (easy:response-json dest-res)] |         (easy:response-json dest-res)) | ||||||
|      [siteinfo (siteinfo-fetch wikiname)]) |       (λ () | ||||||
|  |         (siteinfo-fetch wikiname)))) | ||||||
|    (if (not (jp "/exists" media-detail #f)) |    (if (not (jp "/exists" media-detail #f)) | ||||||
|        (next-dispatcher) |        (next-dispatcher) | ||||||
|        (response-handler |        (response-handler | ||||||
|  | @ -143,7 +147,7 @@ | ||||||
|           (xexp->html body)) |           (xexp->html body)) | ||||||
|         (response/output #:code 200 |         (response/output #:code 200 | ||||||
|                          #:headers (build-headers always-headers) |                          #:headers (build-headers always-headers) | ||||||
|                           (λ (out) (write-html body out)))))))) |                          (λ (out) (write-html body out))))))) | ||||||
| (module+ test | (module+ test | ||||||
|   (parameterize ([(config-parameter 'strict_proxy) "true"]) |   (parameterize ([(config-parameter 'strict_proxy) "true"]) | ||||||
|     (check-equal? (get-media-html "https://static.wikia.nocookie.net/a" "image/jpeg") |     (check-equal? (get-media-html "https://static.wikia.nocookie.net/a" "image/jpeg") | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
|          "config.rkt" |          "config.rkt" | ||||||
|          "data.rkt" |          "data.rkt" | ||||||
|          "../lib/syntax.rkt" |          "../lib/syntax.rkt" | ||||||
|  |          "../lib/thread-utils.rkt" | ||||||
|          "../lib/url-utils.rkt" |          "../lib/url-utils.rkt" | ||||||
|          "whole-utils.rkt" |          "whole-utils.rkt" | ||||||
|          "../lib/xexpr-utils.rkt") |          "../lib/xexpr-utils.rkt") | ||||||
|  | @ -72,10 +73,13 @@ | ||||||
|                               ("formatversion" . "2") |                               ("formatversion" . "2") | ||||||
|                               ("format" . "json"))))) |                               ("format" . "json"))))) | ||||||
| 
 | 
 | ||||||
|    (thread-let |    (define-values (dest-res siteinfo) | ||||||
|     ([dest-res (log-outgoing dest-url) |      (thread-values | ||||||
|                (easy:get dest-url #:timeouts timeouts)] |       (λ () | ||||||
|      [siteinfo (siteinfo-fetch wikiname)]) |         (log-outgoing dest-url) | ||||||
|  |         (easy:get dest-url #:timeouts timeouts)) | ||||||
|  |       (λ () | ||||||
|  |         (siteinfo-fetch wikiname)))) | ||||||
| 
 | 
 | ||||||
|    (define data (easy:response-json dest-res)) |    (define data (easy:response-json dest-res)) | ||||||
| 
 | 
 | ||||||
|  | @ -88,7 +92,7 @@ | ||||||
|     #:code 200 |     #:code 200 | ||||||
|     #:headers (build-headers always-headers) |     #:headers (build-headers always-headers) | ||||||
|     (λ (out) |     (λ (out) | ||||||
|        (write-html body out)))))) |       (write-html body out))))) | ||||||
| (module+ test | (module+ test | ||||||
|   (parameterize ([(config-parameter 'feature_offline::only) "false"]) |   (parameterize ([(config-parameter 'feature_offline::only) "false"]) | ||||||
|     (check-not-false ((query-selector (attribute-selector 'href "/test/wiki/Gacha_Capsule") |     (check-not-false ((query-selector (attribute-selector 'href "/test/wiki/Gacha_Capsule") | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ | ||||||
|          "data.rkt" |          "data.rkt" | ||||||
|          "../lib/pure-utils.rkt" |          "../lib/pure-utils.rkt" | ||||||
|          "../lib/syntax.rkt" |          "../lib/syntax.rkt" | ||||||
|  |          "../lib/thread-utils.rkt" | ||||||
|          "../lib/tree-updater.rkt" |          "../lib/tree-updater.rkt" | ||||||
|          "../lib/url-utils.rkt" |          "../lib/url-utils.rkt" | ||||||
|          "whole-utils.rkt" |          "whole-utils.rkt" | ||||||
|  | @ -41,8 +42,10 @@ | ||||||
|   (define path (string-join (map path/param-path (cddr (url-path (request-uri req)))) "/")) |   (define path (string-join (map path/param-path (cddr (url-path (request-uri req)))) "/")) | ||||||
|   (define source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)) |   (define source-url (format "https://~a.fandom.com/wiki/~a" wikiname path)) | ||||||
| 
 | 
 | ||||||
|   (thread-let |   (define-values (dest-res siteinfo) | ||||||
|    ([dest-res (define dest-url |     (thread-values | ||||||
|  |      (λ () | ||||||
|  |        (define dest-url | ||||||
|          (format "~a/api.php?~a" |          (format "~a/api.php?~a" | ||||||
|                  origin |                  origin | ||||||
|                  (params->query `(("action" . "parse") |                  (params->query `(("action" . "parse") | ||||||
|  | @ -53,8 +56,9 @@ | ||||||
|        (log-outgoing dest-url) |        (log-outgoing dest-url) | ||||||
|        (easy:get dest-url |        (easy:get dest-url | ||||||
|                  #:timeouts timeouts |                  #:timeouts timeouts | ||||||
|                         #:headers `#hasheq((cookie . ,(format "theme=~a" (user-cookies^-theme user-cookies)))))] |                  #:headers `#hasheq((cookie . ,(format "theme=~a" (user-cookies^-theme user-cookies)))))) | ||||||
|     [siteinfo (siteinfo-fetch wikiname)]) |      (λ () | ||||||
|  |        (siteinfo-fetch wikiname)))) | ||||||
| 
 | 
 | ||||||
|   (cond |   (cond | ||||||
|     [(eq? 200 (easy:response-status-code dest-res)) |     [(eq? 200 (easy:response-status-code dest-res)) | ||||||
|  | @ -96,4 +100,4 @@ | ||||||
|              #:code 200 |              #:code 200 | ||||||
|              #:headers headers |              #:headers headers | ||||||
|              (λ (out) |              (λ (out) | ||||||
|                 (write-html body out))))))]))) |                (write-html body out))))))])) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue