Mercurial > core / lisp/lib/net/fetch.lisp
changeset 123: |
a4ed30cbe083 |
parent: |
4ba88cac5bc7
|
child: |
f85a2fac1ed7 |
author: |
ellis <ellis@rwest.io> |
date: |
Sun, 24 Dec 2023 18:19:33 -0500 |
permissions: |
-rw-r--r-- |
description: |
data testing, added ical and vcard formats |
1 (in-package :net/fetch) 3 (define-condition invalid-path-error (error) 4 ((text :initarg :text :reader text))) 6 (defun download (url output) 7 (multiple-value-bind (content-or-stream status header tk stream must-close status-string) 8 (drakma:http-request url :want-stream t :external-format-out :utf-8) 12 (with-open-file (file output 14 :if-does-not-exist :create 16 :element-type '(unsigned-byte 8)) 17 (do ((b (read-byte stream nil nil) (read-byte stream nil nil))) 23 (when must-close (close stream)) 24 (or content-or-stream tk header) 29 (defun split-file-path (path) 30 (let ((pos-last-slash (1+ (position #\/ path :from-end t)))) 31 (list (subseq path 0 pos-last-slash) 32 (subseq path pos-last-slash)))) 34 (defun split-uri-string (uri-string) 35 (let ((pu (puri:parse-uri uri-string))) 36 (cons (puri:uri-host pu) (split-file-path (puri:uri-path pu))))) 38 (defun condition-path (path) 39 "Abuse puri:parse-uri to strip possible get args from path" 40 (let ((p (puri:parse-uri path))) (puri:uri-path p))) 43 (handler-case (probe-file path) 44 (type-error (e) #+sbcl (declare (ignore e)) (error 'invalid-path-error 45 :text (format nil "Invalid path: ~A" path))))) 47 (defun %fetch (url-or-path &key (cache t) 51 ((is-file (condition-path url-or-path)) (condition-path url-or-path)) 52 ((is-file (condition-path (concatenate 'string dir url-or-path))) 53 (condition-path (concatenate 'string dir url-or-path))) 54 ((puri:parse-uri url-or-path) 55 (let* ((tmp-pathname (split-uri-string url-or-path)) 56 (file-pathstring (format nil "~{~A~^~}" (if dir (cons dir tmp-pathname) tmp-pathname))) 57 (file-pathname (ensure-directories-exist 60 (when (is-file file-pathname) (delete-file file-pathname)) 61 (if (and cache (probe-file file-pathname)) 62 (values file-pathname 200 "OK") 63 (handler-case (download url-or-path file-pathname) 64 (drakma:parameter-error () 65 (values nil 404 "Parameter Error") 67 (t (values nil 404 "Not file of url")))) 69 (defun fetch (url-or-path 72 (external-format :utf-8) 76 "Fetch file from ~url-or-location~ if not cached in ~dir~ 77 stores the file in the location specified by dir if url or file is url the file 78 is stored in ~dir~/~uri-host~/~uri-path~. 80 Note that it is important to ensure that dir and subdir if used end in a / 82 -return: path to file or stream if :stream parameter is passed 84 - url-or-path: <string> pathname or url string identifying file to be fetched. 85 - stream: resuests that fetch returns a stream 86 - cache: <T|NIL> if T looks for file in -dir and uses that as source if NIL then the a fresh copy of the file is fetched 87 - dir: location to store fetched file, default location is in the sample directory in the top level of the clml source tree. 88 - flush: if T fetch does not download the file it deletes the existing file. 90 (let ((fetched-path (%fetch url-or-path :dir dir :cache cache :flush flush))) 91 (if (not fetched-path) 94 (open fetched-path :direction :input :external-format external-format)