anchor.diff:  (defpackage :nellie.hdfs
     (:nicknames #:hdfs)
     (:use :cl :alists :simple-date-time :iterate :alexandria)
  +  (:import-from :metabang-bind :bind)
  +  (:import-from :flexi-streams
  +                :make-flexi-stream :octets-to-string
  +                :with-output-to-sequence :octet)
     (:export #:+webfs-port+
              #:+webhdfs-port+
              #:*default-port*
  
positive.code:          :code code
           :message message))
  
  (defun exception-to-keyword (exception)
    (make-keyword (cl-json::simplified-camel-case-to-lisp exception)))
  
  (defun url-with-parameters (url parameters)
    (let* ((uri (puri:parse-uri url))
           (query-params (drakma::dissect-query (puri::uri-query uri)))
           (all-params (append query-params parameters)))
      (setf (puri:uri-query uri)
            (drakma::alist-to-url-encoded-string all-params
                                                 drakma:*drakma-default-external-format*
                                                 #'drakma:url-encode))
      uri))
  
  (defun send-request (method url
                       &key parameters content (content-length t))
    (let ((drakma:*header-stream* nil))
      (multiple-value-bind (bytes code headers)
          (drakma:http-request (url-with-parameters url parameters)
                               :external-format-in :utf-8
                               :external-format-out :utf-8
                               :force-binary t
                               :method method
                               :redirect nil
                               :content content
                               :content-length content-length
                               :content-type "application/octet-stream")
        (let* ((content-type (alist-get :content-type headers))
               (is-json (equal content-type "application/json"))
               (body (cond (is-json
                            (when bytes
                              (json:decode-json-from-string (flexi-streams:octets-to-string bytes))))
                           ((equal (subseq content-type 0 5) "text/")
                            (flexi-streams:octets-to-string bytes))
                           (t bytes))))
          (cond ((< code 400) (values body code headers))
                (is-json (let* ((exception (alist-get :*remote-exception body))
                                (name (alist-get :exception exception))
                                (type (if name (exception-to-keyword name) :unknown-error))
                                (message (or (alist-get :message exception) "Unknown error")))
                           (server-error type code message)))
                (t (server-error :server-error code body)))))))
  
  (defun operation-request (context method operation path &key parameters)
    (let* ((user (context-user context))
           (path (if (eq (char path 0) #\/) path
                     (format nil "/users/~A/~A" user path)))
  
negative.code:   (user "hdfs"))
  
  (define-condition server-error (error)
    ((type :initarg :type :reader error-type)
     (code :initarg :code :reader error-code)
     (message :initarg :message :reader error-message)))
  
  (defmethod print-object ((object server-error) stream)
    (print-unreadable-object (object stream :type t :identity t)
      (format stream "[~D ~A]: ~A"
              (error-type object)
              (error-code object)
              (error-message object))))
  
  (defun server-error (type code message)
    (error 'server-error
  