Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Table of contents
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Concept....................................................................................................................................... 3 Installing Tntnet.......................................................................................................................... 3 Create a simple application with Tntnet......................................................................................3 C++-content (processing, expressions, conditional expressions)............................................... 4 Query-arguments (scalar/vector, untyped/typed, default-value).................................................4 Components................................................................................................................................ 5 Component-parameters............................................................................................................... 5 Returning from components........................................................................................................6 Calling components (dynamic/static)..........................................................................................6 Calling components from c++.....................................................................................................7 Include ecpp-files........................................................................................................................ 7 Declaring subcomponents........................................................................................................... 8 Passing parameters to components..............................................................................................8 Defining scoped variables........................................................................................................... 9 14.1 Lifetime.................................................................................................................................. 9 14.2 Scope.................................................................................................................................... 10 15 Cookies......................................................................................................................................11 16 Component attributes................................................................................................................ 12 17 Configuration............................................................................................................................ 12 18 Accessing configuration variables............................................................................................ 13 19 Logging..................................................................................................................................... 14 20 Exception handling................................................................................................................... 14 21 Savepoints................................................................................................................................. 14 22 Binary content........................................................................................................................... 15 23 Upload....................................................................................................................................... 15 24 HTTP-Auth............................................................................................................................... 16 25 Using c++-classes..................................................................................................................... 16 26 Creating stand alone web applications...................................................................................... 17 27 Some notes about multi threading.............................................................................................18
1 Concept
Tntnet is a application server for web applications written in c++. A web application in tntnet is written with a template-language, which embeds c++processing-instructions in html-pages. You can use external classes or libraries in these pages. That wa programmers can concentrate on the htmlresult, when creating content and put processing in c++-classes. Applications written with the template-language called ecpp are compiled into c++-classes and lin!ed into a d namicall loaded shared librar . This is done at compile-time " not at runtime, li!e other template-s stems often do. #n runtime there is no compiler needed.
2 Installing Tntnet
Tntnet runs on $inux%&nix. You need a c++-compiler to compile Tntnet and also to compile our web applications. As a prere'uisite cxxtools (which is available through the Tntnet-homepage http)%%www.tntnet.org* is needed. +xxtools is a collection of useful c++-classes. To install tntnet ou have to) 1. install cxxtools 2. unpac! the sources with ,tar x-f tntnet-version.tar.g-. /. cd to the source-director ,cd tntnet-version.tar.g-. 0. run ,.%configure. 1. run ,ma!e. 2. run ,ma!e install. This installs) The application server and tools for 1. tntnet " the web application server 2. ecppc " the ecpp-compiler /. ecppl " the ecpp-language-extractor for internationali-ation 0. ecppll " the ecpp-language-lin!er for internationali-ation 1. some shared libraries 2. tntnet-config " a script, which gives ou information about the installed Tntnet and helps ou setting up a simple pro3ect.
0. tntnet.properties " a basic configuration file for logging-configuration 7t used to be necessar to use a valid +++-class name as a pro3ect name, since it was used as a class name internall . This is not true for tntnet 2.8 an more. To build the pro3ect, change to the director and run ,ma!e.. This runs the necessar steps to create a running application. You get a shared librar pro3ectname.so, which contains the web application. To run it enter ,tntnet tntnet.conf. and navigate our browser to http)%%localhost)9888%pro3ectname. You get a simple :eb-page.
interpret the content of the form. To support this, ecpp has a tag) <%args>...</%args>. =etween this pair ou define the arguments of the form. >ach argument is terminated with ;?;. >cpp generates c++-variables of t pe std))string, containing the content of the form. You can precede arguments with a c++-t pe to convert the parameter automaticall into this t pe. This is done using the input-operator of std))istream. @ince tntnet 2.8 a parameter defined with the t pe bool is interpretation as true for all non empt strings. This ma!es it eas to chec!, if a specific submit button was pressed. >cpp supports multiple input-tags with the same name, e.g. multiple chec!boxes or select-tag with attribute multiple. = appending AB to our argument a std))vector and a t pedef will be generated. :riting name[] will be compiled to a t pedef name_type and a vector name. @ingle arguments can have a default value using the s ntax aria!le " de#ault_ alue$. >xamples)
<%args> name; street; city = New York; int age; // content of text-input is converte to int !oo" !utton#; // true$ if t%e su!mit !utton wit% name !utton# was use for // su!mission int sport&'; // mu"tip"e c%eck!oxes wit% t%e same name </%args> <( use t%e vector "ike t%is) (> % for *sport+type))const+iterator it = sport,!egin*-; it .= sport,en *-; //it- 0 <1 2it 1> % 3
& Components
>cpp-pages are called components. The are identified b their name. The name is composed of the local-name and the librar -name divided with ;C;. The local name is b default the filename of the ecpp file without path and extension, but ma be changed to whatever needed b passing a name using -n to the ecpp compiler ecppc. The -n switch can be used to pass full path names as component names. +omponents, which are called b Tntnet are called top-level-components. +omponents can contain internal subcomponents. The subcomponent-name is appended to the class-name divided b a dot. @ubcomponents can;t be called directl from tntnet but onl explicitl using a component call. >xamples are)
mycomp4app
identifies a component with the name ,m comp. in the shared librar ,app.so.
mycomp,su!comp4app
' Component-parameters
>ver component has / parameters called ,re'uest., ,repl . and ,'param.. The ,re'uest.-parameter contains information about the re'uest, received from the browser. This includes information about http-headers, the peer-ip, coo!ies or multipart-components. The parameter is an instance of the class ,tnt))httpDe'uest.. The ,repl .-parameter is used to build the answer to the re'uest. The repl ob3ect is an instance of the class ,tnt))httpDepl .. 7t contains methods to manipulate the http-headers and an output-stream for writing to the httpbod . ,'param. specifies the 'uer -parameters of the component. Eor top-levelcomponents it contains the 'uer -parameters of the form. As described above, the parameters are normall accessed using the F<argsG-bloc!.
sends a http-redirect message to the client Mote that that the redirect method never returns but throws a tnt))Http>rror. 7t is still defined as returning an unsigned, so that the return statement, although s ntacticall correct, ma be left out. 7t is 3ust for s ntactic sugar. Http-authori-ation is also implemented li!e redirects. This is explained in more detail later in this document.
call the component ,somecomp. here. 7f there is a internal subcomponent, this is called, otherwise the component is loo!ed up in the librar of the calling component. @ubcomponents, which are defined in other components, are called b appending the subcomponent-name to the component-name separated b a dot. >xample)
<6 ot%ercomp,su!comp >
call the subcomponent ,subcomp. in the component ,othercomponent.. To call a component in another librar the librar -part is appended to the name. >xample)
<6 somecomp4some"i! 6>
inserts the component ,somecomp. from ,somelib.so. here +omponent-names can be computed at runtime. To call a computed component-name, the expression is put inside brac!ets. >xample) Tntnet users guide N
component-id (of t pe tnt::compident or tnt::subcompident or a std::string* re'uest repl 'uer -parameter-ob3ect (of t pe tnt::query_params*
7t returns a http-result-code. @ee the AI7-documentation for details. @ometimes it is useful not to send the output directl to the client. :ith the method scallComp() it is also possible to retrieve the output and e.g. modif it before sending. 7t ta!es the same parameters as callComp, but no reply. 7nstead a temporar repl -ob3ect is created when the component is called. The httpreturn-code of the called component is ignored. >xample)
st ))string resu"t = sca""7omp*re8uest$ 8param-;
11 Include ecpp-%iles
>cpp-files can be included using the tag F<includeGfilenameF%<includeG. The content is included at compile-time. 7t is similar to the Oinclude-directive in +++. 7ncluding >cpp-files can be useful for)
global declarations initiali-ation, which is needed in multiple components it is strongl recommended for global-scope (explained below* variables.
7t should not be used for including content. +omponent-calling is better for that, because the content is not duplicated.
12 ,eclaring su-components
@ubcomponents are declared using <%def compname>...</%def>. The s ntax of subcomponents is the same as in top-level-components. The onl exception is, that it is not possible to define other subcomponents there. >xample)
9e""o <6 w%o > <% ef w%o> :or" </% ef>
Irints)
9i ;inus <orva" s
>xpressions are enclosed in brac!ets. The parameter t pe can also be numeric or an other t pe, which is seriali-able and deseriali-able using std))ostream and std))istream. >xample)
<0 st ))string name=a"ue = ;inus; st ))string "astname=a"ue = <orva" s; unsigne repeatNum = >; 3> <6 greeting name=*name=a"ue- "astname=*"astname=a"uerepeat=*repeatNum-> <% ef greeting> <%args> "astname; name; unsigne repeatNum = #; </%args> % for *unsigne n = ?; n < repeatNum; //n- 0 9i <1 name 1> <1 "astname 1> % 3 </% ef>
Irints)
9i ;inus <orva" s 9i ;inus <orva" s 9i ;inus <orva" s
A component can pass all its parameters to a subcomponent using its own 'param-ob3ect. 7n the example below the parameters of the subcomponent greeting are forwarded to printname. Tntnet users guide Q
>xample)
<6 greeting name=;inus "astname=<orva" s> <% ef greeting> <%#>greeting</%#> <6printname 8param> </% ef> <% ef printname> <%args> "astname; name; </%args> 9i <1 name 1> <1 "astname 1> <% ef>
Irints)
<%#>greeting</%#> 9i ;inus <orva" s
14.1
Lifetime
Rariables are defined in a lifetime-area. The lifetime can be session, re'uest, application or thread. @ession-variables are valid for the current user session. @essions are identified b coo!ies. >xample
<%session> st ))string current@ser; </%session>
De'uest-variables are valid while the current re'uest is processed. This is the shortest possible lifetime. >xample
<%re8uest> unsigne nextA *?-; </%re8uest>
Application-variables are valid as long as tntnet runs. The are shared between users. >xample Tntnet users guide 18
To use the application-lifetime correctl it is necessar to !now, that our application is one shared librar . Application-variables are onl accessible within the same shared librar . Thread-variables are valid, as long as the thread is running. These variables are not shared between threads, but each thread has its own cop . >xample
<%t%rea > tnt !))7onnection my7onnection*s8"ite)customer, !-; </%t%rea >
14.2
Scope
@tate-variables are b default valid onl in the component, where the are specified. The same name can be used in different components without conflicts. @ometimes it us useful to widen this scope. You could e.g. define a sessionvariable ,current&ser., which is accessible throughout our application. The scopes are specified b adding the scope-attribute to the tag. Ralid scopes are) component (the default*, page (inside the current component and its internal subcomponents* and global. The application is a shared librar with our components. >xamples)
<%session scope=g"o!a"> st ))string current@ser; </%session> <%re8uest scope=page> int num!er*#-; </%re8uest> <% ef> <%re8uest scope=page> int num!er; // t%is references t%e varia!"e num!er // outsi e t%is su!component </%re8uest> </% ef>
efine
A special case is parameter scope. This is a techni'ue, where we can pass almost an class we need as a parameter to subcomponents. The scoping techni'ue is used here. 7n components we can define parameter scope variables) >xample
<%param> tnt !))7onnection my7onnection*s8"ite)customer, !-; </%param>
11
As with other variables, we can pass constructor parameters for default construction, when the parameter is not set. :e can not define a scope, since parameters are alwa s local to the current component. :hen we call these components, we pass the variable as name value pairs divided b ;5; in brac!ets 3ust after the component name) >xample
<%cpp> tnt !))7onnection conn* !ur"-; </%cpp> <6 mysu!comp*my7onnection = conn- 6>
Here we define a connection ob3ect and pass it as a named parameter. Mote that the ob3ect is passed b value, which means, that the ob3ect is copied once. 7f ou want to pass the ob3ect b reference without cop ing, ou ma pass a pointer to it. The F<paramG-bloc! needs to specif the pointer t pe also. T pes are not chec!ed at compile time. 7f ou pass a wrong t pe, the behavior is undefined. You should reall be careful, what to pass.
Coo/ies
+oo!ies are supported b tntnet with a simple api. A coo!ie consists of a name, a value and optionall attributes. To set a coo!ie a ecpp-application call ,repl .set+oo!ie.. The simplest form is to call it with 2 parameters) a name and a coo!ie. You can pass 3ust a std))string or a character-string as name and value of the coo!ie. :hen the browser does its next re'uest, ou can read the coo!ie with ,repl .get+oo!ie(*.. This returns a coo!ie-ob3ect, which is directl convertible to a std))string. >xample) To set a coo!ie)
<0 rep"y,set7ookie*mycookie$ myva"ue-; 3>
12
1' Con%iguration
Tntnet needs a configuration file to run. = default this is read from ,%etc%tntnet%tntnet.conf., but ou can pass a different file as a parameter to tntnet, as was done at the first example. The file is a text file and contains configuration variables. >ver line starts with a variable name followed b 8 or more parameters separated b whitespace. 7f a parameter contains itself whitespace, enclose the parameter in single or double 'uotation mar!s. 7f ou need the 'uotation mar! in the value, ou must precede it with ;S; to escape its special meaning. $ines starting with ;O; and empt lines are ignored. There are variables, which are read b tntnet. &n!nown variables are ignored. +omponents might use them, so the need not be un!nown if the are un!nown to tntnet. The most important variable is ,6ap&rl.. 7t tells tntnet, what to do with re'uests. :ithout this variable tntnet answers ever re'uest with 080 " HTTIJM#TJE#&ML. ,6ap&rl. ta!es at least 2 parameters) a regular expression, which is matched against the url, sent from the client and a component name, which to call, if the expression matches. The component name might contain bac! references to the regular expression. To define bac! references, enclose the interesting part in brac!ets and reference them in the mapping using the dollar sign with a digit. The digit specifies, which brac!eted part is replaced. The brac!ets are numbered from 1. Tntnet users guide 1/
>xamples)
( maps every %tm"-fi"e to t%e component wit% t%e same !asename e,g, ( /in ex,%tm" in ex4myapp Dap@r" /*,2-,%tm" 1#4myapp ( maps re8uests$ w%ic% en wit% ,Epg to components wit% +Epg-suffix e,g, ( /myimg,Epg => myimg+Epg4myapp Dap@r" /*,2-,Epg 1#+Epg4myapp ( makes every component avai"a!"e t%roug% %ttp !y mapping t%e part !efore ( first F/F to t%e app"icationname *s%are -"i!rary-name- an t%e part after ( t%e app Dap@r" /*,2-/*,2- 1G41#
into tntnet.conf. 7f ou don;t specif a default value, the variable is set to an empt string, when not set in tntnet.conf.
1* 1ogging
$ogging is done through the cxxtools-meta-logging-librar . This uses log0cplus, log0cxx or a simple builtin-logging depending on configuration of cxxtools. You don;t have to bother too much about the used librar , when developing tntnet-applications. The AI7 sta s the same. 7f ou use 3ust the cxxtools-provided macros, ou can switch later to another librar without changing the source of our application. >ver logging-librar cxxtools supports, support logging categories and severities. Tntnet defines for each component a categor Tntnet users guide 10
,component.componentname.. :hen ou need to log something, 3ust use one of the macros logJfatal, logJerror, logJwarn, logJinfo or logJdebug. The parameter is passed to a output stream and ou can put multiple outputitems separated b ;FF;. :hat is logged where is specified in ,tntnet.properties. (but this can be changed in tntnet.conf*. 4ust loo! into the example tntnet.properties for some details about configuration and loo! at the documentation of the underl ing logging-librar .
2+ 2xception handling
>xceptions derived from std))exception thrown b components are catched b tntnet. The usuall generate a 188 " HTTIJ7MT>DMA$J@>DR>DJ>DD#D, but there is a exception class tnt))http>rror, which ta!es a error code and a message. The code is used as a http-error-code. You should use the tnt))HTTIJT-constants for it.
21 3a$epoints
@ometimes ou might want to catch exceptions generated b lower level classes or subcomponents and generate a nicel formatted error-message. 7n this case ou might want to close all open html-tags before starting our error-message. This is often a almost impossible tas!, because ou don;t !now, where the exception occurred. $uc!il ou get help from tntnet%ecpp to solve this open-html-tag problem) savepoints. A savepoint is a simple class, which acts li!e a transaction for html-output. You instantiate a savepoint as a local variable at the start of our tr -bloc! and pass the re'uest-ob3ect to it. =efore catch call savepoint))commit(*. 7f the commit is not reached, because a exception happened, the savepoint-ob3ect rolls bac! the output to the point, where it was instantiated. >xample)
<0 try 0 tnt))Havepoint mysavepoint*rep"y-; 3> <form> <input type=text name=va"ue va"ue=<1 o!Eect,get=a"ue*- 1>> </form> <0 mysavepoint,commit*-; 3 catc% *const your+ !exception6 e0 3> <p c"ass=error>C ata!ase-error occure ) <1e,w%at1></p> <0 3 3>
discarded from the output of the component and a nice error-message is printed. :ithout the savepoint the output ends at ,value5... This results in a badl formatted html-page. Mote, that ou have to include Ftnt%savepoint.hG somewhere in a F<preGsection to get the definition of tnt))@avepoint.
22 4inar" content
:eb applications ma contain logos and other images or binar content. The often have static content. Eor web applications to be complete, ou need a wa to include our images. 7n Tntnet%ecpp ou can generate components out of binar files, e.g. 3pegimages. The ecpp-compiler ecppc has a special switch -b, which generates c+ +-classes out of these files, without interpreting tags, which might appear in binar files. :ith the switch -m ou can specif the mimet pe, but if ou don;t do that, ecppc will use our mime-database (normall %etc%mime.t pes*. >xample) To generate a component out of a 3peg-file logo.3pg)
ecppc -! "ogo,Epg
will generate a logo.h and logo.cpp, which ou can compile an lin! into our application librar . The downside is, that for small binaries li!e small graphics there is a relative large overhead (7 measured a increase of the web application of about 9! per image*. Therefore starting with version 1.1 of tntnet the ecpp-compiler is able to pac! multiple binaries into a single component. This is done with the switch -bb. To address a image in a multi-image-component, ou have to pass the name of our image as pathinfo to 6ap&rl in our tntnet.conf)
Dap@r" /images/*2,Epgmymu"tiimagecomponent4mywe!app 1#
23 5pload
&ploading files is supported b html with the input-tag with t pe5.file.. To use it, ou have to specif the enct pe ,multipart%form-data. in our form-tag. :hen the form is submitted, the values comes in a special format, which supports large ob3ects. This is supported b tntnet and it has a simple api to access the uploaded file. =ecause files might be somewhat larger than other form-content, the are not passed through the 'param-parameter and not accessible in F<argsG-bloc!s. You have to fetch a const reference to a tnt))multipart-ob3ect with re'uest.get6ultipart(*. This ob3ect is a container of ob3ects of t pe tnt))part. You can either iterate through the parts or use the find-method to directl find the part, which contains the uploaded file. The tnt))part-ob3ect gives ou access to the content either through constant iterators or 3ust as a string. The iterator-interface is more efficient, because it does not need to instantiate a temporar string. You should consider alwa s to use the iterator-interface. Tntnet users guide 12
24 6TT.-0uth
Tntnet supports HTTI basic authentication. Eor HTTI authentication the server needs to chec! the sent user name and password and if invalid, send a HTTI-error-code 081 with a realm. The realm is presented to the user in a login dialog. There are / methods in tntnet, to support this)
re'uest.get&sername(* returns returns the user name sent b the client as a std))string or an empt string, if nothing set re'uest.verif Iassword(std))string password* returns true, if the password, which is sent b the client, matches the passwort passed as a parameter. Alternativel ou can use re'uest.getIassword(*, which returns the password as sent from the client. repl .notAuthori-ed(std))string realm* throws a http-exception, which sets the proper HTTI-header for basic authentication.
<0 if *re8uest,get@sername*- .= IC"a inI // user name wrongL MM .re8uest,verifyNasswor *Iopen sesameI-- // passwor wrongL 0 rep"y,notCut%ori5e *Iw%o says w%at to open t%e sesameLI-; 3 3>
5sing c++-classes
As mentioned earlier it is desirable to separate content and processing. +ontent is the view, which is created using ecpp. Irocessing are some c++classes. :hat ou need is a wa to access c++-classes from our ecpp-files. $uc!il this is eas done. Tntnet users guide 1N
A c++-class consists generall of a interface in a header-file and a implementation in a implementation-file. You can lin! our application with the implementation, but ou need a wa to include the interface into our ecpp-file. This is done in the F<preG-bloc!. +ontents of this bloc! is copied unmodified to the start of the generated header. You can place Oincludedirectives here. >xample)
<%pre> (inc"u e yourc"ass,% // inc"u e t%e c"ass- efinition %ere </%pre> <0 yourc"ass c; // e,g, instantiate your c"ass 3> <p><1 c,getCttri!ute#*- 1></p> <( inc"u e a attri!ute-va"ue into your page (>
You might as well lin! our shared librar to a external librar and use it this wa .
19
app,map@r"*IP/1I$ I%e""oI,setNat%Anfo*I/%e""oI-; app,map@r"*IP/*,2-1I$ I1#I-; st ))cout << It%e %e""o app"ication is foun %ttp)//"oca"%ost)O?O?/I << st ))en "; app,run*-; 3 catc% *const st ))exception6 e0 st ))cerr << e,w%at*- << st ))en "; 3 3 at
+reate a web application hello.ecpp. :e put a simple greeting into the application here)
<%tm"> <!o y> <%#>9e""o</%#> </!o y> </%tm">
Dun the new binar hello and navigate our browser to http)%%localhost)9888% and ou will see a greeting from our application.
1Q