heuristic: anyone asking for a language can accept a range response
2 files changed, 88 insertions(+), 8 deletions(-)

M run-wispserve.w
M wispserve/serve.w
M run-wispserve.w +3 -4
@@ 15,11 15,10 @@ define : help-message args
          tests
              test-assert : string-contains (help-message '("./program")) "./program"
              test-equal #\U : string-ref (help-message '("./program")) 0
-       format #f "Usage: ~a [options]
+       format #f "Usage: ~a [DOWNLOAD_URL | --serve FOLDER] [options]
 
 Options:
    [link [link ...]] download file(s)
-   --serve <folder>  serve the files in FOLDER
    --ip <ip>         set server IP (default: [::])
    --port <port>     set server port (default: 8083)
    --lazy    hash served when they are requested instead of at startup (default: #f)

          
@@ 42,14 41,14 @@ define : main args
      cond
        : or (null? arguments) (member "--help" arguments) (member "-h" arguments)
          help args
-       : and {(length arguments) > 1} : equal? "--serve" : car arguments
+       : and {(length arguments) > 1} : equal? "--serve" : first arguments
          let
              : ip-opt : or (opt-member arguments "--ip") '("--ip" "::")
                port-opt : or (opt-member arguments "--port") '("--port" "8083")
                lazy : member "--lazy" arguments
              serve (second arguments) (second ip-opt) (string->number (second port-opt)) (not lazy)
        else
-         let* 
+         let*
              : download-data : download-file : car arguments
                output-opt : opt-member arguments "--output"
                output-file

          
M wispserve/serve.w +85 -4
@@ 430,17 430,17 @@ define : hash-and-mime-if-unknown! serve
                 set! served-paths : vhash-cons (served-serverpath new-served) new-served : vhash-delete (served-serverpath served-cdr) served-paths
                 cons (car served-file) new-served
 
-define : server-serve-file range-requested begin-end served-file
+define : server-serve-file range-requested disallow-range begin-end served-file
    define range-begin : car begin-end
    define filesize
        or : and=> (and=> (and=> (and=> served-file cdr) served-accesspath) stat) stat:size
           . 32KiB
    define range-end
-       if : not range-requested
+       if : or disallow-range : and (< filesize 2MiB) : not range-requested 
           . #f
           or
             cdr begin-end
-             ;; if no size is requested, optimize for streaming video
+             ;; if no size is requested, optimize for streaming video, since that’s tho only thing that really needs optimizing
             min : - filesize 1
                 + range-begin
                     cond

          
@@ 467,6 467,7 @@ define : server-serve-file range-request
         cons `(content-range . ,(format #f "bytes ~d-~d/~d" range-begin range-end file-size))
              . base-headers
         . base-headers
+   ;; pretty-print : ` resp-headers ,headers
    values
      build-response
        . #:headers headers

          
@@ 580,11 581,88 @@ define* : string-split-string s substr #
                                    . pieces
 
 
+;; Headers for Tizen Smart-TV
+;; ((req-headers
+;;    ((host "192.168.2.105" . 8083)
+;;     (connection keep-alive)
+;;     (user-agent
+;;       .
+;;       "Mozilla/5.0 (SMART-TV; Linux; Tizen 5.0) AppleWebKit/537.36 (KHTML, like Gecko) SamsungBrowser/2.2 Chrome/63.0.3239.84 TV Safari/537.36")
+;;     (accept
+;;       (image/webp)
+;;       (image/apng)
+;;       (image/*)
+;;       (*/* (q . 800)))
+;;     (referer
+;;       .
+;;       #<<uri> scheme: http userinfo: #f host: "192.168.2.105" port: 8083 path: "/" query: #f fragment: #f>)
+;;     (accept-encoding
+;;       (1000 . "gzip")
+;;       (1000 . "deflate"))
+;;     (accept-language (1000 . "de-DE"))))
+
+
+;; Headers for IceCat:
+;; ((req-headers
+;;    ((host "192.168.2.105" . 8083)
+;;     (user-agent
+;;       .
+;;       "Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0")
+;;     (accept
+;;       (video/webm)
+;;       (video/ogg)
+;;       (video/* (q . 900))
+;;       (application/ogg (q . 700))
+;;       (audio/* (q . 600))
+;;       (*/* (q . 500)))
+;;     (accept-language (1000 . "en-US") (500 . "en"))
+;;     (referer
+;;       .
+;;       #<<uri> scheme: http userinfo: #f host: "192.168.2.105" port: 8083 path: "/drachenzaehmen-leicht-gemacht-1.mp4" query: #f fragment: #f>)
+;;     (range bytes (10518541 . #f))
+;;     (dnt . "1")
+;;     (connection keep-alive)))
+
+;; Headers for Chromium:
+;; ((req-headers
+;;    ((host "192.168.2.105" . 8083)
+;;     (connection keep-alive)
+;;     (dnt . "1")
+;;     (accept-encoding (1000 . "identity") (0 . "*"))
+;;     (user-agent
+;;       .
+;;       "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36")
+;;     (accept (*/*))
+;;     (referer
+;;       .
+;;       #<<uri> scheme: http userinfo: #f host: "192.168.2.105" port: 8083 path: "/drachenzaehmen-leicht-gemacht-1.mp4" query: #f fragment: #f>)
+;;     (accept-language
+;;       (1000 . "de-DE")
+;;       (900 . "de")
+;;       (800 . "en-US")
+;;       (700 . "en"))
+;;     (range bytes (6324235 . #f))))
+
+;; Wget
+;; ((req-headers
+;;    ((user-agent . "Wget/1.20.3 (linux-gnu)")
+;;     (accept (*/*))
+;;     (accept-encoding (1000 . "identity"))
+;;     (host "192.168.2.105" . 8083)
+;;     (connection keep-alive)))
+
+;; Curl
+;; ((req-headers
+;;    ((host "192.168.2.105" . 8083)
+;;     (user-agent . "curl/7.71.0")
+;;     (accept (*/*))))
+
 
 define : server-file-download-handler folder-path request body
     define headers : request-headers request
     let*
         : range-requested : assoc-item headers 'range
+          disallow-range : not : or range-requested : assoc-item headers 'accept-language ;; accept-language is typically interactive, so if it is not present, we fall back to providing the whole file in one go. This is just a heuristic, though. There is no good way to detect "will accept Range response, even though it did not request it".
           begin-end
               if : or (not range-requested) {(length range-requested) < 3}
                  . '(0 . #f)

          
@@ 599,6 677,9 @@ define : server-file-download-handler fo
           ;; ipv4 : inet-ntop AF_INET ip
           ipv6 : inet-ntop AF_INET6 ip
         ;; pretty-print : list 'xalt xalt 'ipv6 ipv6 'peer peer
+        ;; pretty-print
+        ;;   ` : req-headers ,headers
+        ;;       disallow-range ,disallow-range
         cond
             : null? path-elements
               server-list-files

          
@@ 613,7 694,7 @@ define : server-file-download-handler fo
                       alist-cons sha256
                           delete-duplicates : cons ipv6 : or (assoc-ref xalt sha256) : list
                           . xalt
-              server-serve-file range-requested begin-end
+              server-serve-file range-requested disallow-range begin-end
                   hash-and-mime-if-unknown! served-file
 
 define : sha256sum path