This is the first checked-in completely working version. It contains

nearly all concepts and simple implementations thereof needed to get a
simple HTTP/0.9 "compliant" server working (there are some hacks
needed that we don't yet provide, since the correct things will be
added shortly, like complete HTTP/1.1 request parsing.  The hacks
needed are provided as part of the basic HTTP/0.9 server demo in
src/test/basic-demo.cl).

Further work is needed to clean up some things, Entity and Resource
handling needs to be implemented right and less "naive" (the current
implementations are just simple place-holders to get things up and
running).  Connections need to have knowledge of client identity
(passed from the driver, this is implementation-specific stuff).
Logging needs to be implemented (probably as server mixins).
Condition handling needs to generate better responses for HTTP/0.9,
and the division between condition handling and normal handling needs
to be documented/rethought.  Content generation is totally missing
currently and needs to be implemented.  If this is all in place, an
HTTP/1.0 conforming server should be possible, and after porting the
drivers to ACL and LW, we can make a first release.
This commit is contained in:
1999-08-07 17:55:59 +00:00
parent 0a25f68f43
commit e1c4504ede
13 changed files with 898 additions and 7 deletions

112
src/main/entity.cl Normal file
View File

@ -0,0 +1,112 @@
;;;; CLASH --- The Common Lisp Adaptable Simple HTTP server
;;;; This is copyrighted software. See documentation for terms.
;;;;
;;;; entity.cl --- Entity Handling
;;;;
;;;; Checkout Tag: $Name$
;;;; $Id$
(in-package :CLASH)
;;;; %File Description:
;;;;
;;;;
;;;;
(defclass entity ()
())
(defgeneric render-entity-headers (entity stream))
(defgeneric render-entity-body (entity stream))
(defclass entity-header-mixin/1.1 ()
((allow :initarg :allow :reader entity-allow)
(content-base :initarg :content-base :reader entity-content-base)
(content-encoding :initarg :content-encoding
:reader entity-content-encoding)
(content-language :initarg :content-language
:reader entity-content-language)
(content-length :initarg :content-length :reader entity-content-length)
(content-location :initarg :content-location
:reader entity-content-location)
(content-md5 :initarg :content-md5 :reader entity-content-md5)
(content-range :initarg :content-range :reader entity-content-range)
(content-type :initarg :content-type :reader entity-content-type)
(etag :initarg :etag :reader entity-etag)
(expires :initarg :expires :reader entity-expires)
(last-modified :initarg :last-modified :reader entity-last-modified)))
(defmacro render-slots ((obj stream) &rest clauses)
(loop with obj-sym = (gensym)
with stream-sym = (gensym)
for (slot-spec string . body) in clauses
for slot = (if (consp slot-spec) (car slot-spec) slot-spec)
for slot-var = (if (consp slot-spec) (cadr slot-spec) slot-spec)
collect
`(when (slot-boundp ,obj-sym (quote ,slot))
(with-slots ((,slot-var ,slot)) ,obj-sym
(write-string ,string ,stream-sym)
(write-char #\: ,stream-sym)
(write-char #\Space ,stream-sym)
,@body
(write-char #\Return ,stream-sym)
(write-char #\Newline ,stream-sym)))
into clause-list
finally
(return `(let ((,stream-sym ,stream)
(,obj-sym ,obj))
,@clause-list))))
(defmethod render-entity-headers ((e entity-header-mixin/1.1) stream)
(render-slots (e stream)
(allow "Allow"
(write-http-element-list-1 allow stream))
(content-base "Content-Base"
(princ content-base stream))
(content-encoding "Content-Encoding"
(write-http-element-list-1 content-encoding stream))
(content-language "Content-Language"
(write-http-element-list-1 content-language stream))
(content-length "Content-Length"
(format stream "~D" content-length))
(content-location "Content-Location"
(princ content-location stream))
#+NIL
(content-md5 "Content-MD5"
(write-string (base64-encode-string content-md5) stream))
#+NIL
(content-range "Content-Range"
(princ content-range stream))
#+NIL
(content-type "Content-Type"
(princ content-type stream))
#+NIL
(etag "ETag"
(princ etag stream))
#+NIL
(expires "Expires"
(princ expires stream))
#+NIL
(last-modified "Last-Modified"
(princ last-modified stream))))
(defclass simple-entity (entity entity-header-mixin/1.1)
((body :initarg :body :reader entity-body :initform nil)))
(defmethod render-entity-body ((entity simple-entity) stream)
(etypecase (entity-body entity)
(string
(with-input-from-string (in-stream (entity-body entity))
(loop for line = (read-line in-stream nil nil)
while line
do (write-http-line line stream))))
(pathname
(with-open-file (in-stream (entity-body entity))
(let ((buffer (make-string (file-length in-stream))))
(+ (read-sequence buffer in-stream)
(length (write-sequence buffer stream))))))
(function
(funcall (entity-body entity) stream))))