breezewiki/src/url-utils.rkt

72 lines
2.7 KiB
Racket

#lang typed/racket/base
(require racket/string
"pure-utils.rkt")
(provide
; make a query string from an association list of strings
params->query
; make a proxied version of a fandom url
u-proxy-url
; check whether a url is on a domain controlled by fandom
is-fandom-url?)
(module+ test
(require "typed-rackunit.rkt"))
;; https://url.spec.whatwg.org/#urlencoded-serializing
(define urlencoded-set '(#\! #\' #\( #\) #\~ ; urlencoded set
#\$ #\% #\& #\+ #\, ; component set
#\/ #\: #\; #\= #\@ #\[ #\\ #\] #\^ #\| ; userinfo set
#\? #\` #\{ #\} ; path set
#\ #\" #\# #\< #\> ; query set
; c0 controls included elsewhere
; higher ranges included elsewhere
))
(: percent-encode (String (Listof Char) Boolean -> Bytes))
(define (percent-encode value set space-as-plus)
(define b (string->bytes/utf-8 value))
(apply bytes-append
(for/list ([char b]) : (Listof Bytes)
(cond
[(and space-as-plus (eq? char 32))
#"+"]
[(or (member (integer->char char) set)
(char . > . #x7E)
(char . <= . #x1F))
(bytes-append #"%" (string->bytes/latin-1
(string-upcase (number->string char 16))))]
[#t
(bytes char)]))))
(: params->query ((Listof (Pair String String)) -> String))
(define (params->query params)
(string-join
(map (λ ([p : (Pair String String)])
(format "~a=~a"
(percent-encode (car p) urlencoded-set #t)
(percent-encode (cdr p) urlencoded-set #t)))
params)
"&"))
(module+ test
(check-equal? (params->query '(("hello" . "world")))
"hello=world")
(check-equal? (params->query '(("a" . "hello world''") ("utf8" . "")))
"a=hello+world%27%27&utf8=%E2%9C%93"))
(: is-fandom-url? (String -> Boolean))
(define (is-fandom-url? url)
(regexp-match? #rx"^https://static.wikia.nocookie.net/|^https://[a-z-]*.fandom.com/" url))
(module+ test
(check-true (is-fandom-url? "https://static.wikia.nocookie.net/wikiname/images/2/2f/SomeImage.jpg/revision/latest?cb=20110210094136"))
(check-true (is-fandom-url? "https://test.fandom.com/wiki/Some_Page"))
(check-false (is-fandom-url? "https://cadence.moe")))
(: u-proxy-url (String -> String))
(define (u-proxy-url url)
(u
is-fandom-url?
(λ ([v : String]) (string-append "/proxy?" (params->query `(("dest" . ,url)))))
url))