2011-02-20

Emacs で HTTP レスポンスヘッダを表示

emacs-w3m で = 打鍵してもヘッダは確認できますが、 URL をウェブブラウザで開く前に HEAD メソッドで手軽に確認したい、というのが今回の話。

以下のような時に使います。

  • Twitter 等でよく使われる短縮 URL の転送先の確認
  • ウェブページの最終更新日の確認
  • ウェブにアップロードされたファイルのサイズの確認

コマンドラインで
curl -I http://www.example.com/
でもいいのですが、 Emacs 使いならもっと手軽にやりたい。

Show HTTP response header

(defvar my-show-http-header-history nil
  "History list.")
(defvar my-show-http-header-config nil
  "Window configuration.")
(make-variable-buffer-local 'my-show-http-header-config)
(defvar my-show-http-header-name "*HTTP response header*"
  "Buffer name.")

(defun my-show-http-header-read ()
  (let ((default (progn
                   (unless (fboundp 'ffap-url-at-point)
                     (require 'ffap))
                   (ffap-url-at-point))))
    (read-string (if default
                     (format "URL (default %s): " default)
                   "URL: ")
                 nil 'my-show-http-header-history default)))

(defun my-show-http-header-colorize ()
  (save-excursion
    (goto-char (point-min))
    (while (re-search-forward
            "\\(^[Ll]ocation: \\|^[Ll]ast-[Mm]odified: \\)" nil t)
      (add-text-properties (point)
                           (line-end-position)
                           '(face font-lock-keyword-face)))))

(defun my-show-http-header (url &optional use-url)
  "Show HTTP response header of URL.
With prefix arg USE-URL, use `url-retrieve-synchronously'
instead of curl."
  (interactive
   (list (my-show-http-header-read) current-prefix-arg))
  (when (or (not (stringp url))
            (not (string-match "^https?://" url)))
    (error "No URL"))
  (let (window-config)
    ;; Save the window state before pop-to-buffer.
    (when (and (null (get-buffer-window my-show-http-header-name))
               (not (window-minibuffer-p (selected-window))))
      (setq window-config (current-window-configuration)))
    (pop-to-buffer (get-buffer-create my-show-http-header-name))
    (let (buffer-read-only)
      (unwind-protect
          (progn
            (erase-buffer)
            (insert (concat "URL: " url "\n\n"))
            (if use-url  ; or (null use-url) to inverse the prefix arg
                (insert-buffer (let ((url-max-redirections 0)
                                     (url-privacy-level 'paranoid)
                                     (url-request-method "HEAD"))
                                 (url-retrieve-synchronously url))))
            (call-process "curl" nil t nil
                          "-I" "-s" "-k"
                          "-A" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
                          url))
        (goto-char (point-min))
        (save-excursion
          (while (re-search-forward "\r\n" nil t)
            (replace-match "\n")))
        (my-show-http-header-colorize)))
      (when window-config
        (setq my-show-http-header-config window-config))
      (setq view-exit-action (lambda (buffer)
                               (when my-show-http-header-config
                                 (set-window-configuration
                                  my-show-http-header-config))
                               (kill-buffer buffer)))
      (view-mode-enter)))

;; (global-set-key "\C-cH" 'my-show-http-header)

特徴

  • カーソル位置の URL を読み取ってくれるので、手入力する手間が省けます。
  • q 打鍵一発で元のウィンドウの状態に戻ります。
  • Location ヘッダと Last-Modified ヘッダは色付けされます。
  • デフォルトでは外部プログラムの curl を使いますが、 C-u 付きで実行すれば Emacs に含まれる url.el ライブラリを使います。

サーバーによっては User-Agent や Referer 等のリクエストヘッダを見てレスポンスヘッダを変えてきたりしますが、その辺は curl のオプション等を適当にいじってみてください。

使い方
M-x my-show-http-header RET http://tinyurl.com/1awl RET

結果

URL: http://tinyurl.com/1awl

HTTP/1.1 301 Moved Permanently
X-Powered-By: PHP/5.3.5
Location: http://www.google.co.jp/
X-tiny: cache 0.00046396255493164
Content-type: text/html
Connection: close
Date: Wed, 18 Feb 2011 15:03:09 GMT
Server: TinyURL/1.6




動作確認: GNU Emacs 22, Mac OS X 10.6