File: processing.html

package info (click to toggle)
libapache2-mod-rivet 3.2.2-1
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 6,296 kB
  • sloc: xml: 8,554; tcl: 7,568; ansic: 7,094; sh: 5,017; makefile: 195; sql: 91; lisp: 78
file content (226 lines) | stat: -rw-r--r-- 11,358 bytes parent folder | download | duplicates (2)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Apache Rivet HTTP Request Processing</title><link rel="stylesheet" type="text/css" href="rivet.css"><meta name="generator" content="DocBook XSL Stylesheets Vsnapshot"><link rel="home" href="index.html" title="Apache Rivet 3.2"><link rel="up" href="index.html" title="Apache Rivet 3.2"><link rel="prev" href="directives.html" title="Apache Rivet 3.2 Configuration"><link rel="next" href="request.html" title="Apache Child Processes Lifecycle and Request Processing"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Apache Rivet HTTP Request Processing</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="directives.html"><img src="images/prev.png" alt="Prev"></a> </td><th width="60%" align="center"> </th><td width="20%" align="right"> <a accesskey="n" href="request.html"><img src="images/next.png" alt="Next"></a></td></tr></table></div><div class="section"><div class="titlepage"><div><div><hr><h2 class="title" style="clear: both"><a name="processing"></a>Apache Rivet HTTP Request Processing</h2></div></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idm606"></a>Tcl Scripts Processing</h3></div></div></div><p style="width:90%">
			Until 2.x versions Rivet handled requests
			following the vision that inspired the original design
			which was summarized in the definition <span class="quote">“<span class="quote">Web programming
			like in PHP, but with Tcl</span>”</span>. HTTP requests triggered the
			execution of Tcl scripts or a Rivet (.rvt file) templates
			whose path is encoded in the URI (an alias translation or
			URL rewriting might occur to establish the real path). 
			The execution of such scripts can be preceded and/or 
			followed by the execution of scripts common to a whole web site
			or to a hierarchy of directories the BeforeScript and AfterScript
			directives. These scripts can be configured on a per virtual host, 
			per directory or per user basis. Execution of such combined
			scripts can break because of coding errors (thus triggering the
			ErrorScript execution) or it can deliberately interrupt 
			ordinary execution by calling ::rivet::abort_page (which triggers
			the execution of a script defined by the directive AbortScript). 
			This scheme is in case terminated by a further configurable script 
			(AfterEveryScript). This model of request handling was coded within
			the module mod_rivet.so itself. 
		</p><p style="width:90%">
 			With Rivet 3.0 we changed this approach and landed to
 			a new much simpler and flexible model where each request is 
 			by default handled by the following Tcl procedure
		</p><pre class="programlisting"># -- request_handler.tcl
#
# Copyright 2002-2017 The Apache Rivet Team
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#	http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# code of the default handler of HTTP requests

    ::try {
        ::Rivet::initialize_request
    } on error {err} {
        ::rivet::apache_log_error crit \
            "Rivet request initialization failed: $::errorInfo"
    }

    ::try {

        set script [::rivet::inspect BeforeScript]
        if {$script ne ""} {
            set ::Rivet::script $script
            eval $script
        }

        set script [::rivet::url_script]
        if {$script ne ""} {
            set ::Rivet::script $script
            namespace eval ::request $script
        }

        set script [::rivet::inspect AfterScript]
        if {$script ne ""} {
            set ::Rivet::script $script
            eval $script
        }

    } trap {RIVET ABORTPAGE} {err opts} {
        ::Rivet::finish_request $script $err $opts AbortScript
    } trap {RIVET THREAD_EXIT} {err opts} {
        ::Rivet::finish_request $script $err $opts AbortScript
    } on error {err opts} {
        ::Rivet::finish_request $script $err $opts
    } finally {
        ::Rivet::finish_request $script "" "" AfterEveryScript
    }
   
# default_request_handler.tcl ---
</pre><p style="width:90%">
			Note the call to new 3.x command ::rivet::url_script
			that returns the body of the Tcl script or Rivet template
			pointed by the URL. 
		</p><p style="width:90%">
			This procedure emulates the 2.x scheme
			and as such works as a fully compatible request handling
			but opens to the programmers the option of replacing it 
			with their own	application request handling procedure
		</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><table border="0" summary="Note"><tr><td rowspan="2" align="center" valign="top" width="25"><img alt="[Note]" src="images/note.png"></td><th align="left">Note</th></tr><tr><td align="left" valign="top">
			Note that if you redefine the core request handler
			you'll need to handle yourself any error conditions
			and any code interruption brought about by calling 
			<span style="font-family:monospace"><span class="command"><strong>::rivet::abort_page</strong></span></span>.
			The current procedure might work as a template to be
			reworked into your own request handler.
		</td></tr></table></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="idm616"></a>Example: basic OO Rivet Application</h3></div></div></div><p style="width:90%">
			An applications may have no interest in running
			a script pointed by the URL as in the traditional approach 
			followed by rivet inspired to the PHP philosophy of <span class="quote">“<span class="quote">scripting
			the HTML</span>”</span>. A web based application
			could be driven entirely by the URL encoded arguments and by the
			data POSTed with HTML forms, still retaining the ability of exploiting
			the template engine of Rivet through the <span style="font-family:monospace"><span class="command"><strong>::rivet::parse</strong></span></span>.
			In other words an application could hinge on a single entry point to
			handle requests, regardless the complexity of its internal design. 
		</p><p style="width:90%">This section shows a template for such an application 
			(let's call it MyRivetApp) based on an Itcl (or TclOO for what 
			it matters) object instance. In myrivetapp.tcl
			the application class is defined and an instance of it is
			created in the global namespace. 
		</p><pre class="programlisting">## myrivetapp.tcl -- 
