Guide Home
POD Home

How-to...

This provides a place to start when trying to figure out how to do common web server tasks, such as getting query string values from a request or configuring for HTTPS. Stuff that has its own obvious guide page is usually not repeated here, so check the Guide TOC too.

Logging

Logging is accomplished through the Sloop::Logger class. This produces timestamped output; it is generally used via Sloop::Base::err_log(), ::debug_log(), or Sloop::Client::logReq(), which add a tag from the object's id in either square brackets (request), exclamation points (error), or curly braces (debugging). For clients id is by default fdN where N is the actual file descriptor (these will repeat, but there can only be one object with a particular descriptor at any given time). The err_log() and debug_log() methods also add the calling function, which may or may not be meaningful to you.

By default, one logger object is instantiated in the Sloop::Server constructor and then passed to Sloop::Client objects when they are created. If you want to differentiate between these, you may indicate a different logger object via the client_constructor attribute of the server object.

The default logger object logs errors and debugging messages to standard error and requests to standard output. Both streams are set to autoflush, i.e., non-buffered. You can override the streams used via the Sloop::Logger logs attribute. You can also subclass Sloop::Logger to override, e.g., the out() and/or timestamp() methods — but as mentioned, part of the format comes from methods in Sloop::Base and Sloop::Client.

There is also Sloop::Logger::SimpleColor and Sloop::Logger::TriColor if you want to differentiate things with ANSI color. For example, if out of curiosity you want to track how long a given connection lasts after the first request, you could do something like this in a handler:

my $client = shift;
my %colors = ('red', 'yellow', 'green', 'cyan', 'magenta');
$client->{id} =~ /fd(\d+)/;
my $n = $1 % ($#colors + 1);
$client->{logger} = Sloop::Logger::SimpleColor->new($colors[$n]);

Caching Pages

If you have pages that are generated dynamically from a source that only changes from time to time (as opposed to pages that are always unique in some way), you can probably make use of Sloop::Static::Cache. There is an example of this using markdown and Template Toolkit, markdownCache.pl.

Since the "source" for such pages isn't examined beyond the timestamp, you could conceivably use this to cache complex queries by using zero size files, named according to some schema, created when the first time a given query occurs.

Customizing Objects

Although it's an impossible sin in many other OO languages, perl allows you to attach whatever you want to an object, regardless of what that object is or where it came from. In a Sloop context, it may occasionally be useful with Sloop::Clients, etc., to tack on some arbitrary bit of data, rather than going the more conventional route of subclassing and providing an appropriate client_constructor to Sloop::Server.

To prevent collisions and confusion, it is a guarantee that no Sloop class ever uses an attribute starting with an underscore. Hence, anything you attach using such a key won't clobber or get clobbered.

Debugging

If something isn't happening the way you think it should, you can get a closer look at what is going on by setting the 'debug' parameter to Sloop::Server using one or more of the constants explained in Sloop::Constants.

Directory Indexing

See the index() function in Sloop::Static. There's also a demonstration of Sloop::Static::directory(), which uses index() by default, in simpleStatic.pl.

HTTPS/SSL/TLS

HTTPS support is provided by the GnuTLS library, which implements TLS 1.2 (the latest) as well as earlier protocol versions (1.1, 1.0, SSL 3.0). Configuring use with Sloop is done by providing appropriate details in the 'secure' argument to the Sloop::Server constructor.

Query Strings

See the qargs attribute and query() method of Sloop::Client::Request.

Uploading

Virtual Hosting

Sloop only supports name based virtual hosting.

Proxying

Currently Sloop doesn't support true HTTP CONNECT tunnelling, but you could approximate it using Sloop::Other. The issue is that Sloop always parses incoming messages as HTTP requests, so if you just want a web proxy, a (relatively inefficient) one is possible. There is a potential way around this if you dig into how Sloop::WebSocket works; a proper implementation will probably be in a near future version of Sloop.

Forking/Threading

Don't fork after initializing a Sloop::Server. It may seem okay at first, but eventually you will have a problem. Fork/exec is okay.

Sloop is thread safe in the sense that appropriate measures are taken in the XS code, including use of re-entrant functions. However, while using a sloop server in a multi-threaded application should be fine, actually accessing the object from multiple threads is largely untested. Since during run() it is continuously active and there are no internal locks, doing so is probably a very bad idea. If instead you want to access shared data from a sloop handler, beware when locking that you don't block for an indeterminate period of time.

If your concern is with generating very time consuming dynamic pages, it is probably better done by offloading the work to another instance via a Sloop::Other object and appropriate callbacks; the guide has a discussion of this.