/* --------------------------------------------------------------- */ /* WebServer -- a minimal single-thread HTTP server in Rexx */ /* --------------------------------------------------------------- */ /* */ /* Copyright (c) Mike Cowlishaw, 2005, 2012. All rights reserved. */ /* Parts Copyright (c) IBM, 2005. */ /* */ /* Permission to use, copy, modify, and distribute this software */ /* for any non-commercial purpose without fee is hereby granted, */ /* provided that the above copyright notice and this permission */ /* notice appear in all copies, and that notice and the date of */ /* any modifications be added to the software. */ /* */ /* This software is provided "as is". No warranties, whether */ /* express, implied, or statutory, including, but not limited to, */ /* implied warranties of merchantability and fitness for a */ /* particular purpose apply to this software. The author shall */ /* not, in any circumstances, be liable for special, incidental, */ /* or consequential damages, for any reason whatsoever. */ /* */ /* --------------------------------------------------------------- */ /* */ /* This is the skeleton for a simple web server; when a client */ /* (browser) attaches the header and data it sends are displayed, */ /* and a simple HTML 'page' is returned. */ /* */ /* When run as-is you should be able to connect to it on the same */ /* machine using the URL: http://127.0.0.1 [if a firewall is */ /* active it may need unblocking]. */ /* */ /* --------------------------------------------------------------- */ -- 2005.02.09 initial version -- 2005.02.09 initial version -- Load all functions call rxfuncadd sysloadfuncs, rexxutil, sysloadfuncs call sysloadfuncs call rxfuncadd "sockloadfuncs", "rxSock", "sockloadfuncs" call SockLoadFuncs('quiet') CRLF='0d0a'x -- useful /* Get a socket... */ socket=SockSocket("AF_INET", "SOCK_STREAM", "IPPROTO_TCP") if socket<0 then do say 'SockSocket failed:' socket return socket end call SockSetSockOpt socket, "SOL_SOCKET", "SO_REUSEADDR", 1 /* Bind... */ address.!family="AF_INET" address.!port=80 -- HTTP well-known port address.!addr="INADDR_ANY" rc=SockBind(socket, "address.!") if rc<0 then do say 'SockBind failed, errno='SockSock_Errno() return rc end client='?' signal on halt name halted say 'Listening...' /* Main loop waiting for requests */ do forever /* Listen for a request... */ say '...' rc=SockListen(socket, 1) if rc\=0 then do say 'SockListen error, rc='rc return rc end /* Accept a request... */ client=SockAccept(socket, "client.!" ) if client=-1 then do say 'SockAccept() failed' return -1 end /* Receive the message... */ data='' bytes=SockRecv(client, "data", 1000) if bytes<0 then do say 'SockRecv() failed' return -1 end say client.!family client.!port client.!addr', got:' bytes -- put header lines into HEADER., with the request in HEADER.0 heads=0 do forever parse var data header.heads (crlf) data say heads':' header.heads if header.heads=='' then leave -- reached separator line heads=heads+1 end -- here the body of the request (if any) remains in DATA say 'data: "'data'"' /* Send a reply... */ reply=''crlf, 'This is a bold statement.'crlf, '' rc=SockSend(client, reply, length(reply)) call SockClose client -- done with the connection client='?' -- no active client end -- forever loop halted: -- here on Halt break /* Close sockets and TCP/IP */ if client\='?' then call SockClose client call SockClose socket call SockDropFuncs exit