.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Net::HTTPServer 3pm" .TH Net::HTTPServer 3pm "2022-12-06" "perl v5.36.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Net::HTTPServer \- HTTP server .SH "SYNOPSIS" .IX Header "SYNOPSIS" Net::HTTPServer provides a lite \s-1HTTP\s0 server. It can serve files, or can be configured to call Perl functions when a \s-1URL\s0 is accessed. .SH "DESCRIPTION" .IX Header "DESCRIPTION" Net::HTTPServer basically turns a \s-1CGI\s0 script into a stand alone server. Useful for temporary services, mobile/local servers, or embedding an \s-1HTTP\s0 server into another program. .SH "EXAMPLES" .IX Header "EXAMPLES" .Vb 1 \& use Net::HTTPServer; \& \& my $server = new Net::HTTPServer(port=>5000, \& docroot=>"/var/www/site"); \& \& $server\->Start(); \& \& $server\->Process(); # Run forever \& \& ...or... \& \& while(1) \& { \& $server\->Process(5); # Run for 5 seconds \& # Do something else... \& } \& \& $server\->Stop(); .Ve .SH "METHODS" .IX Header "METHODS" .SS "new(%cfg)" .IX Subsection "new(%cfg)" Given a config hash, return a server object that you can start, process, and stop. The config hash takes the options: .PP .Vb 6 \& chroot => 0|1 \- Run the server behind a virtual chroot(). \& Since only root can actually call chroot, \& a URL munger is provided that will not \& allow URLs to go beyond the document root \& if this is specified. \& ( Default: 1 ) \& \& datadir => string \- Path on the filesystem where you want to \& store the server side session files. \& ( Deault: "/tmp/nethttpserver.sessions" ) \& \& docroot => string \- Path on the filesystem that you want to be \& the document root "/" for the server. If \& set to undef, then the server will not serve \& any files off the local filesystem, but will \& still serve callbacks. \& ( Default: undef ) \& \& index => list \- Specify a list of file names to use as the \& the index file when a directory is requested. \& ( Default: ["index.html","index.htm"] ) \& \& log => string \- Path to store the log at. If you set this to \& "STDOUT" then it will display to STDOUT. \& ( Default: access.log ) \& \& mimetypes => string \- Path to an alternate mime.types file. \& ( Default: included in release ) \& \& numproc => int \- When type is set to "forking", this tells the \& server how many child processes to keep \& running at all times. \& ( Default: 5 ) \& \& oldrequests => 0|1 \- With the new request objects, old programs \& will not work. To postpone updating your \& code, just set this to 1 and your programs \& should work again. \& ( Default: 0 ) \& \& port => int \- Port number to use. You can optionally \& specify the string "scan", and the server \& will loop through ports until it finds one \& it can listen on. This port is then returned \& by the Start() method. \& ( Default: 9000 ) \& \& sessions => 0|1 \- Enable/disable server side session support. \& ( Default: 0 ) \& \& ssl => 0|1 \- Run a secure server using SSL. You must \& specify ssl_key, ssl_cert, and ssl_ca if \& set this to 1. \& ( Default: 0 ) \& \& ssl_ca => string \- Path to the SSL ca file. \& ( Default: undef ) \& \& ssl_cert => string \- Path to the SSL cert file. \& ( Default: undef ) \& \& ssl_key => string \- Path to the SSL key file. \& ( Default: undef ) \& \& type => string \- What kind of server to create? Available \& types are: \& single \- single process/no forking \& forking \- preforking server \& (Default: "single") .Ve .SS "AddServerTokens(token,[token,...])" .IX Subsection "AddServerTokens(token,[token,...])" Adds one or more tokens onto the Server header line that the server sends back in a response. The list is separated by a ; to distinguish the various tokens from each other. .PP .Vb 1 \& $server\->AddServerTokens("test/1.3"); .Ve .PP This would result in the following header being sent in a response: .PP \&\s-1HTTP/1.1 200\s0 Server: Net::HTTPServer/0.9 test/1.3 Content-Type: text/html \&... .SS "Process(timeout)" .IX Subsection "Process(timeout)" Listens for incoming requests and responds back to them. This function will block, unless a timeout is specified, then it will block for that number of seconds before returning. Useful for embedding this into other programs and still letting the other program get some \s-1CPU\s0 time. .SS "RegisterAuth(method,url,realm,function)" .IX Subsection "RegisterAuth(method,url,realm,function)" Protect the \s-1URL\s0 using the Authentication method provided. The supported methods are: \*(L"Basic\*(R" and \*(L"Digest\*(R". .PP When a \s-1URL\s0 with a path component that matchs the specified \s-1URL\s0 is requested the server requests that the client perform the specified of authentication for the given realm. When the \s-1URL\s0 is accessed the second time, the client provides the authentication pieces and the server parses the pieces and using the return value from the specified function answers the request. The function is called with the username and the \s-1URL\s0 they are trying to access. It is required that the function return a two item list with a return code and the users's password. .PP The valid return codes are: .PP .Vb 3 \& 200 The user exists and is allowed to access \& this URL. Return the password. \& return( "200", password ) \& \& 401 The user does not exist. Obviously you \& do not have to return a password in this \& case. \& return( "401" ) \& \& 403 The user is forbidden to access this URL. \& (You must still return the password because \& if the user did not auth, then we do not want \& to tip off the bad people that this username \& is valid.) \& return( "403", password ) .Ve .PP The reasoning for having the function return the password is that Digest authentication is just complicated enough that asking you to write part of logic would be considered rude. By just having you give the server the password we can keep the whole Auth interface simple. .PP Here is an example: .PP .Vb 1 \& $server\->RegisterAuth("Basic","/foo/bar.pl","Secure",\e&testBasic); \& \& sub testBasic \& { \& my $url = shift; \& my $user = shift; \& \& my $password = &lookupPassword($user); \& \& return("401","") unless defined($password); \& \& if (($url eq "/foo/bar.pl") && ($user eq "dr_evil")) \& { \& return ("403",$password); \& } \& \& return ("200",$password); \& } \& \& sub lookupPassword \& { \& my $user = shift; \& \& my %passwd; \& $passwd{larry} = "wall"; \& $passwd{dr_evil} = "1million"; \& \& return unless exists($passwd{$user}); \& return $passwd{$user}; \& } .Ve .PP Start a server with that, and the following RegisterURL example, and point your browser to: .PP .Vb 1 \& http://localhost:9000/foo/bar.pl?test=bing&test2=bong .Ve .PP You should be prompted for a userid and password, entering \*(L"larry\*(R" and \*(L"wall\*(R" will allow you to see the page. Entering \*(L"dr_evil\*(R" and \&\*(L"1million\*(R" should result in getting a Forbidden page (and likely needing to restart your browser). Entering any other userid or password should result in you being asked again. .PP If you have a handler for both RegisterURL and RegisterAuth, then your function for RegisterURL can find the identify of the user in the \f(CW\*(C`$env\->{\*(AqREMOTE_USER\*(Aq}\*(C'\fR hash entry. This is similar to \s-1CGI\s0 scripts. .PP You can have multiple handlers for different URLs. If you do this, then the longest complete \s-1URL\s0 handler will be called. For example, if you have handlers for \f(CW\*(C`/foo/bar.pl\*(C'\fR and \f(CW\*(C`/foo\*(C'\fR, and a \s-1URL\s0 of \f(CW\*(C`/foo/bar.pl\*(C'\fR is called, then the handler \f(CW\*(C`/foo/bar.pl\*(C'\fR is called to authorize this request, but if a \s-1URL\s0 of \f(CW\*(C`/foo/bar.html\*(C'\fR is called, then the handler \f(CW\*(C`/foo\*(C'\fR is called. .PP Only complete directories are matched, so if you had a handler for \&\f(CW\*(C`/foo/bar\*(C'\fR, then it would not be called for either /foo/bar.pl or \&\f(CW\*(C`/foo/bar.html\*(C'\fR. .SS "RegisterRegex(regex,function)" .IX Subsection "RegisterRegex(regex,function)" Register the function with the provided regular expression. When a \&\s-1URL\s0 that matches that regular expression is requested, the function is called and passed the environment (\s-1GET+POST\s0) so that it can do something meaningfiul with them. For more information on how the function is called and should be used see the section on RegisterURL below. .PP .Vb 1 \& $server\->RegisterRegex(".*.news$",\e&news); .Ve .PP This will match any \s-1URL\s0 that ends in \*(L".news\*(R" and call the &news function. The \s-1URL\s0 that the user request can be retrieved via the Request object ($reg\->\fBPath()\fR). .SS "RegisterRegex(hash ref)" .IX Subsection "RegisterRegex(hash ref)" Instead of calling RegisterRegex a bunch of times, you can just pass it a hash ref containing Regex/callback pairs. .PP .Vb 4 \& $server\->RegisterRegex({ \& ".*.news$" => \e&news, \& ".*.foo$" => \e&foo, \& }); .Ve .SS "RegisterURL(url,function)" .IX Subsection "RegisterURL(url,function)" Register the function with the provided \s-1URL.\s0 When that \s-1URL\s0 is requested, the function is called and passed in the environment (\s-1GET+POST\s0) so that it can do something meaningful with them. A simple handler looks like: .PP .Vb 1 \& $server\->RegisterURL("/foo/bar.pl",\e&test); \& \& sub test \& { \& my $req = shift; # Net::HTTPServer::Request object \& my $res = $req\->Response(); # Net::HTTPServer::Response object \& \& $res\->Print("\en"); \& $res\->Print(" \en"); \& $res\->Print(" This is a test\en"); \& $res\->Print(" \en"); \& $res\->Print(" \en"); \& $res\->Print("
\en");
\&
\&      foreach my $var (keys(%{$req\->Env()}))
\&      {
\&          $res\->Print("$var \-> ".$req\->Env($var)."\en");
\&      }
\&      
\&      $res\->Print("    
\en"); \& $res\->Print(" \en"); \& $res\->Print("\en"); \& \& return $res; \& } .Ve .PP Start a server with that and point your browser to: .PP .Vb 1 \& http://localhost:9000/foo/bar.pl?test=bing&test2=bong .Ve .PP You should see a page titled \*(L"This is a test\*(R" with this body: .PP .Vb 2 \& test \-> bing \& test2 \-> bong .Ve .SS "RegisterURL(hash ref)" .IX Subsection "RegisterURL(hash ref)" Instead of calling RegisterURL a bunch of times, you can just pass it a hash ref containing URL/callback pairs. .PP .Vb 4 \& $server\->RegisterURL({ \& "/foo/bar.pl" => \e&test1, \& "/foo/baz.pl" => \e&test2, \& }); .Ve .PP See \fBRegisterURL()\fR above for more information on how callbacks work. .SS "\fBStart()\fP" .IX Subsection "Start()" Starts the server based on the config options passed to \fBnew()\fR. Returns the port number the server is listening on, or undef if the server was unable to start. .SS "\fBStop()\fP" .IX Subsection "Stop()" Shuts down the socket connection and cleans up after itself. .SH "SESSIONS" .IX Header "SESSIONS" Net::HTTPServer provides support for server-side sessions much like \s-1PHP\s0's session model. A handler that you register can ask that the request object start a new session. It will check a cookie value to see if an existing session exists, if not it will create a new one with a unique key. .PP You can store any arbitrary Perl data structures in the session. The next time the user accesses your handler, you can restore those values and have them available again. When you are done, simple destroy the session. .SH "HEADERS" .IX Header "HEADERS" Net::HTTPServer sets a few headers automatically. Due to the timing of events, you cannot get to those headers programatically, so we will discuss them general. .PP Obviously for file serving, errors, and authentication it sends back all of the appropriate headers. You likely do not need to worry about those cases. In RegisterURL mode though, here are the headers that are added: .PP .Vb 9 \& Accept\-Ranges: none (not supported) \& Allow: GET, HEAD, POST, TRACE \& Content\-Length: \& Connection: close (not supported) \& Content\-Type: text/html (unless you set it) \& Date: \& Server: .Ve .PP If you have any other questions about what is being sent, try using \&\s-1DEBUG\s0 (later section). .SH "DEBUG" .IX Header "DEBUG" When you are writing your application you might see behavior that is unexpected. I've found it useful to check some debugging statements that I have in the module to see what it is doing. If you want to turn debugging on simply provide the debug => [ zones ] option when creating the server. You can optionally specify a file to write the log into instead of \s-1STDOUT\s0 by specifying the debuglog => file option. .PP I've coded the modules debugging using the concept of zones. Each zone (or task) has it's own debug messages and you can enable/disable them as you want to. Here are the list of available zones: .PP .Vb 9 \& INIT \- Initializing the sever \& PROC \- Processing a request \& REQ \- Parsing requests \& RESP \- Returning the response (file contents are not printed) \& AUTH \- Handling and authentication request \& FILE \- Handling a file system request. \& READ \- Low\-level read \& SEND \- Low\-level send (even prints binary characters) \& ALL \- Turn all of the above on. .Ve .PP So as an example: .PP .Vb 1 \& my $server = new Net::HTTPServer(..., debug=>["REQ","RESP"],...); .Ve .PP That would show all requests and responses. .SH "AUTHOR" .IX Header "AUTHOR" Ryan Eatmon .SH "COPYRIGHT" .IX Header "COPYRIGHT" Copyright (c) 2003\-2005 Ryan Eatmon . All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.