home | O'Reilly's CD bookshelfs | FreeBSD | Linux | Cisco | Cisco Exam  


Writing Apache Modules with Perl and C
By:   Lincoln Stein and Doug MacEachern
Published:   O'Reilly & Associates, Inc.  - March 1999

Copyright © 1999 by O'Reilly & Associates, Inc.


 


   Show Contents   Previous Page   Next Page

Chapter 9 - Perl API Reference Guide / Other Core Perl API Classes
The Apache::Connection Class

The Apache::Connection class provides a Perl interface to the C-language conn_rec data structure, which provides various low-level details about the network connection back to the client. Within a handler, the connection object can be obtained by calling the Apache request object's connection() method. The connection object is not available outside of handlers for the various request phases because there is no connection established in those cases. By convention, we use the variable $c for connection objects.

sub handler {
 my $r = shift;
 my $c = $r->connection;
 ...
}

In this section we discuss the various methods made available by the connection object. They correspond closely to the fields of the C API conn_rec structure discussed in Chapter 10.

aborted()

This method returns true if the client has broken the connection prematurely. This can happen if the remote user's computer has crashed, a network error has occurred, or, more trivially, the user pressed the stop button before the request or response was fully transmitted. However, this value is only set if a soft timeout occurred.

if($c->aborted) {
  warn "uh,oh, the client has gone away!";
}

See the description of soft_timeout() earlier.

auth_type()

If authentication was used to access a password protected document, this method returns the type of authentication that was used, currently either Basic or Digest. This method is different from the request object's auth_type() method, which we discussed earlier, because the request object's method returns the value of the AuthType configuration directive; in other words, the type of authentication the server would like to use. The connection object's auth_type() method returns a value only when authentication was successfully completed and returns undef otherwise.

if($c->auth_type ne 'Basic') {
  warn "phew, I feel a bit better";
}

This method is read-only.

local_addr()

This method returns a packed SOCKADDR_IN structure in the same format as returned by the Perl Socket module's pack_sockaddr_in() function. This packed structure contains the port and IP address at the server's side of the connection. This is set by the server when the connection record is created, so it is always defined.

use Socket ();
sub handler {
 my $r = shift;
 my $local_add = $r->connection->local_addr;
 my($port, $ip) = Socket::unpack_sockaddr_in($local_add);
 ...
}

For obvious reasons, this method is read-only.

remote_addr()

This method returns a packed SOCKADDR_IN structure for the port and IP address at the client's side of the connection. This is set by the server when the connection record is created, so it is always defined.

Among other things, the information returned by this method and local_addr() can be used to perform RFC 1413 ident lookups on the remote client, even when the configuration directive IdentityCheck is turned off. Here is an example using Jan-Pieter Cornet's Net::Ident module:

use Net::Ident qw(lookupFromInAddr);
my $remoteuser = lookupFromInAddr ($c->local_addr,
                                  $c->remote_addr, 2);

remote_host()

This method returns the hostname of the remote client. It only returns the name if the HostNameLookups directive is set to On and the DNS lookup was successful--that is, the DNS contains a reverse name entry for the remote host. If hostname-based access control is in use for the given request, a double-reverse lookup will occur regardless of the HostNameLookups setting, in which case, the cached hostname will be returned. If unsuccessful, the method returns undef.

It is almost always better to use the high-level get_remote_host() method available from the Apache request object (discussed earlier). The high-level method returns the dotted IP address of the remote host if its DNS name isn't available, and it caches the results of previous lookups, avoiding overhead when you call the method multiple times.

my $remote_host = $c->remote_host || "nohost";
my $remote_host = $r->get_remote_host(REMOTE_HOST); # better

This method is read-only.

remote_ip()

This method returns the dotted decimal representation of the remote client's IP address. It is set by the server when the connection record is created and is always defined.

my $remote_ip = $c->remote_ip;

The remote_ip() can also be changed, which is helpful if your server is behind a proxy such as the squid accelerator. By using the X-Forwarded-For header sent by the proxy, the remote_ip can be set to this value so logging modules include the address of the real client. The only subtle point is that X-Forwarded-For may be multivalued in the case of a single request that has been forwarded across multiple proxies. It's safest to choose the last IP address in the list since this corresponds to the original client.

my $header = $r->headers_in->{'X-Forwarded-For'};
if( my $ip = (split /,\s*/, $header)[-1] ) {
  $r->connection->remote_ip($ip);
}

remote_logname()

This method returns the login name of the remote user, provided that the configuration directive IdentityCheck is set to On and the remote user's machine is running an identd daemon. If one or both of these conditions is false, the method returns undef.

It is better to use the high-level get_remote_logname() method which is provided by the request object. When the high-level method is called, the result is cached and reused if called again. This is not true of remote_logname().

my $remote_logname = $c->remote_logname || "nobody";
my $remote_logname = $r->get_remote_logname;  # better

user()

When Basic authentication is in effect, user() returns the name that the remote user provided when prompted for his username and password. The password itself can be recovered from the request object by calling get_basic_auth_pw().

my $username = $c->user;
   Show Contents   Previous Page   Next Page
Copyright © 1999 by O'Reilly & Associates, Inc.