This document describes the protocol used by JServ to communicate between mod_jserv.c (the module) and the Java servlet server (JServHandler). It works over a TCP socket. * STARTUP The module starts up JServHandler during its initialization phase. It should run java, with the appropriate classpath to contain the JDK, JSDK and JServ classes. It may also contains servlets, but note that those cannot be reloaded if changed. It should pass JServHandler one command-line arguments, the port it should run on. e.g.: "java jserv.apache.JServHandler 8007" If JServHandler is started with the "-m" command-line option, it will deactivate the authentication. This means that anyone on the machine can run servlets, so beware. Normally, it is started automatically by the module, without -m. Also, if JServ is started with -m, the host configuration is done by a property file and not stdin. The "-t" command-line option can also be used. If present, it will cause JServ to print a stack trace to System.err (stderr) whenever the servlet throws an exception or an error. This is in addition to the error it normally logs with the name and message of the exception. Then module then passes, to the java process's stdin, the secret authentication key (a string randomly generated by the server) and a newline. After, for every host that will use servlets, it sends one line contains minimally three pieces of information separated by tab : hostname propertyfile( servlet_repository)+ The first element is the name of the host that can run servlets. The second argument is the path to the property file for that host. Finally, follows a tab-delimited list of servlet repositories, either directories or zip/jar files. When all the host data has been sent. The module send a line containing "end". * REQUEST The request is made by opening a TCP connection to port JServHandler is running on. The socket should be opened to the loopback interface (127.0.0.1), request from any other address is refused by JServ. The module sends the request metadata to JServHandler. These are sent as lines, with two parts: A one-character identifier, and the data. This is preceded with a four-digit hex number indicating the length of the following string (with leading 0s), e.g. "000dHDate Friday", where "000d" is the length, "H" is the identifier, and "Date Friday" is the data. a) Authentication and Initialization The module sends "A" is the secret key generated by the server and passed to JServ earlier. If this is not correct, JServHandler will reject the response. b) Server name. The module sends "S". This is the host in which this servlet should be requested. This will determine where JServ will look to service the servlet. c) Repository and class name. The module sends "C". The first element is the repository to which the servlet has been map. This is currently unused but reserved for future extension where repository may be assigned a security model. The class name is the fully qualified name of the class in dot notation. i.e. foo.bar.Servlet. The servlet would load from one of the repository defined for that host or from the CLASSPATH. d) Environment variables The module sends "E". The vars should contain all the standard CGI variables, but should not include the HTTP_ set, since the HTTP headers are sent later. e.g, "EPATH_INFO /foo" The following variables are required. Most are CGI/1.1 variables, but a few are Apache-specific. The following should all be sent (except for those marked with an asterix(*), which should only be sent if appropriate), as well as any additional CGI variables available: AUTH_TYPE(*): The type of authentication used CONTENT_LENGTH(*): The length of the request entity CONTENT_TYPE(*): The media type of the request entity DOCUMENT_ROOT: The server's main document root. PATH_INFO(*): Extra URI path information PATH_TRANSLATED(*): The translated path info QUERY_STRING(*): The query arguments REQUEST_METHOD: The method used for the request REMOTE_USER(*): The authenticated username used for the request REMOTE_ADDR: The IP address of the requesting host REMOTE_HOST: The hostname of the requesting host (if available) SCRIPT_NAME: The URI portion that refers to the servlet SERVER_NAME: The hostname of the server SERVER_PORT: The port number of the server SERVER_PROTOCOL: The protocol used for the request SERVER_SOFTWARE: The name of the server software c) Request headers The module sends all of the client's request headers, in the form "H
". e.g., "HUser-Agent Mozilla/4.0 (Windows NT)" d) A blank line When all the E and H lines (they may be interpolated), the module sends a blank line. (i.e., 0-length) This indicates that the metadata has been completed. e) The request entity If there is a request entity, it is sent. If not, nothing further is sent. * RESPONSE The response consists of two parts, response headers and the response entity. This is sent basically the same way CGI responses are sent: a) Response Headers The headers to be set for the response should then be sent, in MIME format: "
:
", terminated with a crlf. Headers set here will be outputted by the server. The server will add the HTTP line, and Server:, Date: and other headers, so only headers that the servlet needs to set should be set. e.g., Content-type, Cookie, whatever. A few headers have special meanings: Status: This sets the response status to , with a status message of . This is the same as the CGI output header of the same name. e.g., "Status: 404 Not Found" Servlet-Log: This sends a message to be logged in the server's log. Servlet-Error: This indicates that JServHandler had an error occur. The server should send an error response back to the browser, with the status set by a separate Status: header (see above) - 500 should be used if Status: is not present. The strong should be logged to the server's error log, as the reason why the request failed. No response entity will be present for this response. When the last header has been sent, a blank line should be sent. b) Response Entity JServHandler outputs the contents of the response to the module through the socket. When it is finished, JServHandler closes the socket. This will indicate to the module that the request has been completed. SIGNAL HANDLING Since Java doesn't provide any facility for signal handling, after JServ is started and has read the host information via a stdin. It launches a thread that waits for signal token on stdin. These are three character strings (not newline-terminated) of the form "S##", where ## is the number (with leading 0, if neccessary) indicating a POSIX signal has been received, that JServ should deal with. Currently, JServ handles both SIGTERM (S15) and SIGHUP (S01) the same way : it calls destroy() on all its servlets and then quit via System.exit(0). If the signal was a SIGHUP, the parent process (Apache or manual-JServ) will reinstall Java. What this achieves is that the calling process can install a signal handler for itself and when receives such a signal sends it on stdin of JServ.