#
# Application class definition and instance creation
#

package require Itcl

::itcl::class MyRivetApp {

   private variable application_name

   public method init {}
   public method request_processing {urlencoded_args}

}

::itcl::body MyRivetApp::init {app_name}{

   # any initialization steps must go here
   # ....

   set application_name $app_name

}

::itcl::body MyRivetApp::request_processing {urlencoded_args} {

   # the whole application code will run from this method
   ...

}

set ::theApplication [MyRivetApp #auto]

$::theApplication init [dict get [::rivet::inspect server] hostname]

# -- myrivetapp.tcl
</pre><p style="width:90%">
			which provides a very basic interface for both initialization
			and request processing. Such script will be sourced into the
			Tcl interpreter at the mod_rivet initialization stage. In the
			Apache configuration (most
			likely within a &lt;VirtualHost myrivetapp.com:80&gt;...&lt;/VirtualHost&gt;
			definition block)
		</p><pre class="programlisting">&lt;IfModule rivet_module&gt;
    RivetServerConf ChildInitScript "source myrivetapp.tcl"
&lt;/IfModule&gt;</pre><p style="width:90%">
			By running this script when an a thread is started
			we set it up to respond requests, but we still need to 
			tell mod_rivet what code will eventually handle requests
			and how the method MyRivetApp::request_processing will
			be called with appropriate arguments
		</p><pre class="programlisting"># -- myapp_request_handler.tcl
#
# This script will be read by mod_rivet during the process/thread 
# initialization stage and its content stored in a Tcl_Obj object. 
# This object is evaluated internally by mod_rivet
#

::try {

    ::theApplication request_processing [::rivet::var_qs all]

} trap {RIVET ABORTPAGE} {err opts} {

     set abort_code [::rivet::abort_code]

    switch $abort_code {
       code1 {
           # handling abort_page with code1
           ....
       }
       code2 {
           # handling abort_page with code2
          ....      
       }
       # ...
       default {
           # default abort handler
       }
   }

} trap {RIVET THREAD_EXIT} {err opts} {
    
    # myApplication sudden exit handler
    ...

} on error {err opts} {

    # myApplication error handler
    ...

} finally {

    # request processing final elaboration
    
}

# -- myapp_request_handler.tcl
</pre></div><p style="width:90%">
		Finally we have to tell mod_rivet to run this script when a
		request is delivered to myApplication and we do so
		using the 3.0 directive <span style="font-family:monospace"><span class="command"><strong>RequestHandler</strong></span></span> 
	</p><pre class="programlisting">&lt;IfModule rivet_module&gt;
    RivetServerConf ChildInitScript "source myrivetapp.tcl"
    RivetServerConf RequestHandler  "myapp_request_handler.tcl"
&lt;/IfModule&gt;</pre><p style="width:90%">
		Notice that the argument of the directive <span style="font-family:monospace"><span class="command"><strong>RequestHandler</strong></span></span>
		is a file name not a Tcl script as for <span style="font-family:monospace"><span class="command"><strong>ChildInitScript</strong></span></span>
	</p><p style="width:90%">
		With such approach only the <span style="font-family:monospace"><span class="command"><strong>ChildInitScript</strong></span></span>, <span style="font-family:monospace"><span class="command"><strong>ChildExitScript</strong></span></span>
		and <span style="font-family:monospace"><span class="command"><strong>GlobalInitScript</strong></span></span> configuration directives are effective, while 
		the effect of other handler is devolved to our request handler script.
	</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="directives.html"><img src="images/prev.png" alt="Prev"></a> </td><td width="20%" align="center"> </td><td width="40%" align="right"> <a accesskey="n" href="request.html"><img src="images/next.png" alt="Next"></a></td></tr><tr><td width="40%" align="left" valign="top">Apache Rivet 3.2 Configuration </td><td width="20%" align="center"><a accesskey="h" href="index.html"><img src="images/home.png" alt="Home"></a></td><td width="40%" align="right" valign="top"> Apache Child Processes Lifecycle and Request Processing</td></tr></table></div></body></html>