summaryrefslogtreecommitdiffstatshomepage
path: root/tekuti/mod-lisp.scm
blob: 613bda951cedf9df87b86ad92e935d931db33763 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
;; Tekuti
;; Copyright (C) 2008 Andy Wingo <wingo at pobox dot com>

;; This program is free software; you can redistribute it and/or    
;; modify it under the terms of the GNU General Public License as   
;; published by the Free Software Foundation; either version 3 of   
;; the License, or (at your option) any later version.              
;;                                                                  
;; This program is distributed in the hope that it will be useful,  
;; but WITHOUT ANY WARRANTY; without even the implied warranty of   
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    
;; GNU General Public License for more details.                     
;;                                                                  
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, contact:
;;
;; Free Software Foundation           Voice:  +1-617-542-5942
;; 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
;; Boston, MA  02111-1307,  USA       gnu@gnu.org

;;; Commentary:
;;
;; This is the main script that will launch tekuti.
;;
;;; Code:

(define-module (tekuti mod-lisp)
  #:use-module (ice-9 rdelim)
  #:use-module (sxml simple)
  #:use-module (sxml transform)
  #:use-module (tekuti url)
  #:use-module (tekuti util)
  #:use-module (tekuti config)
  #:export (event-loop))

(define (read-headers socket)
  (define (read-line*)
    (let ((line (read-line socket)))
      (if (eof-object? line)
          (error "unexpected eof")
          line)))
  (let lp ((keys '()) (values '()))
    (let ((k (read-line*)))
      (if (string=? k "end")
          (reverse (map cons keys values))
          (lp (cons k keys) (cons (read-line*) values))))))

(define (write-headers headers port)
  (for-each
   (lambda (k v)
     (format port "~a\n~a\n" k v))
   (map car headers) (map cdr headers))
  (display "end\n" port))

(define xhtml-doctype
  (string-append
   "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" "
   "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"))

(define (connection-received socket sockaddr handle-request)
  (let ((headers (read-headers socket))
        (post-data "")) ;; blocks: (read-delimited "" socket)))

    (dbg "~a" headers)
    (catch #t
           (lambda ()
             (let ((sxml (handle-request headers post-data)))
               (write-headers '(("Status" . "200 OK")
                                ("Content-Type" . "text/html"))
                              socket)
               (display xhtml-doctype socket)
               (sxml->xml sxml socket)))
           (lambda args
             (write-headers '(("Status" . "500 Internal Server Error")
                              ("Content-Type" . "text/plain"))
                            socket)
             (write args socket)))
             
    (close-port socket)))

(define (event-loop handle-request)
  (pk 'listening)
  (let ((socket (socket PF_INET SOCK_STREAM 0)))
    (bind socket AF_INET (inet-aton *host*) *port*)
    (listen socket *backlog*)
    (unwind-protect
     (let lp ((pair (accept socket)))
       (pk pair)
       (connection-received (car pair) (cdr pair) handle-request)
       (pk 'done)
       (lp (accept socket)))
     (shutdown socket 2))))