changeset 143:35eef880a5ac

emacs: add http-twiddle for POST debugging
author Augie Fackler <durin42@gmail.com>
date Thu, 17 Sep 2009 10:33:59 -0500
parents daceba28ace4
children a7deb3b738a2
files .elisp/http-twiddle.el .elisp/settings/10.require.el
diffstat 2 files changed, 154 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/.elisp/http-twiddle.el
@@ -0,0 +1,153 @@
+;;; http-twiddle.el -- send & twiddle & resend HTTP requests
+;;
+;; Version 1.0 written by Luke Gorrie <luke@synap.se> in February 2006
+;; This program belongs to the public domain.
+;;
+;; (downloaded from http://fresh.homeunix.net/~luke/misc/emacs/http-twiddle.el)
+;;
+;; This is a program for testing hand-written HTTP requests. You write
+;; your request in an Emacs buffer (using http-twiddle-mode) and then
+;; press `C-c C-c' each time you want to try sending it to the server.
+;; This way you can interactively debug the requests. To change port or
+;; destination do `C-u C-c C-c'.
+;;
+;; The program is particularly intended for the POST-"500 internal
+;; server error"-edit-POST loop of integration with SOAP programs.
+;;
+;; The mode is activated by `M-x http-twiddle-mode' or automatically
+;; when opening a filename ending with .http-twiddle.
+;;
+;; The request can either be written from scratch or you can paste it
+;; from a snoop/tcpdump and then twiddle from there.
+;;
+;; See the documentation for the `http-twiddle-mode' and
+;; `http-twiddle-mode-send' functions below for more details and try
+;; `M-x http-twiddle-mode-demo' for a simple get-started example.
+;;
+;; Tested with GNU Emacs 21.4.1 and not tested/ported on XEmacs yet.
+
+;;; Example buffer:
+
+;; POST / HTTP/1.0
+;; Connection: close
+;; Content-Length: $Content-Length
+;;
+;; The request body goes here
+
+(require 'font-lock)                    ; faces
+
+(eval-when-compile
+  (unless (fboundp 'define-minor-mode)
+    (require 'easy-mmode)
+    (defalias 'define-minor-mode 'easy-mmode-define-minor-mode))
+  (require 'cl))
+
+(define-minor-mode http-twiddle-mode
+  "Major mode for twiddling around with HTTP requests and sending them.
+Use `http-twiddle-mode-send' (\\[http-twiddle-mode-send]) to send the request."
+  nil
+  " http-twiddle"
+  '(("\C-c\C-c" . http-twiddle-mode-send)))
+
+(defvar http-twiddle-show-request t
+  "*Show the request in the transcript.")
+
+(add-to-list 'auto-mode-alist '("\\.http-twiddle$" . http-twiddle-mode))
+
+(defvar http-twiddle-endpoint nil
+  "Cache of the (HOST PORT) to send the request to.")
+
+(defvar http-twiddle-process nil
+  "Socket connected to the webserver.")
+
+(defvar http-twiddle-port-history '()
+  "History of port arguments entered in the minibuffer.
+\(To make XEmacs happy.)")
+
+(defvar http-twiddle-host-history '()
+  "History of port arguments entered in the minibuffer.
+\(To make XEmacs happy.)")
+
+(defun http-twiddle-mode-send (host port)
+  "Send the current buffer to the server.
+Linebreaks are automatically converted to CRLF (\\r\\n) format and any
+occurences of \"$Content-Length\" are replaced with the actual content
+length."
+  (interactive (http-twiddle-read-endpoint))
+  ;; close any old connection
+  (when http-twiddle-process
+    (kill-buffer (process-buffer http-twiddle-process)))
+  (let ((content (buffer-string)))
+    (with-temp-buffer
+      (insert content)
+      (http-twiddle-convert-cr-to-crlf)
+      (http-twiddle-expand-content-length)
+      (let ((request (buffer-string)))
+        (setq http-twiddle-process
+              (open-network-stream "http-twiddle" "*HTTP Twiddle*" host port))
+        (set-process-filter http-twiddle-process 'http-twiddle-process-filter)
+        (set-process-sentinel http-twiddle-process 'http-twiddle-process-sentinel)
+        (process-send-string http-twiddle-process request)
+        (save-selected-window
+          (pop-to-buffer (process-buffer http-twiddle-process))
+          (when http-twiddle-show-request
+            (insert request)
+            (set-window-start (selected-window) (point))
+            (add-text-properties (point-min) (point-max)
+                                 '(face font-lock-comment-face)))
+          (set-mark (point)))))))
+
+(defun http-twiddle-read-endpoint ()
+  "Return the endpoint (HOST PORT) to send the request to."
+  (if (and http-twiddle-endpoint (null current-prefix-arg))
+      http-twiddle-endpoint
+    (setq http-twiddle-endpoint
+          (list (read-string "Host: (default localhost) "
+                             nil 'http-twiddle-host-history "localhost")
+                (let ((input (read-from-minibuffer "Port: " nil nil t 'http-twiddle-port-history)))
+                  (if (integerp input)
+                      input
+                    (error "Not an integer: %S" input)))))))
+
+(defun http-twiddle-convert-cr-to-crlf ()
+  "Convert \\n linebreaks to \\r\\n in the whole buffer."
+  (save-excursion
+    (goto-char (point-min))
+    (while (re-search-forward "[^\r]\n" nil t)
+      (backward-char)
+      (insert "\r"))))
+
+(defun http-twiddle-expand-content-length ()
+  "Replace any occurences of $Content-Length with the actual Content-Length."
+  (save-excursion
+    (goto-char (point-min))
+    (let ((content-length
+           (save-excursion (when (search-forward "\r\n\r\n" nil t)
+                             (- (point-max) (point))))))
+      (unless (null content-length)
+        (let ((case-fold-search t))
+          (while (search-forward "$content-length" nil t)
+            (replace-match (format "%d" content-length) nil t)))))))
+
+(defun http-twiddle-process-filter (process string)
+  "Process data from the socket by inserting it at the end of the buffer."
+  (with-current-buffer (process-buffer process)
+    (goto-char (point-max))
+    (insert string)))
+
+(defun http-twiddle-process-sentinel (process what)
+  (with-current-buffer (process-buffer process)
+    (goto-char (point-max))
+    (let ((start (point)))
+      (insert "Connection closed\n")
+      (add-text-properties start (point) '(face font-lock-string-face)))))
+
+(defun http-twiddle-mode-demo ()
+  (interactive)
+  (pop-to-buffer (get-buffer-create "*http-twiddle demo*"))
+  (http-twiddle-mode 1)
+  (erase-buffer)
+  (insert "POST / HTTP/1.0\nContent-Length: $Content-Length\nConnection: close\n\nThis is the POST body.\n")
+  (message "Now press `C-c C-c' and enter a webserver address (e.g. google.com port 80)."))
+
+(provide 'http-twiddle)
--- a/.elisp/settings/10.require.el
+++ b/.elisp/settings/10.require.el
@@ -19,3 +19,4 @@
 (add-to-list 'auto-mode-alist '("\\.yml$" . yaml-mode))
 
 (require 'nose)
+(require 'http-twiddle)