summaryrefslogtreecommitdiff
path: root/docs/manual/developer/layeredio.html
blob: a4d1f5cda429f923c981158d209ba90f2be13da6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta name="generator" content="HTML Tidy, see www.w3.org" />

    <title>Apache 2.0 Layered I/O</title>
  </head>
  <!-- Background white, links blue (unvisited), navy (visited), red (active) -->

  <body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
  vlink="#000080" alink="#FF0000">
    <h1 align="center">Apache Layered I/O</h1>

    <p>Layered I/O has been the holy grail of Apache module writers
    for years. With Apache 2.0, module writers can finally take
    advantage of layered I/O in their modules.</p>

    <p>In all previous versions of Apache, only one handler was
    allowed to modify the data stream that was sent to the client.
    With Apache 2.0, one module can modify the data and then
    specify that other modules can modify the data if they would
    like.</p>

    <h2>Taking advantage of layered I/O</h2>

    <p>In order to make a module use layered I/O, there are some
    modifications needed. A new return value has been added for
    modules, RERUN_HANDLERS. When a handler returns this value, the
    core searches through the list of handlers looking for another
    module that wants to try the request.</p>

    <p>When a module returns RERUN_HANDLERS, it must modify two
    fields of the request_rec, the handler and content_type fields.
    Most modules will set the handler field to NULL, and allow the
    core to choose the which module gets run next. If these two
    fields are not modified, then the server will loop forever
    calling the same module's handler.</p>

    <p>Most modules should not write out to the network if they
    want to take advantage of layered I/O. Two BUFF structures have
    been added to the request_rec, one for input and one for
    output. The module should read and write to these BUFFs. The
    module will also have to setup the input field for the next
    module in the list. A new function has been added,
    ap_setup_input, which all modules should call before they do
    any reading to get data to modify. This function checks to
    determine if the previous module set the input field, if so,
    that input is used, if not the file is opened and that data
    source is used. The output field is used basically the same
    way. The module must set this field before they call ap_r* in
    order to take advantage of layered I/O. If this field is not
    set, ap_r* will write directly to the client. Usually at the
    end of a handler, the input (for the next module) will be the
    read side of a pipe, and the output will be the write side of
    the same pipe.</p>

    <h3>An Example of Layered I/O.</h3>

    <p>This example is the most basic layered I/O example possible.
    It is basically CGIs generated by mod_cgi and sent to the
    network via http_core.</p>

    <p>mod_cgi executes the cgi script, and then sets
    request_rec-&gt;input to the output pipe of the CGI. It then
    NULLs out request_rec-&gt;handler, and sets
    request_rec-&gt;content_type to whatever the CGI writes out (in
    this case, text/html). Finally, mod_cgi returns
    RERUN_HANDLERS.</p>

    <p>ap_invoke_handlers() then loops back to the top of the
    handler list and searches for a handler that can deal with this
    content_type. In this case the correct module is the
    default_handler from http_core.</p>

    <p>When default handler starts, it calls ap_setup_input, which
    has found a valid request_rec-&gt;input, so that is used for
    all inputs. The output field in the request_rec is NULL, so
    when default_handler calls an output primitive it gets sent out
    over the network.</p>
    <i>Ryan Bloom, 25th March 2000</i>
  </body>
</html>