stas 2002/12/15 09:32:04
Modified: src/docs/2.0 TODO
src/docs/2.0/devel/core apache_integration.pod
src/docs/2.0/user config.cfg
src/docs/2.0/user/coding coding.pod
src/docs/2.0/user/config config.pod
src/docs/2.0/user/intro start_fast.pod
Log:
a bunch of docco fixes and improvements
Revision Changes Path
1.4 +231 -1 modperl-docs/src/docs/2.0/TODO
Index: TODO
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/TODO,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- TODO 4 Dec 2002 02:58:26 -0000 1.3
+++ TODO 15 Dec 2002 17:32:04 -0000 1.4
@@ -52,9 +52,239 @@
If you create an apr object and register your own cleanup, you still
have that object until your registered cleanup is finished.
+---
+
+Need to integrate the following example, removed from overview.pod, in
+protocols.pod:
+
+
+=head2 Apache::CommandServer
+
+Our first protocol handler example took advange of Apache's server
+framework, but did not tap into any other modules. The next example
+is based on the example in the "TCP Servers with IO::Socket" section
+of the I<perlipc> manpage. Of course, we don't need C<IO::Socket>
+since Apache takes care of those details for us. The rest of that
+example can still be used to illustrate implementing a simple text
+protocol. In this case, one where a command is sent by the client to
+be executed on the server side, with results sent back to the client.
+
+The C<Apache::CommandServer> handler will support four commands:
+C<motd>, C<date>, C<who> and C<quit>. These are probably not commands
+which can be exploited, but should we add such commands, we'll want to
+limit access based on ip address/hostname, authentication and
+authorization. Protocol handlers need to take care of these tasks
+themselves, since we bypass the HTTP protocol handler.
+
+As with all C<PerlProcessConnectionHandlers>, we are passed an
+C<Apache::Connection> object as the first argument. Again, we will be
+directly accessing the client socket via the I<client_socket> method.
+The I<login> subroutine is called to check if access by this client
+should be allowed. This routine makes up for what we lost with the
+core HTTP protocol handler bypassed. First we call the
+C<Apache::RequestRec> I<new> method, which returns a I<request_rec>
+object, just like that which is passed at request time to
+C<Perl*Handlers> and returned by the subrequest API methods,
+I<lookup_uri> and I<lookup_file>. However, this "fake request" does
+not run handlers for any of the phases, it simply returns an object
+which we can use to do that ourselves. The C<location_merge> method
+is passed the "location" for this request, it will look up the
+C<E<lt>LocationE<gt>> section that matches the given name and merge it
+with the default server configuration. For example, should we only
+wish to allow access to this server from certain locations:
+
+ <Location Apache::CommandServer>
+ deny from all
+ allow from 10.*
+ </Location>
+
+The I<location_merge> method only looks up and merges the
+configuration, we still need to apply it. This is done in I<for>
+loop, iterating over three methods: I<run_access_checker>,
+I<run_check_user_id> and I<run_auth_checker>. These methods will call
+directly into the Apache functions that invoke module handlers for
+these phases and will return an integer status code, such as C<OK>,
+C<DECLINED> or C<FORBIDDEN>. If I<run_access_check> returns something
+other than C<OK> or C<DECLINED>, that status will be propagated up to
+the handler routine and then back up to Apache. Otherwise, the access
+check passed and the loop will break unless I<some_auth_required>
+returns true. This would be false given the previous configuration
+example, but would be true in the presense of a I<require> directive,
+such as:
+
+ <Location Apache::CommandServer>
+ deny from all
+ allow from 10.*
+ require user dougm
+ </Location>
+
+Given this configuration, I<some_auth_required> will return true. The
+I<user> method is then called, which will return false if we have not
+yet authenticated. A I<prompt> utility is called to read the username
+and password, which are then injected into the I<headers_in> table
+using the I<set_basic_credentials> method. The I<Authenticate> field
+in this table is set to a base64 encoded value of the
+username:password pair, exactly the same format a browser would send
+for I<Basic authentication>. Next time through the loop
+I<run_check_user_id> is called, which will in turn invoke any
+authentication handlers, such as I<mod_auth>. When I<mod_auth> calls
+the I<ap_get_basic_auth_pw()> API function (as all Basic auth modules
+do), it will get back the username and password we injected. If we
+fail authentication a B<401> status code is returned which we
+propagate up. Otherwise, authorization handlers are run via
+I<run_auth_checker>. Authorization handlers normally need the I<user>
+field of the I<request_rec> for its checks and that field was filled
+in when I<mod_auth> called I<ap_get_basic_auth_pw()>.
+
+Provided login is a success, a welcome message is printed and main
+request loop entered. Inside the loop the I<getline> function returns
+just one line of data, with newline characters stripped. If the
+string sent by the client is in our command table, the command is then
+invoked, otherwise a usage message is sent. If the command does not
+return a true value, we break out of the loop. Let's give it a try
+with this configuration:
+
+ Listen 8085
+ <VirtualHost _default_:8085>
+ PerlProcessConnectionHandler Apache::CommandServer
+
+ <Location Apache::CommandServer>
+ allow from 127.0.0.1
+ require user dougm
+ satisfy any
+ AuthUserFile /tmp/basic-auth
+ </Location>
+ </VirtualHost>
+
+ % telnet localhost 8085
+ Trying 127.0.0.1...
+ Connected to localhost (127.0.0.1).
+ Escape character is '^]'.
+ Login: dougm
+ Password: foo
+ Welcome to Apache::CommandServer
+ Available commands: motd date who quit
+ motd
+ Have a lot of fun...
+ date
+ Mon Mar 12 19:20:10 PST 2001
+ who
+ dougm tty1 Mar 12 00:49
+ dougm pts/0 Mar 12 11:23
+ dougm pts/1 Mar 12 14:08
+ dougm pts/2 Mar 12 17:09
+ quit
+ Connection closed by foreign host.
+
+=head2 Apache::CommandServer Source
+
+ package Apache::CommandServer;
+
+ use strict;
+ use Apache::Connection ();
+ use APR::Socket ();
+ use Apache::HookRun ();
+
+ use Apache::Const -compile => qw(OK DECLINED);
+
+ my @cmds = qw(motd date who quit);
+ my %commands = map { $_, \&{$_} } @cmds;
+
+ sub handler {
+ my Apache::Connection $c = shift;
+ my APR::Socket $socket = $c->client_socket;
+
+ if ((my $rc = login($c)) != Apache::OK) {
+ $socket->send("Access Denied\n");
+ return $rc;
+ }
+
+ $socket->send("Welcome to " . __PACKAGE__ .
+ "\nAvailable commands: @cmds\n");
+
+ for (;;) {
+ my $cmd;
+ next unless $cmd = getline($socket);
+
+ if (my $sub = $commands{$cmd}) {
+ last unless $sub->($socket) == APR::SUCCESS;
+ }
+ else {
+ $socket->send("Commands: @cmds\n");
+ }
+ }
+
+ return Apache::OK;
+ }
+
+ sub login {
+ my $c = shift;
+
+ my $r = Apache::RequestRec->new($c);
+ $r->location_merge(__PACKAGE__);
+
+ for my $method (qw(run_access_checker run_check_user_id
run_auth_checker)) {
+ my $rc = $r->$method();
+
+ if ($rc != Apache::OK and $rc != Apache::DECLINED) {
+ return $rc;
+ }
+
+ last unless $r->some_auth_required;
+
+ unless ($r->user) {
+ my $socket = $c->client_socket;
+ my $username = prompt($socket, "Login");
+ my $password = prompt($socket, "Password");
+
+ $r->set_basic_credentials($username, $password);
+ }
+ }
+
+ return Apache::OK;
+ }
+
+ sub getline {
+ my $socket = shift;
+ my $line;
+ $socket->recv($line, 1024);
+ return unless $line;
+ $line =~ s/[\r\n]*$//;
+ return $line;
+ }
+
+ sub prompt {
+ my($socket, $msg) = @_;
+ $socket->send("$msg: ");
+ getline($socket);
+ }
+
+ sub motd {
+ my $socket = shift;
+ open my $fh, '/etc/motd' or return;
+ local $/;
+ my $status = $socket->send(scalar <$fh>);
+ close $fh;
+ return $status;
+ }
+
+ sub date {
+ my $socket = shift;
+ $socket->send(scalar(localtime) . "\n");
+ }
+
+ sub who {
+ my $socket = shift;
+ $socket->send(scalar `who`);
+ }
+
+ sub quit {1}
+
+ 1;
+ __END__
+
----
---
1.3 +33 -2
modperl-docs/src/docs/2.0/devel/core/apache_integration.pod
Index: apache_integration.pod
===================================================================
RCS file:
/home/cvs/modperl-docs/src/docs/2.0/devel/core/apache_integration.pod,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- apache_integration.pod 9 Dec 2002 16:39:34 -0000 1.2
+++ apache_integration.pod 15 Dec 2002 17:32:04 -0000 1.3
@@ -20,7 +20,7 @@
=head2 The Link Between mod_perl and httpd
-I<mod_perl.c> defines a special structure:
+I<mod_perl.c> includes a special data structure:
module AP_MODULE_DECLARE_DATA perl_module = {
STANDARD20_MODULE_STUFF,
@@ -161,7 +161,7 @@
modperl_trace_level_set(s, NULL);
}
-=head1 The pre_config stage
+=head1 The C<pre_config> Phase
After Apache processes its command line arguments, creates various
pools and reads the configuration file in, it runs the registered
@@ -214,6 +214,37 @@
called for every section and subsection that includes mod_perl
directives (META: or inherits from such a section even though
specifies no mod_perl directives in it?).
+
+=head2 Virtual Hosts Fixup
+
+After the configuration tree is processed, C<ap_fixup_virtual_hosts()>
+is called. One of the responsibilities of this function is to merge
+the virtual hosts configuration objects with the base server's object.
+If there are virtual hosts, C<merge_server_configs()> calls
+C<modperl_config_srv_merge()> and C<modperl_config_dir_merge()> for
+each virtual host, to perform this merge for mod_perl configuration
+objects.
+
+META: is that's the place where everything restarts? it doesn't
+restart under debugger since we run with NODETACH I believe.
+
+=head2 The I<open_logs> Phase
+
+After Apache processes the configuration it's time for the
+I<open_logs> phase, executed by C<ap_run_open_logs()>. mod_perl has
+registered the C<modperl_hook_init()> hook to be called for this phase.
+
+META: complete what happens at this stage in mod_perl
+
+META: why is it called modperl_hook_init and not open_logs? is it
+because it can be called from other functions?
+
+=head2 The I<post_config> Phase
+
+Immediately after I<open_logs>, the I<post_config> phase follows. Here
+C<ap_run_post_config()> calls C<modperl_hook_post_config()>
+
+
=head1 Request Processing
1.18 +0 -1 modperl-docs/src/docs/2.0/user/config.cfg
Index: config.cfg
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/config.cfg,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -r1.17 -r1.18
--- config.cfg 9 Dec 2002 16:47:07 -0000 1.17
+++ config.cfg 15 Dec 2002 17:32:04 -0000 1.18
@@ -11,7 +11,6 @@
group => 'Introduction',
chapters => [qw(
intro/start_fast.pod
- intro/what_is_new.pod
overview/overview.pod
design/design.pod
)],
1.16 +29 -10 modperl-docs/src/docs/2.0/user/coding/coding.pod
Index: coding.pod
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/coding/coding.pod,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -r1.15 -r1.16
--- coding.pod 30 Aug 2002 12:23:07 -0000 1.15
+++ coding.pod 15 Dec 2002 17:32:04 -0000 1.16
@@ -155,15 +155,16 @@
know what you are doing.
-=head1 Threads Coding Issues under mod_perl
+=head1 Threads Coding Issues Under mod_perl
The following sections discuss threading issues when running mod_perl
under a threaded MPM.
=head2 Thread-environment Issues
-The only thing you have to worry about your code is that it's
-thread-safe and that you don't use functions that affect all threads.
+The "only" thing you have to worry about your code is that it's
+thread-safe and that you don't use functions that affect all threads
+in the same process.
Perl 5.8.0 itself is a thread-safe. That means that operations like
C<push()>, C<map()>, C<chomp()>, C<=>, C</>, C<+=>, etc. are
@@ -172,8 +173,8 @@
by the perl functions are thread-safe.
For example the function C<localtime()> is not thread-safe when the
-implementation of asctime(3) is not thread-safe. Other usually
-problematic functions include readdir(), srand(), etc.
+implementation of C<asctime(3)> is not thread-safe. Other usually
+problematic functions include C<readdir()>, C<srand()>, etc.
Another important issue that shouldn't be missed is what some people
refer to as I<thread-locality>. Certain functions executed in a single
@@ -183,7 +184,12 @@
thread that C<chdir()>'ed to that directory. Other functions with
similar effects include C<umask()>, C<chroot()>, etc. Currently there
is no cure for this problem. You have to find these functions in your
-code and replace them with different workarounds.
+code and replace them with alternative solutions which don't incur
+this problem.
+
+For more information refer to the I<perlthrtut>
+(I<http://perldoc.com/perl5.8.0/pod/perlthrtut.html>) manpage.
+
=head2 Deploying Threads
@@ -194,13 +200,26 @@
If you want to spawn your own threads, first of all study how the new
ithreads Perl model works, by reading the I<perlthrtut>, I<threads>
-and I<threads::shared> manpages.
+(I<http://search.cpan.org/search?query=threads>) and
+I<threads::shared>
+(I<http://search.cpan.org/search?query=threads%3A%3Ashared>) manpages.
Artur Bergman wrote an article which explains how to port pure Perl
-modules to work properly with Perl ithreads. Issues with chdir() and
-other functions that rely on shared process' datastructures are
-discussed. http://www.perl.com/lpt/a/2002/06/11/threads.html
+modules to work properly with Perl ithreads. Issues with C<chdir()>
+and other functions that rely on shared process' datastructures are
+discussed. I<http://www.perl.com/lpt/a/2002/06/11/threads.html>.
+
+=head2 Shared Variables
+
+Global variables are only global to the interpreter in which they are
+created. Other interpreters from other threads can't access that
+variable. Though it's possible to make existing variables shared
+between several threads running in the same process by using the
+function C<threads::shared::share()>. New variables can be shared by
+using the I<shared> attribute when creating them. This feature is
+documented in the I<threads::shared>
+(I<http://search.cpan.org/search?query=threads%3A%3Ashared>) manpage.
=head1 Maintainers
1.31 +3 -9 modperl-docs/src/docs/2.0/user/config/config.pod
Index: config.pod
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/config/config.pod,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- config.pod 6 Dec 2002 07:45:36 -0000 1.30
+++ config.pod 15 Dec 2002 17:32:04 -0000 1.31
@@ -1032,16 +1032,10 @@
=head1 Perl Interface to the Apache Configuration Tree
-META:
-
-Apache::Directive
-
-t/response/TestApache/conftree.pm
-
-
-
-
+META: any volunteers to write this section? see
+t/response/TestApache/conftree.pm for examples of using the api.
+L<Apache::Directive|docs::2.0::api::modperl_2.0::Apache::Directive>.
1.9 +25 -12 modperl-docs/src/docs/2.0/user/intro/start_fast.pod
Index: start_fast.pod
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/user/intro/start_fast.pod,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- start_fast.pod 3 Sep 2002 05:02:18 -0000 1.8
+++ start_fast.pod 15 Dec 2002 17:32:04 -0000 1.9
@@ -9,15 +9,18 @@
=head1 Installation
-First of all check that you have the L<mod_perl 2.0
+If you are a Win32 user, please refer to the L<Win32 installation
+document|docs::2.0::os::win32::install>.
+
+First, L<download|download::index> the mod_perl 2.0 source.
+
+Before installing mod_perl, you need check that you have the
+L<mod_perl 2.0
prerequisites|docs::2.0::user::install::install/Prerequisites>.
In this chapter we assume that httpd was installed under
I<$HOME/httpd/prefork>.
-Next, download the mod_perl 2.0 source from:
-I<http://perl.apache.org/download/>.
-
Now, configure mod_perl:
% tar -xvzf mod_perl-2.x.xx.tar.gz
@@ -42,6 +45,9 @@
=head1 Configuration
+If you are a Win32 user, please refer to the L<Win32 configuration
+document|docs::2.0::os::win32::config>.
+
Enable mod_perl built as DSO, by adding to I<httpd.conf>:
LoadModule perl_module modules/mod_perl.so
@@ -76,14 +82,12 @@
Check I<$HOME/httpd/prefork/logs/error_log> to see that the server has
started and it's a right one. It should say something similar to:
- [Tue Sep 03 12:34:57 2002] [notice] Apache/2.0.41-dev (Unix)
- mod_perl/1.99_05-dev Perl/v5.8.0 mod_ssl/2.0.41-dev OpenSSL/0.9.6d
+ [Tue Sep 03 12:34:57 2002] [notice] Apache/2.0.44 (Unix)
+ mod_perl/1.99_07 Perl/v5.8.0 mod_ssl/2.0.44 OpenSSL/0.9.6g
DAV/2 configured -- resuming normal operations
-
-
=head1 Registry Scripts
To enable registry scripts add to I<httpd.conf>:
@@ -118,7 +122,10 @@
If that didn't work check the I<error_log> file.
-
+For more information on the registry scripts refer to the
+C<L<ModPerl::Registry|docs::2.0::api::ModPerl-Registry::ModPerl::Registry>>
+manapage. (XXX: on day there will a tutorial on registry, should port
+it from 1.0's docs).
=head1 Handler Modules
@@ -127,6 +134,8 @@
response handler similar to the registry script from the previous
section:
+ #file:MyApache/Rocks.pm
+ #----------------------
package MyApache::Rocks;
use strict;
@@ -179,9 +188,13 @@
=head1 Troubleshooting
-If after reading the complete installation and configuration chapters
-you are still having problems, please L<report
-them|docs::2.0::user::help::help/Reporting_Problems>.
+If after reading the complete
+L<installation|docs::2.0::user::install::install> and L<configuration
+chapters|docs::2.0::user::config::config> you are still having
+problems, take a look at the L<troubleshooting
+sections|docs::2.0::user::troubleshooting::troubleshooting>. If the problem
+persist, please report them using the L<following
+guidelines|docs::2.0::user::help::help/Reporting_Problems>.
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]