Function: verb--request-spec-callback

verb--request-spec-callback is a natively compiled function defined in verb.el.

Signature

(verb--request-spec-callback STATUS RS RESPONSE-BUF START TIMEOUT-TIMER WHERE NUM)

Documentation

Callback for verb--request-spec-send for request RS.

Set up the current buffer so that it can be used to view the HTTP response in a user-friendly way.

More response information can be read from STATUS. RESPONSE-BUF points to a buffer where the response should be copied to, which the user can then use or edit freely. START contains a floating point number indicating the timestamp at which the request was sent. TIMEOUT-TIMER contains a timer set to call verb--timeout-warn, or nil. WHERE describes where the results should be shown in (see verb-send-request-on-point). NUM is this request's identification number.

Source Code

;; Defined in /nix/store/8jnfn8w2mxcxbr2crbklcnija9m0zlkq-emacs-packages-deps/share/emacs/site-lisp/elpa/verb-20260818.1921/verb.el
(defun verb--request-spec-callback (status rs response-buf start timeout-timer
                                           where num)
  "Callback for `verb--request-spec-send' for request RS.
Set up the current buffer so that it can be used to view the HTTP
response in a user-friendly way.

More response information can be read from STATUS.
RESPONSE-BUF points to a buffer where the response should be copied
to, which the user can then use or edit freely.
START contains a floating point number indicating the timestamp at
which the request was sent.
TIMEOUT-TIMER contains a timer set to call `verb--timeout-warn', or
nil.
WHERE describes where the results should be shown in (see
`verb-send-request-on-point').
NUM is this request's identification number."
  (when timeout-timer
    (cancel-timer timeout-timer))

  (verb--teardown-request-environment rs)

  ;; Handle errors first.
  (when-let ((http-error (plist-get status :error))
             (error-info (cdr http-error))
             (error-code (car error-info))
             (url (oref rs url)))
    ;; If there's an HTTP error code (404, 405, etc.) in the error
    ;; information, or if we hit the max redirections limit, continue
    ;; as usual.
    (unless (or (numberp (and (eq error-code 'http)
                              (cadr error-info)))
                (eq error-code 'http-redirect-limit))
      (kill-buffer (current-buffer))
      (kill-buffer response-buf)
      (let ((msg (format "Request error: could not connect to %s:%s"
                         (url-host url) (url-port url))))
        (verb-util--log num 'E msg)
        (verb-util--log num 'E "Error details: %s" http-error)
        (user-error "%s" msg))))

  ;; No errors, continue to read response.
  (let ((elapsed (- (time-to-seconds) start))
        (original-buffer (current-buffer))
        status-line headers content-type charset coding-system body-bytes
        binary-handler text-handler)

    (widen)
    (goto-char (point-min))
    ;; Skip HTTP/1.X status line.
    (setq status-line (verb-util--nonempty-string
                       (buffer-substring-no-properties (point)
                                                       (line-end-position))))

    (verb-util--log num 'I "%s" status-line)

    (forward-line)
    ;; Skip all HTTP headers.
    (while (re-search-forward verb-util--http-header-parse-regexp
                              (line-end-position) t)
      (let ((key (string-trim (match-string 1)))
            (value (string-trim (match-string 2))))
        ;; Save header to alist.
        (push (cons key value) headers)
        (unless (eobp) (forward-char))))

    ;; Read Content-Type and charset.
    (setq content-type (verb--headers-content-type headers))
    (setq charset (or (cdr content-type) verb-default-response-charset))

    ;; Try to get a buffer handler function for this content type.
    (let ((handler (verb--get-handler content-type)))
      (unless handler
        ;; Use default content type handler instead.
        (setq handler verb-default-content-type-handler))

      (if (= (length handler) 1)
          ;; Text handler.
          (setq text-handler (nth 0 handler))
        ;; Binary handler (maybe).
        (unless (and (consp handler)
                     (functionp (nth 0 handler))
                     (eq (nth 1 handler) t)
                     (= (length handler) 2))
          (user-error "Invalid content handler: %s" handler))
        (setq binary-handler (nth 0 handler))))

    ;; Remove headers and blank line from buffer.
    ;; All left should be the content.
    (beginning-of-line)
    (forward-line)
    (delete-region (point-min) (point))

    ;; Current buffer should be unibyte.
    (when enable-multibyte-characters
      ;; If this fails, then something changed in url.el.
      (error "%s" "Expected a unibyte buffer for HTTP response"))

    ;; Record body size in bytes.
    ;; Since the current buffer is unibyte, this will return the correct value
    ;; (i.e. not number of characters).
    (setq body-bytes (buffer-size))

    ;; Make RESPONSE-BUF the current buffer, as we'll need to change
    ;; its major mode, coding system, etc.
    (set-buffer response-buf)

    ;; Copy bytes from `original-buffer' into it.
    (insert-buffer-substring original-buffer)

    (if binary-handler
        (progn
          ;; Response content is a binary format:
          (verb-util--log num 'I "Using binary handler: %s" binary-handler)

          (set-buffer-multibyte nil)
          (set-buffer-file-coding-system 'binary)
          (buffer-disable-undo)
          (funcall binary-handler))

      ;; else: Response content is text:
      (verb-util--log num 'I "Using text handler: %s" text-handler)

      ;; Choose corresponding coding system for charset.
      (setq coding-system (or (mm-charset-to-coding-system charset)
                              'utf-8))

      ;; Decode contents using coding system.
      (decode-coding-region (point-min) (point-max) coding-system)

      (set-buffer-file-coding-system coding-system)

      ;; Prepare buffer for editing by user.
      (funcall text-handler))

    (goto-char (point-min))

    ;; Kill original response buffer.
    (kill-buffer original-buffer)

    ;; Store details of request and response
    ;; `verb-http-response' is a permanent buffer local variable.
    (setq verb-http-response
          (verb-response :headers (nreverse headers)
                         :request rs
                         :status status-line
                         :duration elapsed
                         :body-bytes body-bytes
                         ;; TODO: Could this potentially be expensive
                         ;; for large responses?
                         :body (unless (zerop body-bytes)
                                 (verb--buffer-string-no-properties))))

    ;; Apply the response mapping function, if one was specified.
    (when-let ((map-response (verb--request-spec-metadata-get
                              rs "map-response"))
               (original-body (or (oref verb-http-response body) t)))
      (setq verb-http-response (funcall map-response verb-http-response))
      (unless (verb--object-of-class-p verb-http-response 'verb-response)
        (user-error (concat "Response mapping function `%s' must return a "
                            "`verb-response' value")
                    map-response))

      ;; If response mapping function updated the body, then update
      ;; the buffer contents as well.
      ;; Note that we compare using `eq' instead of `string='.
      ;; Technically `string=' should be used since strings are
      ;; mutable, but this is cheaper and probably good enough.
      (unless (eq original-body (or (oref verb-http-response body) t))
        (erase-buffer)
        (insert (oref verb-http-response body))))

    ;; Update global last response variable.
    (setq verb-last verb-http-response)

    ;; Store the response separately as well depending on user
    ;; metadata.
    (verb--maybe-store-response verb-http-response)

    (verb-response-body-mode)

    (when where
      (message "%s | %s %s"
               (oref verb-http-response status)
               (oref rs method)
               (verb-request-spec-url-to-string rs)))

    ;; Run post response hook.
    (run-hooks 'verb-post-response-hook)))