httpd
上传用户:rrhhcc
上传日期:2015-12-11
资源大小:54129k
文件大小:5k
源码类别:

通讯编程

开发平台:

Visual C++

  1. #
  2. # The httpd_ procedures implement a stub http server.
  3. #
  4. # Copyright (c) 1997-1998 Sun Microsystems, Inc.
  5. # Copyright (c) 1999-2000 Scriptics Corporation
  6. #
  7. # See the file "license.terms" for information on usage and redistribution
  8. # of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  9. #
  10. # SCCS: @(#) httpd 1.2 98/02/20 14:51:59
  11. #set httpLog 1
  12. proc httpd_init {{port 8015}} {
  13.     socket -server httpdAccept $port
  14. }
  15. proc httpd_log {args} {
  16.     global httpLog
  17.     if {[info exists httpLog] && $httpLog} {
  18. puts stderr "httpd: [join $args { }]"
  19.     }
  20. }
  21. array set httpdErrors {
  22.     204 {No Content}
  23.     400 {Bad Request}
  24.     401 {Authorization Required}
  25.     404 {Not Found}
  26.     503 {Service Unavailable}
  27.     504 {Service Temporarily Unavailable}
  28.     }
  29. proc httpdError {sock code args} {
  30.     global httpdErrors
  31.     puts $sock "$code $httpdErrors($code)"
  32.     httpd_log "error: [join $args { }]"
  33. }
  34. proc httpdAccept {newsock ipaddr port} {
  35.     global httpd
  36.     upvar #0 httpd$newsock data
  37.     fconfigure $newsock -blocking 0 -translation {auto crlf}
  38.     httpd_log $newsock Connect $ipaddr $port
  39.     set data(ipaddr) $ipaddr
  40.     fileevent $newsock readable [list httpdRead $newsock]
  41. }
  42. # read data from a client request
  43. proc httpdRead { sock } {
  44.     upvar #0 httpd$sock data
  45.     if {[eof $sock]} {
  46. set readCount -1
  47.     } elseif {![info exists data(state)]} {
  48. # Read the protocol line and parse out the URL and query
  49. set readCount [gets $sock line]
  50. if [regexp {(POST|GET|HEAD) ([^?]+)??([^ ]*) HTTP/(1.[01])} 
  51. $line x data(proto) data(url) data(query) data(httpversion)] {
  52.     set data(state) mime
  53.     httpd_log $sock Query $line
  54. } else {
  55.     httpdError $sock 400
  56.     httpd_log $sock Error "bad first line:$line"
  57.     httpdSockDone $sock
  58. }
  59. return
  60.     } elseif {$data(state) == "mime"} {
  61. # Read the HTTP headers
  62. set readCount [gets $sock line]
  63.     } elseif {$data(state) == "query"} {
  64. # Read the query data
  65. if {![info exists data(length_orig)]} {
  66.     set data(length_orig) $data(length)
  67. }
  68. set line [read $sock $data(length)]
  69. set readCount [string length $line]
  70. incr data(length) -$readCount
  71.     }
  72.     # string compare $readCount 0 maps -1 to -1, 0 to 0, and > 0 to 1
  73.     set state [string compare $readCount 0],$data(state),$data(proto)
  74.     httpd_log $sock $state
  75.     switch -- $state {
  76. -1,mime,HEAD -
  77. -1,mime,GET -
  78. -1,mime,POST {
  79.     # gets would block
  80.     return
  81. }
  82. 0,mime,HEAD -
  83. 0,mime,GET -
  84. 0,query,POST { 
  85.     # Empty line at end of headers,
  86.     # or eof after query data
  87.     httpdRespond $sock
  88. }
  89. 0,mime,POST {
  90.     # Empty line between headers and query data
  91.     if {![info exists data(mime,content-length)]} {
  92. httpd_log $sock Error "No Content-Length for POST"
  93. httpdError $sock 400
  94. httpdSockDone $sock
  95.     } else {
  96. set data(state) query
  97. set data(length) $data(mime,content-length)
  98. # Special case to simulate servers that respond
  99. # without reading the post data.
  100. if {[string match *droppost* $data(url)]} {
  101.     fileevent $sock readable {}
  102.     httpdRespond $sock
  103. }
  104.     }
  105. }
  106. 1,mime,HEAD -
  107. 1,mime,POST -
  108. 1,mime,GET {
  109.     # A line of HTTP headers
  110.     if {[regexp {([^:]+):[  ]*(.*)}  $line dummy key value]} {
  111. set data(mime,[string tolower $key]) $value
  112.     }
  113. }
  114. -1,query,POST {
  115.     httpd_log $sock Error "unexpected eof on <$data(url)> request"
  116.     httpdError $sock 400
  117.     httpdSockDone $sock
  118. }
  119. 1,query,POST {
  120.     append data(query) $line
  121.     if {$data(length) <= 0} {
  122. set data(length) $data(length_orig)
  123. httpdRespond $sock
  124.     }
  125. }
  126. default {
  127.     if {[eof $sock]} {
  128. httpd_log $sock Error "unexpected eof on <$data(url)> request"
  129.     } else {
  130. httpd_log $sock Error "unhandled state <$state> fetching <$data(url)>"
  131.     }
  132.     httpdError $sock 404
  133.     httpdSockDone $sock
  134. }
  135.     }
  136. }
  137. proc httpdSockDone { sock } {
  138.     upvar #0 httpd$sock data
  139.     unset data
  140.     catch {close $sock}
  141. }
  142. # Respond to the query.
  143. proc httpdRespond { sock } {
  144.     global httpd bindata port
  145.     upvar #0 httpd$sock data
  146.     switch -glob -- $data(url) {
  147. *binary* {
  148.     set html "$bindata[info hostname]:$port$data(url)"
  149.     set type application/octet-stream
  150. }
  151. *post* {
  152.     set html "Got [string length $data(query)] bytes"
  153.     set type text/plain
  154. }
  155. default {
  156.     set type text/html
  157.     set html "<html><head><title>HTTP/1.0 TEST</title></head><body>
  158. <h1>Hello, World!</h1>
  159. <h2>$data(proto) $data(url)</h2>
  160. "
  161.     if {[info exists data(query)] && [string length $data(query)]} {
  162. append html "<h2>Query</h2>n<dl>n"
  163. foreach {key value} [split $data(query) &=] {
  164.     append html "<dt>$key<dd>$valuen"
  165.     if {$key == "timeout"} {
  166. after $value ;# pause
  167.     }
  168. }
  169. append html </dl>n
  170.     }
  171.     append html </body></html>
  172. }
  173.     }
  174.     
  175.     # Catch errors from premature client closes
  176.     catch {
  177. if {$data(proto) == "HEAD"} {
  178.     puts $sock "HTTP/1.0 200 OK"
  179. } else {
  180.     puts $sock "HTTP/1.0 200 Data follows"
  181. }
  182. puts $sock "Date: [clock format [clock clicks]]"
  183. puts $sock "Content-Type: $type"
  184. puts $sock "Content-Length: [string length $html]"
  185. puts $sock ""
  186. flush $sock
  187. if {$data(proto) != "HEAD"} {
  188.     fconfigure $sock -translation binary
  189.     puts -nonewline $sock $html
  190. }
  191.     }
  192.     httpd_log $sock Done ""
  193.     httpdSockDone $sock
  194. }