Rivet

Difference between version 143 and 144 - Previous - Next
[http://tcl.apache.org/rivet/Rivetlogo_small.png]

[Apache] '''[http://tcl.apache.org/rivet/%|%Rivet]''' is the next generation of [mod_dtcl] and [NeoWebScript], combined:
"like [PHP], but with [Tcl]."


** See Also **

   [THP]:   [CAU]: an alternative to Rivet;  A webserver-neutral way to embed Tcl code.

   [RivetCGI], by [rkeene%|%Roy Keene]:   A port of Rivet to [CGI].



** Attributes **

   website:   http://tcl.apache.org/rivet/
   current version:   [http://tcl.apache.org/rivet/html/download.html%|%3.2.01]


** Description **

Rivet "lets you program in not only mixed [HTML]/Tcl, but also pure Tcl, which
is good for separating content and presentation."

Current developers of Rivet are [Massimo Manghi], [Harald Oehlmann], [George Petasis], [Karl Lehenbauer] and sometimes [Damon Courtney]. [David Welton],[Brad Morrison],[Pat Thoyts] and [Andy Doerr] have all greatly contributed in the past.


** Rivet 3.0 Release Notes

Rivet 3.0 is tested and works with the Apache Webserver version 2.4 (running any MPM) and requires Tcl >= 8.6.1. Rivet 3.0 now supports also the Apache Web server when running with the MS-Windows family of operative systems. The module has been built on MS-Windows through the CMake build system using the 
[https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017%|%Visual Studio Community 2017] compiler. 

Version 3.0 is a drop-in replacement of any earlier version of Rivet but there are new features that can deeply change the way you have so far developed your Rivet based applications 


** Download **

You can get Rivet from the [http://tcl.apache.org/rivet/html/download.html%|%download page] of the project. Rivet is available as package for many Unix-like systems. Check your Unix/Linux package manager (Debian/Ubuntu derived Linux distribution call the package [https://tracker.debian.org/pkg/libapache2-mod-rivet%|%libapache2-mod-rivet]

Apache Rivet still is not distributing an official Windows binary package. Any Tcl developer wishing contribute by packaging Rivet for Windows is welcome to step forward and join us at [email protected] ([email protected] to subscribe to the Rivet mailing list)
Ubuntu and Debian have Rivet in their repositories. Rivet runs with the prefork mpm of Apache, this might require to change Apache configuration (for Apache 2.4) or the httpd binary itself (Apache 2.2) as the MPM gets built into the the server itself. See the documentation of your OS for direction on how to change the running MPM

[http://software.opensuse.org/package/apache2-mod_rivet?search_term=apache2-mod_rivet%|%OpenSUSE] offers Rivet for various versions of their Linux distribution and for CentOS. 


** Installation **

[Rivet - OpenBsd 4.9]: [PWQ] 2011-09-27: installation notes on OpenBSD.
[mxmTcl anghi] 2018-01-22: mod_r Rivet ruons Windows]: oStarting Apacwith version w3.0 Riveth bruns also with the Windon-thws poreaded
([htt of Aps://httpd.apache. Rivet org/n Windocws/2.4/mod/prefork.htm was buil%|%prefort using CMak])e and the threaded
([https://hwww.visualsttpudio.apache.orgm/docs/2.4/mod/worker.htmnl%|%worker] and [https://http#build.apache.-torg/docls/2.4/m-fod/er-vent.htmisual-studio-2017%|%event]) 
MVisual Studiprocessing MCodmmunity 2017] compilesr
[Tcl and Rivet on Windows]: Rivet 3.0 runs also with the Windows port of Apache. Rivet on Windows was built using CMake and the 
[https://www.visualstudio.com/downloads/#build-tools-for-visual-studio-2017%|%Visual Studio Community 2017] compiler



** Apache MPM and Rivet Bridge Modules **
Rivet 3.0 iwas a major rewriting of mod_rivet, the Apache HTTP Websever module at the core of Rivet. Unlike in previous versions of mod_rivet which only supported the prefork MPM (Multiprocessing Module ), starting with 3.0 we attained full support of different MPM for the Apache framework. Threaded MPM integration was achieved by making mod_rivet multithreaded and modular itself, introducing the mod_rivet/MPM bridge concept. We developed a set of loadable modules which are supposed not only to overcome the issues related to threading but also to offer the best possible MPM mod_rivet integration. As a side effect of this modular design, mod_rivet is not only able to integrate with its environment, but also to work as a framework for writing more MPM bridges designed along different multi-threading schemes and workload management models. See the internals section of the rivet [http://tcl.apache.org/rivet/manual3.0%|%manual] for further reading. MPM bridges are loaded accordingly to a heuristics of rules based on the Apache introspection calls, but they can be determined in the configuration. Only a bridge can be loaded at a time. 


** Community **

   [http://mail-archives.apache.org/mod_mbox/tcl-rivet-dev/%|%rivet-dev mailing list]: 


** Examples **

   [Rivet HTTP REST service example]:   


** News **
   20153-121-20521:   Rivet [https://tcl.apache.org/rivet/html/rn-elease%2-2dnotes.html%|%23.2.41] released
**   2017-11-11:   RivSet [http://tcl.apache.org/rivet/html/rn-2-3.html%|%2.3.5] reAleasedo **
   2018-02-09[THP]:   Rivet [httpCAU]://tcl. apn achlte.org/rnative t/ho Rivetml/;  A websernver-3-0.hneutml%|%3.0.1] reale wasy to embed Tcl code.
   [RivetCGI], by [rkeene%|%Roy Keene]:   A port of Rivet to [CGI].

** Discussion **

[FW]: Was this made by the same people as NWS and mod_dtcl, or is it a separate team of developers?

----

Can we have some testimonials by Rivet users?  (sorry, i'm new to servers in general)

   1. how do you connect to a db, tcl db extensions?
   2. is an apache instance with rivet and tomcat possible? encouraged?
   3. mod_rewrite in the midst of all this, or is that only available on top of a tomcat instance?
   4. are importing libraries like [tcllib] a piece of cake after rivets installed?

i want to run a dual [java]/tcl environment...

----

[davidw]: I think these questions are more appropriate for the newsgroup or the rivet mailing list, but I'll give it a shot:

1) You use regular Tcl database extensions.  Rivet is pretty much standard Tcl, making a lot of the code you write for it reusable on or off the web.

2) I've never mixed Apache and Tomcat.  I don't really care for Java for these sorts of things unless you have a *big* infrastructure, and that's not something I've dealt with a lot.

3) mod_rewrite is an Apache thing and it works just fine with Rivet.  In fact, it's encouraged if you want to do things like have one rivet script respond to a whole virtual directory tree.  So /foo/bar/ /foo/baz/ /foo/bee/bop and so forth are all mapped to foo.tcl?bar foo.tcl?baz foo?bee+bop and so forth.

4) tcllib and other libs are a piece of cake:-)

----

[RLH]: Are there any Rivet tutorials mucking about?

[Massimo Manghi]: Rivet manuals have examples for both configuration and programming. Rivet extends Tcl with a small set of new commands dedicated to web programming and therefore having a good Tcl manual can be useful, depending on the familiarity of the developer with the language.

----

[davidw]: Not yet, but Rivet is very similar to plain old Tcl, and the differences are covered in the documentation.

As far as programming style, if you are doing something simple... just go ahead and mix your HTML and Tcl code.  If it's a more complex app, separate things out into .tcl files that act as the logic and use .rvt files simply as templates.

Or write the mailing list for more specific questions...

[RLH]: I am looking for something similiar to HTML::Template [http://html-template.sourceforge.net/article.html] from the Perl side of the house. I like the clean separation of code and HTML.  : )

----

That perl template stuff just adds funny tags, which are not standard HTML.  If you want to separate code and templates, do your processing in a .tcl file, then do "parse foo.rvt", and in the .rvt file, put statements like <? puts $foo ?> <? puts $bar?> where you need variable values.  Or if you really wanted to do something fancy, you could call the parse.rvt in its own namespace/interpreter/whatever from the .tcl file, and create procs that are aliases to your variables, so all you have to do is <?foo?> <?bar?> in order to get output.  I suppose a standardized way of doing this would be nice, but it is pretty easy... experiment and tell us (on the list, please) what you end up liking!

[RLH]: You are correct about the funny tags, I meant more of a "standard way of doing this..." as you said. I will go with your suggestions. I am far from good enough to create the "standard way" though.  : )

----

[RLH] 2006-02-07: Are there any hosting companies that support Rivet?

[Roy Keene] 2008-10-06: Any Rivet application can be turned into an HTTP/CGI application.  And with Starpacks the entire thing can be completely self-contained in one file.

----

[APW] 2007-01-20: if you have problems installing [Tcl and Rivet on Windows] follow the link.

----

[Roy Keene] 2008-10-05: Rivet can also be implemented transparently using CGI.  This has the advantage of using "suEXEC" and working well with all versions of Apache. More information can be found on the Rivet/CGI page ([http://www.rkeene.org/projects/info/wiki/51])

[Roy Keene] 2009-03-20: Rivet/CGI ([http://www.rkeene.org/projects/info/wiki/51]) now supports converting a Rivet application into a Starkit (which can be turned into a Starpack)

----

2012-07-07: [Massimo Manghi] gave a speech on [http://www.eurotcl.eu/program.html%|%EuroTCL%|%].
The [http://www.eurotcl.eu/eurotcl-2012/presentations/11-Manghi-Rivet.odp%|%slides%|%] gave a good overview of current Rivet capabilities.

----

<<discussion>> Apache start error: can not locate tcllib8.5.so (Unix)
[HaO] 2012-05-04: Rivet loads the tcl library using the dynamic linker.

Thus, it must be:

   * in the default location ''/usr/lib(64)''
   * or in a folder listed in the environment variable ''LD_LIBRARY_PATH'' of apache.


I felt it easier to add a symlink to ''/usr/lib(64)'' instead setting a custom library path.Commands necessary, if tcl is installed in ''/usr/local/lib'':
======none
# cd /usr/lib(64)
# ln -s /usr/local/lib(64)/libtcl8.5.so
======
<<discussion>>

<<discussion>> Apache start error: undefined symbol: xxx
[HaO] 2012-05-04: I got the following error starting apache:

''Can't locate API module structure `mod_rivet' in file /etc/httpd/modules/mod_rivet.so: /etc/httpd/modules/mod_rivet.so: undefined symbol: mod_rivet''

This was due to the following line in the apache config file:

======none
LoadModule mod_rivet /etc/httpd/modules/mod_rivet.so
======

The second word ''mod_rivet'' was incorrect and its value is shown in the error message.
The correct value is: ''rivet_module''

======none
LoadModule rivet_module /etc/httpd/modules/mod_rivet.so
======

<<discussion>>

<<discussion>> error return page


*** George Petasis asked about the default error return page: ***

I am writing a rest service in Rivet. When an error occurs, how can I 
return an error page?
I have tried "headers numeric 500". Firefox sees that the server 
responded with an internal server error, but I see a blank page.
How can I use the apache default error page?

*** Massimo Manghi answered: ***

A Tcl error can be handled setting up an ErrorScript. If the error is raised by an abnormal condition you are catching somehow in your code you may call 'abort_page <abort_code>' which will trigger the code set up in AbortScript. Within this script you can check which condition brought about the error using the 'abort_code' command that is supposed to return the <abort_code> you passed when you fired the exception.

You may also issue a redirect forcing the browser to issue a request for a different URL which might create the error page.

See also the 'headers' and 'no_body' commands

Surely you can design your own error page if you want. It should imply some extra work but greater flexibility

Did you check this page about error customization in Apache?

http://httpd.apache.org/docs/2.0/custom-error.html

*** George Petasis asked how to use the standard Apache error page ***

I am not sure I understand. I want to avoid creating my error page, and return the apache standard one to the caller.
Is this possible? 

*** Massimo answered that this is propably not possible ***

I don't think I know the answer then. Reproducing your attempt on my machine lets Apache return a 200, therefore a normal completion, even though 'headers numeric 500' is issued (is it the right HTTP header name anyway? Doing it in this way is expected to trigger a 500 error on the server?)

Apache will certainly return its standard error messages when an internal abnormal condition occur that cannot be handled by Rivet.
More questions come up to my mind related to the error handling and Rivet interaction with other Apache components.

*** Harald Oehlmann wrote, why you need your own error page ***

You are interested in doing your own return page.
Why ? It depends on the requested format.
I follow the book "RESTful Web Services Cookbook" by Subbu Allamaraju.
Half the book is about "error return"...

My example:


A data base is queried and there are the following formats available:

   * web (pretty web page)
   * http table
   * xml table
   * csv table

First, I find out the required destination format:
   * A form variable
   * if not given: headers(Accept)
     -> there is a new method in 2.0.5 to easily parse this

Then I look into the data base.
If the required data is not found or there is another error, I output
error pages depending on the required format and the set http status.
See also, that I flag "not found data" as cacheable, but server errors
as not ;-)

======
if {[catch {
    set resultData [wwwbaseProductDataGet\
        [env REMOTE_ADDR]\
        [var get log]\
        $response(key)\
        {}\
        $response(country)\
        $response(language)\
        $response(date)\
        $response(format)]
} Err dErr]} {
    switch -exact -- [dict get $dErr -errorcode] {
        PARAM {
            # > Return 400 Bad request
            wwwbaseCacheSet 1
            headers numeric 400
        }
        NOT_FOUND {
            # > Return 404 Not found
            wwwbaseCacheSet 1
            headers numeric 404
        }
        default {
            # > Return 500 Internal server error
            wwwbaseCacheSet 0
            headers numeric 500
        }
    }
    switch -exact -- $response(format) {
        csv {
            puts Error\n$Err
        }
        json {
            puts "\{error: \"$Err\"\}"
        }
        xml {
            puts "<error>$Err</error>"
        }
        html {
            puts "<html><head><title>\
                    [mce PageTitleProductRequest]</title>\
                    <body><h1>[mce ErrSearch $Err]</h1></body>"
        }
        form {
            switch -exact -- [dict get $dErr -errorcode] {
                PARAM {
                    puts [mce ErrParam $Err]
                }
                NOT_FOUND {
                    puts [mce ErrSearch $Err]
                }
                default {
                    puts [mce ErrServer $Err]
                }
            }
            # puts $Err<br/>[string map {\n <br/>} $::errorInfo]
        }
    }
} else {
    # > Correct response is cacheable
    wwwbaseCacheSet 1
    switch -exact -- $response(format) {
        csv {
            headers set Content-Disposition\
                    "attachment; filename=product.csv"
        }
        form {
            puts {} 
        }
    }
    puts -nonewline $resultData
    
}
======

In addition, I have added header information, if the result is cacheable
or not:

======
proc ::wwwbase::wwwbaseCacheSet {{fCacheable 1}} {
    if {$fCacheable} {
        headers set Cache-Control max-age=86400,must-revalidate
    } else {
        headers set Cache-Control no-cache,no-store
    }
}
======
<<discussion>>

<<discussion>> Rivet 2.1.x on Redhat and CentOS
[HaO] 2013-02-26: I am sorry, Rivet 2.1.x requires TCL 8.5.10, due to a fixed Loadlib parameter.
As all CentOS and Redhat distributions use maximum tcl 8.5.7, Rivet builds only with a self-compiled tcl.

Thus, RPMs are only available for Rivet 2.0 (exception: Fedora, OpenSuSE): [http://software.opensuse.org/package/apache2-mod_rivet?search_term=rivet]

----

*** Compile Log for CentOS 6.2 64 bit ***

Here is my install log to build Tcl8.6.0 and Rivet 2.1.1 on CentOS 64 bit:
It is build by user "admin" in the folder "test".
Please use your own user name and temporary build folder.
The final location is '/usr/local/*'.

[MarcoP]: The procedure works also for CentOS 6.4 64 bit.

**** Create files ****

There are 2 files to create.
One may use 'vi' for that as follows:
   * vi <filename>
   * press key `a` to append text
   * type your text or copy it from the clipboard or this web-page
   * press the keys `esc`, `:` and `x` to save and exit

**** Prepare build environment ****

Invoke the following commands on a shell as user root:

======none
yum groupinstall Entwicklungs-Tools
======none

This is on a german locale, [MarcoP] english is:

======none
yum groupinstall "Development tools"
======

and httpd-devel to get program 'apxs' for rivet compilation:

======none
yum install httpd-devel
======

Create a file /usr/local/share/config.site with contents:

======none
test "$libdir" = '${exec_prefix}/lib' && libdir='${exec_prefix}/lib64'
true
======

**** Compile and install Tcl ****

Tcl source distribution is in '/home/admin/test'.
Invoke the following commands as user 'admin':

======none
cd test
gzip -d tcl8.6.0.tar.gz
tar xvf tcl8.6.0.tar.gz
cd tcl8.6.0/unix
./configure
make
======

Now change to root user, install and set link in '/usr/lib64':
======none
su
make install
cd /usr/lib64
ln -s /usr/local/lib64/libtcl8.6.so
======


**** Compile and install Rivet 2.1.1 ****

Rivet source distribution is in '/home/admin/rivet-2.1.1.tar.gz'.
Invoke as user 'admin':

======none
cd test
gzip -d rivet-2.1.1.tar.gz
tar xvf rivet-2.1.1.tar
cd rivet-2.1.1
./configure --with-tcl=/usr/local/lib64 --with-apxs=/usr/sbin/apxs --with-tclsh=/usr/local/bin/tclsh8.6 --with-apache-version=2 --with-rivet-target-dir=/usr/local/lib64/rivet --enable-version-display --enable-64bit
make
======

and as user root:
======none
su
make install
======

Create file "/etc/httpd/conf.d/mod_rivet.conf" with contents:

======none
# load the module
LoadModule rivet_module modules/mod_rivet.so

# Let the module handle .rvt and .tcl files.
AddType application/x-httpd-rivet  rvt
AddType application/x-rivet-tcl    tcl

# The default charset can be specified in the configuration
AddType "application/x-httpd-rivet; charset=utf-8" rvt

# Add index.rvt to the list of files that will be served
DirectoryIndex index.rvt
======

Restart apache:
======
service httpd restart
======

<<discussion>>

----

[BH] 2013-07-02 14:27:41:

Rivet 2.1.2 working on OpenSuse 12.1 with native TCL8.5/apache2 package.

   *  yast install apache2, apache2-devel, tcl8.5 and tcl8.5-devel

   *  cd rivet2.1.2
   *  compile River

======none
$ aclocal
$ autoreconf
$ ./configure --with-tcl=/usr/lib --with-apache-version=2 \
     --with-tclsh=/usr/bin/tclsh --with-apache=/usr \
     --with-rivet-target-dir=/usr/lib/myrivetlib \
     --with-apxs=/usr/sbin/apxs2
$ make
$ su
% ake install
======

   *  Creating a mod_rivet.conf for apache:
   `vi /etc/apache2/mod_rivet.conf` and added in it:

======none
AddType application/x-httpd-rivet  rvt
AddType application/x-rivet-tcl    tcl
AddType "application/x-httpd-rivet; charset=utf-8" rvt
======

   *  Start Yast Sysconfig module:
   Navigate to Network Service->HTTP->modules
   Add "rivet" to APACHE_MODULES

   *  Add "/etc/apache2/mod_rivet.conf" to APACHE_CONF_INCLUDE_FILES in httpd.conf
   *  Installing the river packages.

======none
% cd rivet2.1.2
% make install-packages
======
   
   *  Test:
======none
$ vi /srv/www/htdocs/test.rvt
======

======none
<?
 package require Rivet
 package require Session
 package require DIO
 package require form

 puts "<b>I got right here!</b>"
?>
======

======none
% service apache2 start
======

   point the browser to url = localhost/test.rvt

   and got the magic "I got right here!".

   *  Thanks to Harald and Massimo in helping me to get it working.

----

[RJM]: I want to add the mc package to apache rivet. Of course, this question applies more in general: how can I add Tcl extensions to rivet?

----

'''[hav] 2015-06-26 04:06:23:'''

Hey Y'all - is there a NWS layer in place for rivet? ie - can existing nws be used if we switch to rivet instead of nws?

----

'''[hav] 2015-06-26 04:09:07:'''

I guess what I was really asking is "is rivet backward compatible with nws?"

----

'''[ray2501] 2018-01-22 17:25:00:'''

Rivet 2.3 is tested and works with the Apache Webserver version 2.4 (running the prefork MPM).

Rivet 3.0 provides support for both non threaded Apache MPMs (Multi Process Module), such as mod_mpm_prefork,
and threaded MPMs such as mod_mpm_worker, mod_mpm_event and mod_mpm_winnt.

It is a good thing because Apache mod_http2 does not work at mod_mpm_prefork.

<<categories>> Internet | Web