Shammer's Philosophy

My private adversaria

sbcl http GET client

とりあえずですが書いてみました。

(require :sb-bsd-sockets)

(defpackage web
  (:use :cl :sb-bsd-sockets))

(in-package web)

(defun resolve-hostname (name-or-IPv4Address)
  (car (host-ent-addresses
	(get-host-by-name name-or-IPv4Address))))

(defun send-http-line (socket request-line)
  (princ request-line socket)
  (princ (code-char 13) socket)
  (princ (code-char 10) socket))

(defun execute-http (destination-host destination-port uri)
  (let* ((client-sock (make-instance 'inet-socket :type :stream :protocol :tcp))
	 (stream (socket-make-stream client-sock :output t :input t)))
    (socket-connect client-sock (resolve-hostname destination-host) destination-port)
    (multiple-value-bind (addr port)
			 (socket-peername client-sock)
			 (format t "Connected to ~A:~A~%" addr port))
    (send-http-line stream (concatenate 'string	"GET " uri " HTTP/1.1"))
    (send-http-line stream (concatenate 'string "Host: " destination-host))
    (send-http-line stream (concatenate 'string "Connection: close"))
    (send-http-line stream "")
    (force-output stream)
    ;;;; Read response from here
    (do ()
	(nil)
	(let ((line (read-line stream nil 'eof)))
	  (when (equal line 'eof)
	    (return))
	  (format t "~A~%" line)))
    (socket-close client-sock)))
  

(execute-http "www.google.com" 80 "/")