![]() |
|
||||
![]() ![]() ![]() ![]() ![]() ![]() ![]() |
|||||
|
|
|||||
HTTP servers, creating |
|||||
This program implements a simple HTTP file server. It can be used with any web browser (including Lynx) . The server sends to the browser the contents of a named file, in an HTML or other format. The server also creates a log file containing the date, time, and IP address of each visit, as well as some details about which file was requested.
The program creates a TCP service on a given port, which the server uses to wait for an HTTP request. Once the server receives a request, the client's IP address is recorded in the log file ("simpserv.log"). The server then checks the requested file. If the file contains the shutdown command, the server terminates and sends a message to the browser indicating that the server has been shut down.
If the file does not contain the shutdown command, the server checks for the requested file. If no such file exists, an error message is recorded in the log file, and the response to the client is a "404 File Not Found" error message. If the file is found, the contents are loaded into the entity-body of the response, and then sent to the client. This transaction is now complete, and the server waits for the next one.
; Copyright, (c) 1998 by OmniMark Technologies Corporation
; All Rights Reserved
;
; This example illustrates the OmniMark implementation for a simple
; HTTP server. All file requests to the server are recorded in a ; log file. The server configuration,
; service port, log file name, file root dir and shutdown command
; can be specified on the command line.
; ex. omnimark -s simpserv.xom -c SvcPort 1080 -d RootDir "/http/files"
;
; OmniMark libraries: The HTTP library makes use of both the I/O
; Protocol library and the TCP library, so both must be included in
; the order they appear here.
declare function-library "omioprot"
include "omioprot.xin"
declare function-library "omtcp"
include "omtcp.xin"
include "omhttp.xin"
; macro for message display
macro DisplayLog is
put (#ERROR & OutFile) date "=Y/=M/=D =H:=m:=s " ||
macro-end
; server config - alternate values can be specified on command line
; if desired.
global integer SvcPort initial {80} ; service port number
global stream RootDir initial {"."} ; WWW root file dir
global stream ExitCmd initial {"shutdown"} ; request to stop server
global stream LogFile initial {"simpserv.log"} ; log file
; other global variables
global TCPService this-service; identifies the TCP service
global stream PathSep initial {mhttp_unixdirdelim}; refers to ; macros in omhttp.xin that specify the path delimiters for various ; platforms
global stream OutFile; creates the stream that will write to the log file
process
; start recording
; attaches the
reopen OutFile as file LogFile
; initialize the service
set this-service to TCPServiceOpen at SvcPort
DisplayLog "Server started on port %d(SvcPort)%n"
; set the path separator for the platfom. The default platform is UNIX. This action will determine the platform that is being run and choose the appropriate path separator.
set PathSep to mhttp_dosdirdelim
when #PLATFORM-INFO matches ("ms-dos"|"OS2"|"Windows")
; loop for request: Sets the service to await a request.
repeat
; local variables
local HttpRequest Request; creates the request shelf
local HttpResponse Response; creates the response shelf
local TCPConnection this-connection
local switch Continue initial {true}
; get a request
HttpServiceAwaitRequest
this-service receive Request connection this-connection
DisplayLog TCPConnectionGetPeerIP this-connection || "%n"
; check the requested file
do scan Request {"path"}
; if the file is the shutdown command, this will shut down the server
match [mhttp_dirdelim] ul(ExitCmd)
set Response {"entity-body"} to
"<html><body><h1>Server Shutdown</h1></body></html>"
set Continue to false
match [\ "#"]*=> FileName "#"? any*=>FilePos
; sets the path separator to the correct one for the platform in use
local stream PlatformFile
open PlatformFile as buffer
using output as PlatformFile
repeat scan RootDir||FileName
match [\mhttp_httpdirdelim]+=>nondelim
output nondelim
match mhttp_httpdirdelim
output PathSep
again
close PlatformFile
DisplayLog "Request for file %"%g(PlatformFile)%"%n"
; check for the file existence
do when file PlatformFile exists
; if the file exists, put its contents into the HTTP response shelf and write to the log that this has been done
DisplayLog "Sending file %"%g(PlatformFile)%"%n"
set Response {"entity-body"} to file PlatformFile
else
; if the file is not found, note this in the log and place an error report on the HTTP response shelf.
DisplayLog "File not found%n"
set Response {"status-code"} to "404"
set Response {"reason-phrase"} to "File Not Found"
set Response {"entity-body"} to
"<html><body><h1>File not found</h1></body></html>"
done
done
; send the response
HttpConnectionSendResponse this-connection send Response
; exit if request
exit when not Continue
again
DisplayLog "Server stopped%n"
close OutFile
This sample program implements a simple HTTP server that uses cookies to interact with the client browser. When the sample program is run, an OmniMark program records hits on the server machine, while passing cookies to the client. The OmniMark program records the date, time, and the client's IP address for each visit. The client will see a dynamically created HTML page displaying an HTTP header, with repeated hits incrementing the "cookies-visitcount" field.
The sample program creates a TCP service on a given port, which the server uses to wait for an HTTP request. When the server has received a request, the client's IP address and the date will be recorded in the OmniMark program. The sample program first checks the request for the shutdown command. If no shutdown command is received, the server generates an HTTP response that sends a dynamically created HTML page to the client. The cookie counter will be sent with the response, and will increment each time the page is reloaded.
If the client sends a shutdown command, the server will report a shutdown message to both the OmniMark program and the client, then shut down. This will end the TCP service and disconnect the server.
; Sample OmniMark implementation of an HTTP server that
; communicates
; with the client browser using cookies. The client makes the
; request to the server. If no user cookie is specified, the server
; generates a new ID for the user and transfers the cookie back to
; the user. If the client already has a user-id cookie, a visit-count
; cookie is incremented and returned to the client. The entire client
; request is returned for display on the client browser for testing
; and verification. The server configuration can be specified
; on the command line.
; sample command line:
; omnimark -s cookserv.xom -i ../../xin/ -x ../../lib -c svcport 1080 -d ExitCmd "^QUIT^"
; To connect to the server, the URL entered in the browser should be "http://<address>:<port number>
process
; OmniMark libraries - full path specifications must be included on the command line
declare function-library "omioprot"
include "omioprot.xin"
declare function-library "omtcp"
include "omtcp.xin"
declare function-library "omutil"
include "omutil.xin"
include "omhttp.xin"
include "omdate.xin"
; macro for message display - sets the date and time an entry is made in the message log
macro DisplayLog is
put (#ERROR & OutFile) date "=Y/=M/=D =H:=m:=s " ||
macro-end
; server configuration - specify on command line
global integer SvcPort initial {80} ; service port number
global stream RootDir initial {"."} ; WWW root file dir
global stream ExitCmd initial {"shutdown"} ; request to stop server
global stream LogFile initial {"cookserv.log"} ; log file
; other global variables
global TCPService this-service
global stream PathSep initial {mhttp_unixdirdelim}
global stream OutFile
; request handling routine
; the function reads the contents of the request shelf into Resp
define function RequestProcess
read-only stream Req
into modifiable stream Resp
as
; local variables
local stream Cookies variable
local integer UserID
local integer VisitCount
local stream Expires
; displays the contents of the request and response
; puts the output onto the Response shelf's "entity-body" item
open Resp {"entity-body"} as buffer
using output as Resp {"entity-body"}
do
output "<html><head><title>cookserv.xom</title></head><body>"
output "<h1>http Request</h1>"
repeat over Req
; examine each item on the Request shelf
output "<br>" || key of Req || " = %g(Req)"
again
output "<br></body></html>"
done
close Resp {"entity-body"}
; get the request cookies
HttpObjectGetCookieValues Req into Cookies
do when Cookies has key "userid"
set UserID to Cookies {"userid"}
else
set UserID to UTIL_UniformRand(1,100)
done
do when Cookies has key "visitcount"
set VisitCount to Cookies {"visitcount"} + 1
else
set VisitCount to 1
done
set Expires to ymdhms-to-arpadate ( add-to-ymdhms now-as-ymdhms months 1 )
; set some cookies
HttpObjectSetCookieValue Resp for 'UserID' to "%d(UserID)"
HttpObjectSetCookieAttribute Resp
for 'UserID' attribute 'Expires' to Expires
HttpObjectSetCookieAttribute Resp
for 'UserID' attribute 'Path' to '/'
HttpObjectSetCookieAttribute Resp
for 'UserID' attribute 'Version' to '1'
HttpObjectSetCookieValue Resp for 'VisitCount' to "%d(VisitCount)"
HttpObjectSetCookieAttribute Resp
for 'VisitCount' attribute 'Expires' to Expires
HttpObjectSetCookieAttribute Resp
for 'VisitCount' attribute 'Path' to '/'
HttpObjectSetCookieAttribute Resp
for 'VisitCount' attribute 'Version' to '1'
;return
process
; display version
put #ERROR HTTPLibraryVersion || "%n"
; start recording
reopen OutFile as file LogFile
; initialize the service
set this-service to TCPServiceOpen at SvcPort
DisplayLog "Server started on port %d(SvcPort)%n"
; set the path separator for the platform
set PathSep to mhttp_dosdirdelim
when #PLATFORM-INFO matches ("ms-dos"|"OS2"|"Windows")
; loop for request
repeat
; local variables
: HttpRequest and HttpResponse are http shelves defined in the omhttp.xin file
local HttpRequest Request
local HttpResponse Response
local TCPConnection this-connection
local switch Continue initial {true}
; get a request
HttpServiceAwaitRequest
this-service receive Request connection this-connection
DisplayLog (TCPConnectionGetPeerIP this-connection) || "%n"
; check the requested file
do when Request {"path"} matches ([mhttp_dirdelim] ul(ExitCmd))
set Response {"entity-body"} to
"<html><head></head><body><h1>Server shutdown</h1></body></html>"
set Continue to false
else
RequestProcess Request into Response
done
; send the response
HttpConnectionSendResponse this-connection send Response
; exit if request
exit when not Continue
again
DisplayLog "Server stopped%n"
close OutFile