Download
(require 'http-get)
(require 'http-cookies)
(defvar http-post-version "1.0.6")
(defun http-post (url parameters content-type &optional headers sentinel
version verbose bufname)
"Post to a URL in a buffer using HTTP 1.1, and return the process.
You can get the buffer associated with this process using
`process-buffer'.
PARAMETERS is an alist of parameters to use. Each element has the
form \(NAME . VALUE). These usually correspond to successful controls
on HTML forms.
CONTENT-TYPE is a coding system to use. Its upper case print name
will be used for the server. Possible values are `iso-8859-1' or
`euc-jp' and others.
The optional HEADERS are an alist where each element has the form
\(NAME . VALUE). Both must be strings and will be passed along with
the request. The reason CONTENT-TYPE is not just passed along as one
of the headers is that part of the Content-Type value is fixed and
cannot be changed: The basic encoding is implemented using
`html-url-encode' and is called application/x-www-form-urlencoded.
With optional argument SENTINEL, the buffer is not shown. It is the
responsibility of the sentinel to show it, if appropriate. A sentinel
function takes two arguments, process and message. It is called when
the process is killed, for example. This is useful when specifying a
non-persistent connection. By default, connections are persistent.
Add \(\"Connection\" . \"close\") to HEADERS in order to specify a
non-persistent connection. Usually you do not need to specify a
sentinel, and `ignore' is used instead, to prevent a message being
printed when the connection is closed.
If you want to filter the content as it arrives, bind
`http-filter-pre-insert-hook' and `http-filter-post-insert-hook'.
The optional argument VERSION specifies the HTTP version to use. It
defaults to version 1.0, such that the connection is automatically
closed when the entire document has been downloaded.
If the optional argument VERBOSE is non-nil, a message will show the
command sent to the server.
The coding system of the process is set to `binary', because we need to
distinguish between \\r and \\n. To correctly decode the text later,
use `decode-coding-region' and get the coding system to use from
`http-headers'."
(interactive)
(setq version (or version 1.0))
(unless (string-match
"https?://\\([^/:]+\\)\\(:\\([0-9]+\\)\\)?/\\(.*/\\)?\\([^:]*\\)"
url)
(error "Cannot parse URL %s" url))
(let* (host dir file port proc buf header body content-length
(use-curl (string-match "https" url))
(separator (if use-curl "\\r\\n" "\r\n")))
(unless bufname (setq bufname
(format "*HTTP POST %s *" url)))
(setq host (match-string 1 url)
port (or (and (setq port (match-string 3 url))
(string-to-int port)) 80)
dir (or (match-string 4 url) "")
file (or (match-string 5 url) "")
buf (get-buffer-create bufname))
(let (result)
(dolist (param parameters)
(setq result (cons (concat (car param) "="
(http-url-encode (cdr param)
content-type))
result)))
(setq body (mapconcat 'identity result "&")))
(setq header
(concat (if use-curl
""
(format "POST %s%s%s HTTP/%.1f%s"
(if http-proxy-host
(concat "http://" host "/")
"/") dir file version separator))
(format "Host: %s\r\n" host)
"Content-Type: application/x-www-form-urlencoded"
(format "; charset=%s%s"
(upcase (symbol-name content-type))
separator)
(format "Content-Length: %d%s" (length body) separator)))
(when http-emacs-use-cookies
(let ((cookie (http-cookies-build-header url)))
(when cookie (add-to-list 'headers cookie))))
(if headers
(setq header (concat header
(mapconcat (lambda (pair)
(concat (car pair) ": " (cdr pair)))
headers
separator)
(concat separator separator)))
(setq header (concat header separator)))
(if sentinel
(set-buffer buf)
(switch-to-buffer buf))
(erase-buffer)
(kill-all-local-variables)
(setq proc (if use-curl
(start-process "curl" buf "curl" "--compressed" "-H" (concat "\"" header "\"") "-X" "POST" "--data-binary" (concat "\"" body "\"") url)
(open-network-stream
(concat "HTTP POST " url)
buf (if http-proxy-host http-proxy-host host)
(if http-proxy-port http-proxy-port port))))
(set-process-sentinel proc (or sentinel 'ignore))
(set-process-coding-system proc 'binary 'binary)
(set-process-filter proc 'http-filter)
(set-marker (process-mark proc) (point-min) buf)
(with-current-buffer buf
(setq http-host host)
(setq http-url url)
(when use-curl (setq curl-command (process-command proc))))
(when verbose
(message "%s" (concat header body "\n\n")))
(unless use-curl
(process-send-string proc (concat header body separator)))
proc))
(provide 'http-post)