Skip to content

Instantly share code, notes, and snippets.

@gongo
Created April 30, 2014 13:24
Show Gist options
  • Save gongo/d8a985baa0f29c144450 to your computer and use it in GitHub Desktop.
Save gongo/d8a985baa0f29c144450 to your computer and use it in GitHub Desktop.
とある研修で、Web(HTTP)サーバの役割は HTTP Request を解析して対応する HTTP Response を返すだけだから Emacs Lisp でも簡単にサーバ書けるよって教えたい
;; See also https://github.com/skeeto/emacs-web-server
(defvar gongo-httpd->status-codes
'((200 . "OK") (403 . "Forbidden")))
(defun gongo-httpd:start ()
"8080 ポートで待ち受ける HTTP サーバを作成"
(interactive)
(make-network-process
:name "httpd"
:server t
:host 'local
:httpd-ip-family 'ipv4
:service 8080
:filter 'gongo-httpd:filter))
(defun gongo-httpd:stop ()
(interactive)
(when (process-status "httpd")
(delete-process "httpd")))
(defun gongo-httpd:filter (proc string)
"Request Header から User-Agent を探し出して
もしそいつが curl であれば 200 OK、そうでなければ 403 Forbidden"
(let ((headers (split-string string "[\n\r]+"))
agent)
(dolist (header headers)
(when (string-match "User-Agent: \\(.*\\)" header)
(setq agent (match-string 1 header))))
(if (string-match "curl" agent)
(gongo-httpd:response proc 200 "It's curl OK!!")
(gongo-httpd:response proc 403 "Not curl... NG...")))
(delete-process proc))
(defun gongo-httpd:response (proc status body)
(let ((status-name (cdr (assq status gongo-httpd->status-codes)))
(headers `("Connection: close"
"Content-Type: text/plain"
,(format "Content-Length: %d" (length body)))))
(with-temp-buffer
(insert (format "HTTP/1.1 %d %s\r\n" status status-name))
(dolist (header headers)
(insert (format "%s\r\n" header)))
(insert "\r\n\r\n")
(insert body)
(process-send-region proc (point-min) (point-max)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment