Files
eww-http-code-advice-el/eww-http-code-advice.el
2026-03-26 01:11:50 -07:00

107 lines
3.7 KiB
EmacsLisp

;;; eww-http-code-advice.el --- Add HTTP status code tracking to eww -*- lexical-binding: t; -*-
;; Copyright (C) 2026 Robert Rose
;; Author: Robert Rose <robert@consignat.io>
;; Version: 0.1
;; Package-Requires: ((emacs "25.1"))
;; Keywords: comm, hypermedia
;; URL: https://consignat.io
;; This file is not part of GNU Emacs.
;; This package is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 3, or (at your option)
;; any later version.
;; This package is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Advises `eww-render' to capture the HTTP response status code
;; (from `url-http-response-status') and store it in `eww-data' as
;; `:status-code'. Provides `eww-http-status-string' for display.
;;; Code:
(defvar eww-http-status-codes
'((100 . "Continue")
(101 . "Switching Protocols")
(102 . "Processing")
(200 . "OK")
(201 . "Created")
(202 . "Accepted")
(203 . "Non-Authoritative Information")
(204 . "No Content")
(205 . "Reset Content")
(206 . "Partial Content")
(300 . "Multiple Choices")
(301 . "Moved Permanently")
(302 . "Found")
(303 . "See Other")
(304 . "Not Modified")
(307 . "Temporary Redirect")
(308 . "Permanent Redirect")
(400 . "Bad Request")
(401 . "Unauthorized")
(403 . "Forbidden")
(404 . "Not Found")
(405 . "Method Not Allowed")
(408 . "Request Timeout")
(409 . "Conflict")
(410 . "Gone")
(413 . "Payload Too Large")
(414 . "URI Too Long")
(415 . "Unsupported Media Type")
(418 . "I'm a Teapot")
(429 . "Too Many Requests")
(451 . "Unavailable For Legal Reasons")
(500 . "Internal Server Error")
(501 . "Not Implemented")
(502 . "Bad Gateway")
(503 . "Service Unavailable")
(504 . "Gateway Timeout"))
"Alist mapping HTTP status codes to reason phrases.")
(defun eww-http-status-string ()
"Return the HTTP status code and reason for the current eww page."
(let ((code (plist-get eww-data :status-code)))
(if code
(format "%d %s" code
(or (alist-get code eww-http-status-codes) "Unknown"))
"No status")))
;; Plain variables to shuttle data from :before to :after — the data
;; buffer is killed inside eww-render so buffer-local won't survive.
(defvar eww-render-fix--pending-status nil)
(defvar eww-render-fix--pending-error nil)
(defun eww-render-fix--before (status _url &rest _args)
"Capture `url-http-response-status' and error from STATUS.
Runs as :before advice on `eww-render' in the data buffer."
(setq eww-render-fix--pending-status
(bound-and-true-p url-http-response-status))
(setq eww-render-fix--pending-error
(plist-get status :error)))
(defun eww-render-fix--after (_status _url &optional _point buffer &rest _)
"Store captured status code and error into `eww-data'.
Runs as :after advice on `eww-render'."
(when (and buffer (buffer-live-p buffer))
(with-current-buffer buffer
(plist-put eww-data :status-code eww-render-fix--pending-status)
(plist-put eww-data :error eww-render-fix--pending-error))))
(advice-add 'eww-render :before #'eww-render-fix--before)
(advice-add 'eww-render :after #'eww-render-fix--after)
(provide 'eww-http-code-advice)
;;; eww-http-code-advice.el ends here