<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.zh-cn.xsl"?>
-<!-- English Revision: 586770:1326058 (outdated) -->
+<!-- English Revision: 586770:1325333 (outdated) -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
arguments. For example, if the hook returns an <code>int</code> and
takes a <code>request_rec *</code> and an <code>int</code> and is
called <code>do_something</code>, then declare it like this:</p>
- <example>
+ <highlight language="c">
AP_DECLARE_HOOK(int, do_something, (request_rec *r, int n))
- </example>
+ </highlight>
<p>This should go in a header which modules will include if
they want to use the hook.</p>
which is used to record the module functions that use the hook.
This is declared as follows:</p>
- <example>
- APR_HOOK_STRUCT(<br />
- <indent>
- APR_HOOK_LINK(do_something)<br />
- ...<br />
- </indent>
+ <highlight language="c">
+ APR_HOOK_STRUCT(
+ APR_HOOK_LINK(do_something)
+ ...
)
- </example>
+ </highlight>
</section>
<section id="create-implement"><title>Implement the hook caller</title>
<p>If the return value of a hook is <code>void</code>, then all the
hooks are called, and the caller is implemented like this:</p>
- <example>
+ <highlight language="c">
AP_IMPLEMENT_HOOK_VOID(do_something, (request_rec *r, int n), (r, n))
- </example>
+ </highlight>
<p>The second and third arguments are the dummy argument
declaration and the dummy arguments as they will be used when
calling the hook. In other words, this macro expands to
something like this:</p>
- <example>
- void ap_run_do_something(request_rec *r, int n)<br />
- {<br />
- <indent>
- ...<br />
- do_something(r, n);<br />
- </indent>
+ <highlight language="c">
+ void ap_run_do_something(request_rec *r, int n)
+ {
+ ...
+ do_something(r, n);
}
- </example>
+ </highlight>
</section>
<section><title>Hooks that return a value</title>
<p>If the hook returns a value, then it can either be run until
the first hook that does something interesting, like so:</p>
- <example>
+ <highlight language="c">
AP_IMPLEMENT_HOOK_RUN_FIRST(int, do_something, (request_rec *r, int n), (r, n), DECLINED)
- </example>
+ </highlight>
<p>The first hook that does <em>not</em> return <code>DECLINED</code>
stops the loop and its return value is returned from the hook
value other than one of those two stops the loop, and its
return is the return value. Declare these like so:</p>
- <example>
+ <highlight language="c">
AP_IMPLEMENT_HOOK_RUN_ALL(int, do_something, (request_rec *r, int n), (r, n), OK, DECLINED)
- </example>
+ </highlight>
<p>Again, <code>OK</code> and <code>DECLINED</code> are the traditional
values. You can use what you want.</p>
<p>At appropriate moments in the code, call the hook caller,
like so:</p>
- <example>
- int n, ret;<br />
- request_rec *r;<br />
- <br />
+ <highlight language="c">
+ int n, ret;
+ request_rec *r;
+
ret=ap_run_do_something(r, n);
- </example>
+ </highlight>
</section>
</section>
<p>Include the appropriate header, and define a static function
of the correct type:</p>
- <example>
+ <highlight language="c">
static int my_something_doer(request_rec *r, int n)<br />
- {<br />
- <indent>
- ...<br />
- return OK;<br />
- </indent>
+ {
+ ...
+ return OK;
}
- </example>
+ </highlight>
</section>
<section id="hooking-add"><title>Add a hook registering function</title>
registering function, which is included in the module
structure:</p>
- <example>
- static void my_register_hooks()<br />
- {<br />
- <indent>
- ap_hook_do_something(my_something_doer, NULL, NULL, APR_HOOK_MIDDLE);<br />
- </indent>
- }<br />
- <br />
- mode MODULE_VAR_EXPORT my_module =<br />
- {<br />
- <indent>
- ...<br />
- my_register_hooks /* register hooks */<br />
- </indent>
+ <highlight language="c">
+ static void my_register_hooks()
+ {
+ ap_hook_do_something(my_something_doer, NULL, NULL, APR_HOOK_MIDDLE);
+ }
+
+ mode MODULE_VAR_EXPORT my_module =
+ {
+ ...
+ my_register_hooks /* register hooks */
};
- </example>
+ </highlight>
</section>
<section id="hooking-order"><title>Controlling hook calling order</title>
example, suppose we want "mod_xyz.c" and "mod_abc.c" to run
before we do, then we'd hook as follows:</p>
- <example>
- static void register_hooks()<br />
- {<br />
- <indent>
- static const char * const aszPre[] = { "mod_xyz.c", "mod_abc.c", NULL };<br />
- <br />
- ap_hook_do_something(my_something_doer, aszPre, NULL, APR_HOOK_MIDDLE);<br />
- </indent>
+ <highlight language="c">
+ static void register_hooks()
+ {
+ static const char * const aszPre[] = { "mod_xyz.c", "mod_abc.c", NULL };
+
+ ap_hook_do_something(my_something_doer, aszPre, NULL, APR_HOOK_MIDDLE);
}
- </example>
+ </highlight>
<p>Note that the sort used to achieve this is stable, so
ordering set by <code>APR_HOOK_<var>ORDER</var></code> is preserved, as far
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.zh-cn.xsl"?>
-<!-- English Revision: 1042988:1326057 (outdated) -->
+<!-- English Revision: 1042988:1325816 (outdated) -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
For now, we're only concerned with the first purpose of the module name,
which comes into play when we need to load the module:
</p>
-<example><pre><a href="../mod/mod_so.html#LoadModule">LoadModule</a> example_module modules/mod_example.so</pre></example>
+<highlight language="config">
+LoadModule example_module modules/mod_example.so
+</highlight>
<p>
In essence, this tells the server to open up <code>mod_example.so</code> and look for a module
called <code>example_module</code>.
<code>mod_example</code>, so we'll add a configuration directive that tells
the server to do just that:
</p>
-<example><pre>
+<highlight language="config">
AddHandler example-handler .sum
-</pre></example>
+</highlight>
<p>
What this tells the server is the following: <em>Whenever we receive a request
for a URI ending in .sum, we are to let all modules know that we are
telling an individual module (or a set of modules) how to behave, such as
these directives control how <code>mod_rewrite</code> works:
</p>
-<example><pre>
+<highlight language="config">
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/foo/bar
RewriteRule ^/foo/bar/(.*)$ /foobar?page=$1
-</pre></example>
+</highlight>
<p>
Each of these configuration directives are handled by a separate function,
that parses the parameters given and sets up a configuration accordingly.
So far so good. To access our new handler, we could add the following to
our configuration:
</p>
-<example><pre>
+<highlight language="config">
<Location /example>
SetHandler example-handler
</Location>
-</pre></example>
+</highlight>
<p>
When we visit, we'll see our current configuration being spit out by our
module.
<!-- END EXAMPLE CODE -->
<p>
-<img src="../images/build_a_mod_4.png" alt="Directives structure" /><br />
+<img src="../images/build_a_mod_4.png" alt="Directives structure"/><br />
As you can see, each directive needs at least 5 parameters set:
</p>
<ol>
In our httpd.conf file, we can now change the hard-coded configuration by
adding a few lines:
</p>
-<example><pre>
+<highlight language="config">
ExampleEnabled On
ExamplePath "/usr/bin/foo"
ExampleAction file allow
-</pre></example>
+</highlight>
<p>
And thus we apply the configuration, visit <code>/example</code> on our
web site, and we see the configuration has adapted to what we wrote in our
configurations. This part of the process particularly apply to scenarios
where you have a parent configuration and a child, such as the following:
</p>
-<example><pre>
+<highlight language="config">
<Directory "/var/www">
ExampleEnable On
ExamplePath /foo/bar
<Directory "/var/www/subdir">
ExampleAction file deny
</Directory>
-</pre></example>
+</highlight>
<p>
In this example, it is natural to assume that the directory <code>
/var/www/subdir</code> should inherit the value set for the <code>/var/www
context aware. First off, we'll create a configuration that lets us test
how the module works:
</p>
-<example><pre>
+<highlight language="config">
<Location "/a">
SetHandler example-handler
ExampleEnabled on
ExamplePath "/foo/bar/baz"
ExampleEnabled on
</Location>
-</pre></example>
+</highlight>
<p>
Then we'll assemble our module code. Note, that since we are now using our
name tag as reference when fetching configurations in our handler, I have
<section id="moddef"><title>Module Definition</title>
<p>There are now a lot fewer stages to worry about when
- creating your module definition. The old defintion looked
+ creating your module definition. The old definition looked
like</p>
<example><pre>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE manualpage SYSTEM "../style/manualpage.dtd">
<?xml-stylesheet type="text/xsl" href="../style/manual.en.xsl"?>
-<!-- English Revision: 420993:462914 (outdated) -->
+<!-- English Revision: 420993:1328338 (outdated) -->
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
private to the filter).</p>
<example><title>How to handle an empty brigade</title>
+ <highlight language="c">
apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)<br />
- {<br />
- <indent>
- if (APR_BRIGADE_EMPTY(bb)) {<br />
- <indent>
- return APR_SUCCESS;<br />
- </indent>
- }<br />
- ....<br />
- </indent>
+ {
+ if (APR_BRIGADE_EMPTY(bb)) {
+ return APR_SUCCESS;
+ }
+ ....
+ </highlight>
</example>
</section>
follows:</p>
<example><title>Bad output filter -- do not imitate!</title>
- apr_bucket *e = APR_BRIGADE_FIRST(bb);<br />
-const char *data;<br />
-apr_size_t len;<br />
-<br />
-while (e != APR_BRIGADE_SENTINEL(bb)) {<br />
-<indent>
- apr_bucket_read(e, &data, &length, APR_BLOCK_READ);<br />
- e = APR_BUCKET_NEXT(e);<br />
-</indent>
-}<br />
-<br />
+ <highlight language="c">
+apr_bucket *e = APR_BRIGADE_FIRST(bb);
+const char *data;
+apr_size_t len;
+
+while (e != APR_BRIGADE_SENTINEL(bb)) {
+ apr_bucket_read(e, &data, &length, APR_BLOCK_READ);
+ e = APR_BUCKET_NEXT(e);
+
+}
+
return ap_pass_brigade(bb);
+</highlight>
</example>
<p>The above implementation would consume memory proportional to
href="#state">Maintaining state</a> section.</p>
<example><title>Better output filter</title>
-apr_bucket *e;<br />
-const char *data;<br />
-apr_size_t len;<br />
-<br />
-while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {<br />
-<indent>
- rv = apr_bucket_read(e, &data, &length, APR_BLOCK_READ);<br />
- if (rv) ...;<br />
- /* Remove bucket e from bb. */<br />
- APR_BUCKET_REMOVE(e);<br />
- /* Insert it into temporary brigade. */<br />
- APR_BRIGADE_INSERT_HEAD(tmpbb, e);<br />
- /* Pass brigade downstream. */<br />
- rv = ap_pass_brigade(f->next, tmpbb);<br />
- if (rv) ...;<br />
- apr_brigade_cleanup(tmpbb);<br />
-</indent>
+<highlight language="c">
+apr_bucket *e;
+const char *data;
+apr_size_t len;
+
+while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {
+ rv = apr_bucket_read(e, &data, &length, APR_BLOCK_READ);
+ if (rv) ...;
+ /* Remove bucket e from bb. */
+ APR_BUCKET_REMOVE(e);
+ /* Insert it into temporary brigade. */
+ APR_BRIGADE_INSERT_HEAD(tmpbb, e);
+ /* Pass brigade downstream. */
+ rv = ap_pass_brigade(f->next, tmpbb);
+ if (rv) ...;
+ apr_brigade_cleanup(tmpbb);
}
+</highlight>
</example>
</section>
href="#brigade">Brigade structure</a> section.</p>
<example><title>Example code to maintain filter state</title>
-struct dummy_state {<br />
-<indent>
- apr_bucket_brigade *tmpbb;<br />
- int filter_state;<br />
- ....<br />
-</indent>
-};<br />
-<br />
-apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)<br />
-{<br />
-<indent>
- struct dummy_state *state;<br />
-<br />
- state = f->ctx;<br />
- if (state == NULL) {<br />
- <indent>
+ <highlight language="c">
+struct dummy_state {
+ apr_bucket_brigade *tmpbb;
+ int filter_state;
+ ....
+};
+
+apr_status_t dummy_filter(ap_filter_t *f, apr_bucket_brigade *bb)
+{
+
+ struct dummy_state *state;
+
+ state = f->ctx;
+ if (state == NULL) {
+
/* First invocation for this response: initialise state structure.
- */<br />
- f->ctx = state = apr_palloc(sizeof *state, f->r->pool);<br />
-<br />
- state->tmpbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);<br />
- state->filter_state = ...;<br />
- </indent>
- }<br />
+ */
+ f->ctx = state = apr_palloc(sizeof *state, f->r->pool);
+
+ state->tmpbb = apr_brigade_create(f->r->pool, f->c->bucket_alloc);
+ state->filter_state = ...;
+
+ }
...
-</indent>
+</highlight>
</example>
</section>
<example>
<title>Example code using non-blocking bucket reads</title>
-apr_bucket *e;<br />
-apr_read_type_e mode = APR_NONBLOCK_READ;<br />
-<br />
-while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {<br />
-<indent>
- apr_status_t rv;<br />
-<br />
- rv = apr_bucket_read(e, &data, &length, mode);<br />
- if (rv == APR_EAGAIN && mode == APR_NONBLOCK_READ) {<br />
- <indent>
- /* Pass down a brigade containing a flush bucket: */<br />
- APR_BRIGADE_INSERT_TAIL(tmpbb, apr_bucket_flush_create(...));<br />
- rv = ap_pass_brigade(f->next, tmpbb);<br />
- apr_brigade_cleanup(tmpbb);<br />
- if (rv != APR_SUCCESS) return rv;<br />
-<br />
- /* Retry, using a blocking read. */<br />
- mode = APR_BLOCK_READ;<br />
- continue;<br />
- </indent>
- } else if (rv != APR_SUCCESS) {<br />
- <indent>
- /* handle errors */<br />
- </indent>
- }<br />
-<br />
- /* Next time, try a non-blocking read first. */<br />
- mode = APR_NONBLOCK_READ;<br />
- ...<br />
-</indent>
+ <highlight language="c">
+apr_bucket *e;
+apr_read_type_e mode = APR_NONBLOCK_READ;
+
+while ((e = APR_BRIGADE_FIRST(bb)) != APR_BRIGADE_SENTINEL(bb)) {
+ apr_status_t rv;
+
+ rv = apr_bucket_read(e, &data, &length, mode);
+ if (rv == APR_EAGAIN && mode == APR_NONBLOCK_READ) {
+
+ /* Pass down a brigade containing a flush bucket: */
+ APR_BRIGADE_INSERT_TAIL(tmpbb, apr_bucket_flush_create(...));
+ rv = ap_pass_brigade(f->next, tmpbb);
+ apr_brigade_cleanup(tmpbb);
+ if (rv != APR_SUCCESS) return rv;
+
+ /* Retry, using a blocking read. */
+ mode = APR_BLOCK_READ;
+ continue;
+ } else if (rv != APR_SUCCESS) {
+ /* handle errors */
+ }
+
+ /* Next time, try a non-blocking read first. */
+ mode = APR_NONBLOCK_READ;
+ ...
}
+</highlight>
</example>
</section>
<section id="security"><title>The Security Phase</title>
<p>Needs Documentation. Code is:</p>
- <example><pre>
+ <highlight language="c">
if ((access_status = ap_run_access_checker(r)) != 0) {
return decl_die(access_status, "check access", r);
}
if ((access_status = ap_run_auth_checker(r)) != 0) {
return decl_die(access_status, "check authorization", r);
}
- </pre>
- </example>
+ </highlight>
</section>
<section id="preparation"><title>The Preparation Phase</title>
that every function called from Apache be thread safe. When linking in 3rd
party extensions it can be difficult to determine whether the resulting
server will be thread safe. Casual testing generally won't tell you this
- either as thread safety problems can lead to subtle race conditons that
+ either as thread safety problems can lead to subtle race conditions that
may only show up in certain conditions under heavy load.</p>
</summary>