Cobra/MyHttpServer.cobra
< Cobra
use System
use System.Collections
use System.IO
use System.Net
use System.Net.Sockets
use System.Threading
class HttpProcessor
var _socket as TcpClient
pro socket as TcpClient
get
return _socket
set
_socket = value
var _srv as HttpServer
pro srv as HttpServer
get
return _srv
set
_srv = value
var __inputStream as Stream is private
var _outputStream as StreamWriter
pro outputStream as StreamWriter
get
return _outputStream
set
_outputStream = value
var _http_method as String = ''
pro http_method as String
get
return _http_method
set
_http_method = value
var _http_url as String = ''
pro http_url as String
get
return _http_url
set
_http_url = value
var _http_protocol_version_string as String = ''
pro http_protocol_version_string as String
get
return _http_protocol_version_string
set
_http_protocol_version_string = value
var _httpHeaders as Hashtable = Hashtable()
pro httpHeaders as Hashtable
get
return _httpHeaders
set
_httpHeaders = value
const MAX_POST_SIZE = 10 * 1024 * 1024
is private
const BUF_SIZE = 4096
is private
cue init(socket as TcpClient, srv as HttpServer)
base.init
.socket = socket
.srv = srv
__inputStream = BufferedStream(_socket.getStream)
_outputStream = StreamWriter(BufferedStream(_socket.getStream))
def streamReadLine(inputStream as Stream) as String
data = StringBuilder()
while true
next_char = inputStream.readByte
if next_char == Convert.toByte(c'\n'), break
if next_char == Convert.toByte(c'\r'), continue
if next_char == -1
Thread.sleep(1)
continue
data.append(Convert.toChar(next_char))
return data.toString
def parseRequest is public
request = .streamReadLine(__inputStream)
tokens = request.split(' ')
if tokens.length <> 3, throw Exception("invalid http request line")
_http_method = tokens[0].toUpper
_http_url = tokens[1]
_http_protocol_version_string = tokens[2]
print 'starting: [request]'
def readHeaders is public
print 'readHeaders()'
line as String?
while (line = .streamReadLine(__inputStream)) <> nil
if line.equals('')
print 'got headers'
return
separator = line.indexOf(c':')
if separator == -1, throw Exception('invalid http header line: [line]')
name = line.substring(0, separator)
pos = separator + 1
while (pos < line.length) and (line[pos] == c' '), pos += 1
value = line.substring(pos, line.length - pos)
print 'header: [name]:[value]'
_httpHeaders[name] = value
def handleGETRequest is public
_srv.handleGETRequest(this)
def process is public
print 'process()'
try
.parseRequest
.readHeaders
if _http_method.equals('GET'), .handleGETRequest
else if _http_method.equals('POST'), .handlePOSTRequest
catch e as Exception
print 'Exception: [e.toString]'
.writeFailure
_outputStream.flush
_socket.close
Thread.sleep(0)
def handlePOSTRequest is public
print 'get post data start'
content_len = 0
ms = MemoryStream()
if _httpHeaders.containsKey("Content-Length")
content_len = Convert.toInt32(_httpHeaders["Content-Length"])
if content_len > .MAX_POST_SIZE
throw Exception(String.format(
"POST Content-Length({0}) too big for this simple server",
content_len)
)
buf = uint8[](.BUF_SIZE)
to_read = content_len
while to_read > 0
print 'starting Read, to_read=[to_read]'
numread = __inputStream.read(buf, 0, Math.min(.BUF_SIZE, to_read))
print 'read finished, numread=[numread]'
if numread == 0
if to_read == 0, break
else, throw Exception('client disconnected during post')
to_read -= numread
ms.write(buf, 0, numread)
ms.seek(0, SeekOrigin.Begin)
print 'get post data end'
_srv.handlePOSTRequest(this, StreamReader(ms))
def writeSuccess is public
_outputStream.write('HTTP/1.0 200 OK\n')
_outputStream.write('Content-Type: text/html\n')
_outputStream.write('Connection: close\n')
_outputStream.write('\n')
def writeFailure is public
_outputStream.write('HTTP/1.0 404 File not found\n')
_outputStream.write('Connection: close\n')
_outputStream.write('\n')
class HttpServer is abstract
var _port as int is protected
var _listener as TcpListener?
var _is_active = true
cue init(port as int)
base.init
_port = port
def listen is public
#ipAddress = Dns.getHostEntry("localhost").addressList[0]
#_listener = TcpListener(ipAddress, _port)
_listener = TcpListener(IPAddress.any, _port)
_listener.start
while _is_active
s = _listener.acceptTcpClient
processor = HttpProcessor(s, this)
thread = Thread(ThreadStart(ref processor.process))
thread.start
Thread.sleep(1)
def handleGETRequest(p as HttpProcessor) is abstract
def handlePOSTRequest(p as HttpProcessor, inputData as StreamReader) is abstract
class MyHttpServer inherits HttpServer
cue init(port as int)
base.init(port)
def handleGETRequest(p as HttpProcessor) is public, override
print 'request: [p.http_url]'
p.writeSuccess
p.outputStream.writeLine('<html><body><h1>test server</h1>')
p.outputStream.writeLine('Current Time: [DateTime.now.toString]')
p.outputStream.writeLine('url : [p.http_url]')
p.outputStream.writeLine('<form method=post action=/form>')
p.outputStream.writeLine('<input type=text name=foo value=foovalue>')
p.outputStream.writeLine('<input type=submit name=bar value=barvalue>')
p.outputStream.writeLine('</form>')
def handlePOSTRequest(p as HttpProcessor, inputData as StreamReader) is public, override
print 'POST request: [p.http_url]'
data = inputData.readToEnd
p.outputStream.writeLine('<html><body><h1>test server</h1>')
p.outputStream.writeLine('<a href=/test>return</a><p>')
p.outputStream.writeLine('postbody: <pre>[data]</pre>')
class Program
def main
if CobraCore.commandLineArgs.count > 1
arg = CobraCore.commandLineArgs[1]
if arg.length > 0, httpServer = MyHttpServer(Convert.toInt32(arg))
else, httpServer = MyHttpServer(8080)
else
httpServer = MyHttpServer(8080)
thread = Thread(ThreadStart(ref httpServer.listen))
thread.start