Difference between revisions of "fcl-web/fr"

From Lazarus wiki
(Creating and titles translation)
 
(Voir aussi)
 
(20 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
{{fcl-web}}
 
{{fcl-web}}
  
== Qu'est fpWeb ? ==
+
== Qu'est ce que fpWeb ? ==
fpWeb can be used to build web server applications. A web server application can be one of the following
+
fpWeb peut être utilisé pour construire des applications Web serveur. Une application serveur Web peut être l'une des suivantes:
* CGI application
+
* Application CGI.
* FastCGI application
+
* Application FastCGI.
* Apache module
+
* Module Apache.
* A standalone HTTP(s) server using Free Pascal HTTP server components.
+
* Serveur HTTP(s) autonome utilisant les composants Free Pascal HTTP server.
* A standalone HTTP(s) server using GNU libmicrohttp
+
* Serveur HTTP(s) autonome utilisant  libmicrohttp de GNU.
* A windows SysHTTP application.
+
* Application Windows SysHTTP.
In all cases, the development model is the same:
 
you register handlers for a set of URLS (called routes) that your application will support.  
 
  
Then you embed these routes in one of the above environments:  
+
Dans tous les cas, le modèle de développement est le même : Vous enregistrez des gestionnaires (handlers) pour un ensemble d'URL (appelées routes) auxquels votre application saura répondre.
This means you choose the application object that you will be using.
+
Ensuite vous incorporez ces routes dans l'un des environnements du dessus : Ceci signifie que vous choisissez l'objet application que vous allez utilisez.
  
The lazarus IDE  you have the choice of applications when you start a new project. It's possible to change the application type once the application was started, this usually just means changing the name of a unit in the project's uses clause.
+
Dans l'EDI Lazarus, vous avez le choix des applications quand vous commencez un nouveau projet. Il est possible de changer le type d'application une fois que l'application a été démarrée, cela se limite souvent au changement de nom d'une unité dans la clause <code>uses</code> du projet.
  
It is possible to support multiple environments within a single binary, although this takes some extra work.
+
Il est possible de prendre en charge de multiples environnement dans un unique exécutable, au prix de quelques efforts supplémentaires.
 +
fpWeb offre aussi du support non conventionnel pour un serveur de base de données REST ou pour des mécanismes JSON RPC 2.0. Ceux-ci sont construits en haut de la structure du dessus. Le [[Brook_for_Free_Pascal/fr|cadre d'application Brook]] est aussi construit en haut de l'architecture exposée au dessus.
 +
Plus d'informations sur le sujet peut être trouvé dans [[fpWeb Tutorial]].
  
fpWeb also offers some out-of-the box support for a database REST server or for JSON RPC 2.0 mechanisms.
+
== Utilisation de fpWeb avec Lazarus ==
These are built on top of the above structure. The Brook framework is also built on top of the basic architecture outlined above.
 
 
 
More about this can be found in the [[fpWeb Tutorial]]
 
 
 
== Utilisation de fpWeb avec Lazearus Lazarus ==
 
  
 
=== Installation du paquet Lazarus fpWeb weblaz ===
 
=== Installation du paquet Lazarus fpWeb weblaz ===
Line 32: Line 27:
 
=== Création d'une application CGI ===
 
=== Création d'une application CGI ===
  
After the weblaz package is installed, a very simple CGI web application which displays an HTML page can be created by going to the Lazarus menu "File->New...". From the list of possible applications select "CGI Application" as in the image below, which will create a main CGI project file and a fpweb web module.
+
Après que le paquet <code>weblaz</code> ait été installé, une très simple application Web CGI qui affiche une page HTML peut être créée en allant dans le menu Lazarus "Fichier" -> "Nouveau...". Dans la liste des applications possibles, sélectionnez "CGI Application" comme dans l'image ci-dessous, qui va créer un fichier de projet CGI principal et un Web module fpweb.
  
 
[[Image:New_cgi.PNG]]
 
[[Image:New_cgi.PNG]]
  
The TFPWebModule allows you to manipulate properties and events using the Object Inspector.
+
Le TFPWebModule vous permet de manipuler des propriétés et des événements utilisant l'inspecteur d'objet.
  
To add code to show the page, a request handler should be added. To do this, double click the OnRequest property in the object inspector, as in the image below:
+
Pour ajouter du code pour montrer la page, un gestionnaire de requête doit être ajouté. Pour faire ceci, double-cliquer sur la propriété <code>OnRequest</code> dans l'inspecteur d'objet, comme dans l'image qui suit:
  
 
[[Image:Webmodule.PNG]]
 
[[Image:Webmodule.PNG]]
  
In the event handler one should write the HTML code which will be displayed by the browser. To avoid mixing Pascal and HTML, this page can be loaded from the directory the CGI executable is in by using AResponse.Contents.LoadFromFile().  
+
Dans le gestionnaire d'événement, on doit écrire le code HTML qui sera affiché par le navigateur. Pour éviter de mélanger le Pascal et le HTML, cette page peut être chargée depuis le répertoire où se trouve  l'exécutable CGI, en utilisant <code>AResponse.Contents.LoadFromFile()</code>.  
  
The type of the response should be set in AResponse.ContentType. For HTML pages this should have the value 'text/html;charset=utf-8'.  
+
Le type de la réponse doit être défini dans <code>AResponse.ContentType</code>. Pour les pages HTML, cela devrait avoir la valeur <code>'text/html;charset=utf-8'</code>.
  
Finally, Handled should be set to True to indicate that the request was successfully handled (and return a 200 OK status code to the browser). After adding this code, the web module should look like this:
+
Finalement, <code>Handled</code> devrait être défini à <code>True</code> pour indiquer que la requête a été traité avec succès (et retourne un code d'état '200 OK' au navigateur). Après l'ajout de ce code, le module Web devrait ressembler à ceci :
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 95: Line 90:
 
=== Déploiement d'une application CGI ===
 
=== Déploiement d'une application CGI ===
  
This section assumes the Apache web server is used. Of course, other web servers that support CGI (nginx, cherokee) can be used, too.
+
Cette section suppose que le serveur Web Apache est utilisé. Bien sûr, d'autres serveurs Web qui supportent CGI (nginx, cherokee) peuvent aussi être utilisé.
 
 
Apache can be downloaded here: http://httpd.apache.org/download.cgi or installed using your distribution's package manager.
 
  
The default installation of Apache will treat all files located in its cgi-bin directory as CGI programs, so the user won't be able to access plain HTML files placed there. This directory can be set in the file httpd.conf in the following section:
+
Apache peut être téléchargé [http://httpd.apache.org/download.cgi ici] ou installé en utilisant le gestionnaire de paquets de votre distribution.
  
 +
L'installation par défaut d'Apache traitera tous les fichiers dans son répertoire cgi-bin comme des programmes CGI, afin que l'utilisateur ne puisse pas accéder aux fichiers HTML simples qui y sont placés. Ce répertoire peut être défini dans le fichier <code>httpd.conf</code> dans la section suivante :
 
<pre>
 
<pre>
 
   #
 
   #
Line 113: Line 107:
 
</pre>
 
</pre>
  
If you place an executable called "mywebpage.cgi" in this directory, then the page can be accessed as http://localhost/cgi-bin/mywebpage.cgi (or remotely with the corresponding IP address or domain name).
+
Si vous placez un exécutable appelé "mywebpage.cgi" dans ce répertoire, alors la page peut être accédée comme <code>http://localhost/cgi-bin/mywebpage.cgi</code> (ou à distance avec l'adresse IP correspondante ou le nom de domaine).
  
fcl-web with Lazarus on Windows produces .exe files. For Apache to serve these files you have to add this:
+
fcl-web avec Lazarus sur Windows produit des fichiers .exe. Pour qu'Apache serve ces fichiers, vous devez ajouter ceci:
 
<pre>
 
<pre>
 
     AddHandler cgi-script .exe
 
     AddHandler cgi-script .exe
 
</pre>
 
</pre>
  
And to serve your executables from another directory, you add this:
+
Et pour servir vos exécutables depuis un autre répertoire, vous ajoutez ceci :
 
<syntaxhighlight lang="xml">
 
<syntaxhighlight lang="xml">
 
   ScriptAlias /bin/ "C:/lazarus_projects/test-fclweb/bin/"
 
   ScriptAlias /bin/ "C:/lazarus_projects/test-fclweb/bin/"
Line 133: Line 127:
 
=== Formatage du HTML and lecture des champs de requête ===
 
=== Formatage du HTML and lecture des champs de requête ===
  
The previous example just showed a plain HTML page. One might wish to e.g.
+
L'exemple précédent montrait juste une simple page HTML. On pourrait désirer p.ex. :
* dynamically change the HTML page output, and
+
* changer dynamiquement la sortie de la page HTML, et
* as read the variables the browser passed to the webpage in Query fields (in e.g. HTTP GET and HTTP POST actions).  
+
* en lisant les variables que le navigateur a transmises à la page Web dans les champs de requête (par exemple dans les actions HTTP GET et HTTP POST).
  
A simple solution for the first problem is simply using the standard Pascal routine Format and adding %s or %d in the HTML file in the appropriate places which will receive a custom value.
+
Une solution simple pour le premier problème est l'utilisation de routine de format du Pascal standard et l'ajout des <code>%s</code> ou <code>%d</code> dans le fichier HTML aux places appropriées qui recevront les valeurs spécifiques.
  
 
=== Lecture des données GET ===
 
=== Lecture des données GET ===
To read the GET variables one can use ARequest.QueryFields, which is a TStrings descendent. Each variable will be in a separate line in the TStrings in the format variablename=value, similarly to how they are shown in the browser page address. To search for a specific variable one can use ARequest.QueryFields.Values[], passing the variable name in the brackets to receive its value back, instead of parsing the string manually.
 
  
The resulting code:
+
Pour lire les variables GET, on peut utiliser <code>ARequest.QueryFields</code>, qui est un descendant de TStrings. Chaque variable sera dans une ligne séparée de la TStrings selon le format NomVariable=Valeur, de la même façon qu'elles sont montrées dans l'adresse de la page du navigateur. Pour accéder à une variable, on utilise <code>ARequest.QueryFields.Values[]</code> en passant le nom de la variable dans les crochets pour recevoir en retour sa valeur, au lieu d'analyser la chaîne manuellement (NdT: Explication superflue, classe de base du Pascal Objet).
  
 +
Le code résultant :
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;
 
procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;
Line 163: Line 157:
 
=== Lecture des données POST ===
 
=== Lecture des données POST ===
  
Data submitted by POST requests can be obtained from <code>TRequest.Content</code>. It will come without the request headers - in other words it contains the body of the request.
+
Les données soumises par des requêtes POST peuvent être obtenues de <code>TRequest.Content</code>. Il viendra sans les entêtes de requête - en d'autres mots, il contient le corps de la requête.
  
Submitted form data can also be accessed using <code>TRequest.ContentFields</code> which is the content parsed as fields separated by & and decoded. For example, the following set of form values:
+
Les données de formulaire soumises peuvent être accédées en utilisant <code>TRequest.ContentFields</code> qui est le contenu analysé comme des champs séparés par & et décodés. Par exemple, l'ensemble suivant de valeurs de formulaire :
  
 
  login: dfg 345&&
 
  login: dfg 345&&
Line 171: Line 165:
 
  email: dfg
 
  email: dfg
  
Will be encoded in 'APPLICATION/X-WWW-FORM-URLENCODED' like this (see [http://en.wikipedia.org/wiki/POST_%28HTTP%29 wikipedia POST (HTTP)]):
+
Sera décodé en 'APPLICATION/X-WWW-FORM-URLENCODED' comme ceci (voir [http://en.wikipedia.org/wiki/POST_%28HTTP%29 wikipedia POST (HTTP)]):
  
 
  login=dfg+345%26%26&login_senha=%3D%3D%3D%3D&email=dfg
 
  login=dfg+345%26%26&login_senha=%3D%3D%3D%3D&email=dfg
  
And will be available in TRequest.ContentFields via the line index or using the Values property, which is more convenient:
+
Et sera disponible dans <code>TRequest.ContentFields</code> via l'index de ligne ou en utilisant la propriété <code>Values</code>, ce qui est plus pertinent :
  
 
  TRequest.ContentFields[0]: login=dfg 345&&
 
  TRequest.ContentFields[0]: login=dfg 345&&
Line 182: Line 176:
 
  TRequest.ContentFields.Values['email']: dfg
 
  TRequest.ContentFields.Values['email']: dfg
  
If using other mime-types than 'MULTIPART/FORM-DATA' and 'APPLICATION/X-WWW-FORM-URLENCODED' (the types supported by HTML forms):
+
En cas d'utilisation d'autres types MIME que 'MULTIPART/FORM-DATA' et 'APPLICATION/X-WWW-FORM-URLENCODED' (les types supportés par les formulaires HTML) :
* content is only available in TRequest.Content, not TRequest.ContentFields
+
* le contenu est uniquement disponible dans <code>TRequest.Content</code> et non pas <code>TRequest.ContentFields</code>.
* use of these mime-types raises an exception for FPC 2.4.2 (fixed in FPC 2.5+).
+
* l'usage de ces types MIME lève un exception pour FPC 2.4.2 (corrigé dans FPC 2.5+).
  
Note that HTTP POST can also send Query fields (in the URL), e.g. http://server/bla?question=how, and those are accessed by TRequest.QueryFields as explained in the previous section.
+
Remarquez que HTTP POST peut aussi envoyer des champs de requête (dans l'URL), p.ex. <code>http://server/bla?question=how</code>, et qui sont accédés par <code>TRequest.QueryFields</code> comme expliqué dans la section précédente.
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 198: Line 192:
  
 
=== Lecture des données binaire POST ===
 
=== Lecture des données binaire POST ===
Uploaded files are saved to a temporary location with a temporary filename, to retain the file you should move it to a permanent location.
+
Les fichiers téléchargés vers le serveur sont sauvés dans un emplacement temporaire avec un nom de fichier temporaire, pour conserver le fichier, vous devrez le déplacer vers un emplacement permanent.
  
To receive data on the server that has been POSTed e.g. as multipart/form-data, use something like this:
+
Pour recevoir des données sur le serveur qui a été POSTé p.ex comme multipart/form-data, utilisez quelques chose comme ceci :
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 219: Line 213:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
The client can send data using e.g. FileFormPost.
+
Le client peut envoyer des données en utilisant p.ex. <code>FileFormPost</code>.
  
 
== Modules spécialisés ==
 
== Modules spécialisés ==
The *TFPWebModule* class (used below) is a simple example of a WEb module that can be used for all kinds of HTTP requests.
+
La classe *<code>TFPWebModule</code>* (utilisée dessous) est un simple exemple de module Web quii peut être utilisé pour toutes sortes de requêtes HTTP..
  
However, fpweb comes with some specialized modules, that have extra support for specialized tasks:
+
Toutefois, fpweb vient avec quelques modules spécialisés, qui réalisent des tâches spécialisés :
  
* The '''TSimpleFileModule''' class in unit ''fpwebfile.pp'' can be used to send files. You point it to a directory, and it does the rest.
+
* La classe '''TSimpleFileModule''' dans l'unité ''fpwebfile.pp'' peut etre utilisée pour envoyer des fichiers. Vous pointez vers un répertoire et elle fait le reste.
* The '''TFPHTMLModule''' class in unit ''fphtml.pp'' can be used to produce HTML.
+
* La classe '''TFPHTMLModule''' dans l'unité ''fphtml.pp'' peut être utlisé pour produire du HTML.
* The '''TProxyWebModule''' class in unit ''fpwebproxy.pp'' is a ready-made forwarding proxy.  
+
* La classe '''TProxyWebModule''' dans l'unité ''fpwebproxy.pp'' est un proxy de transmission (forwarding proxy) prêt à l'emploi.  
* The '''TFPWebProviderDataModule''' class in unit ''fpwebdata.pp'' serves data in JSON format that can be consumed by ExtJS stores.
+
* La classe '''TFPWebProviderDataModule''' dans l'unité ''fpwebdata.pp'' sert des données au format JSON qui peut être consommé par des magasins (stores) ExtJS.
* The '''TSQLDBRestModule''' class in unit ''sqldbrestmodule.pp'' implements a full REST server backed by SQLDB. See more info in [[SQLDBRestBridge]].
+
* La classe '''TSQLDBRestModule''' dans l'unité ''sqldbrestmodule.pp'' implémente un serveur full REST appuyé par SQLDB. Voir plus d'informations dans [[SQLDBRestBridge]].
* The '''TJSONRPCModule''' class in unit ''webjsonrpc.pp'' implements a JSON-RPC service.
+
* La classe '''TJSONRPCModule''' dans l'unité ''webjsonrpc.pp'' implémente un service JSON-RPC.
* The '''TExtDirectModule''' class in unit ''fpextdirect.pp'' implements a Ext.Direct variant of a JSON-RPC service.
+
* La classe '''TExtDirectModule''' dans l'unité ''fpextdirect.pp'' implémente une variante Ext.Direct d'un service JSON-RPC.
  
 
== Utiliser de multiples modules ==
 
== Utiliser de multiples modules ==
If there is only one module in the web application, all requests will be directed to this module.  
+
Si il y a un seul module dans l'application Web, toutes les requêtes seront redirigées vers ce module.
  
As your web application grows, multiple modules can be used. A new module can be added by choosing 'File - New' and then one of 'Web module' or 'HTML Web Module'.  
+
Comme votre application Web grossit, de multiples modules peuvent être utilisés. Un nouveau module peut être ajouté en choisissant "Fichier" -> "Nouveau..."  et ensuite un des 'Module Web' ou 'Module Web HTML'.
  
FCL-web uses the URL to determine how a HTTP request should be handled. It must therefore know which web-modules exist in the application. To achieve this, each module must be registered.
+
FCL-web utilise l'URL pour déterminer comment une requête HTTP qui devrait être manipulé. Il doit donc savoir quels modules Web existent dans l'application. Pour ce faire, chaque module doit être enregistré.
  
Each module is registered with fcl-web in the initialization section of the unit it is defined in:
+
Chaque module est enregistré avec fcl-web dans la section 'initialisation de l'unité dans lequel il est défini:
  
 
<syntaxhighlight lang="pascal">RegisterHTTPModule('location', TMyModule);</syntaxhighlight>
 
<syntaxhighlight lang="pascal">RegisterHTTPModule('location', TMyModule);</syntaxhighlight>
  
The module will then be invoked if an URL of the form
+
Le module sera alors invoqué si une URL de la forme
 
  <nowiki>http://www.mysite.org/mycgi.cgi/location</nowiki>
 
  <nowiki>http://www.mysite.org/mycgi.cgi/location</nowiki>
or
+
ou
 
  <nowiki>http://www.mysite.org/mycgi.cgi?module=location</nowiki>
 
  <nowiki>http://www.mysite.org/mycgi.cgi?module=location</nowiki>
is used.
+
est utilisée.
  
If multiple modules are present, the name of the module must appear in the URL, or an error will be raised.
+
Si plusieurs modules sont présents, le nom du module doit apparaître dans l'URL, ou une erreur sera levée.
  
This behaviour can also be forced for applications that have only a single module by setting the Application's property AllowDefaultModule to false:
+
Ce comportement peut aussi être forcé pour les applications qui ont seulement un unique module en définissant la propriéte <code>AllowDefaultModule</code> de l'application à <code>False</code> :
  
 
<syntaxhighlight lang="pascal">Application.AllowDefaultModule := False;</syntaxhighlight>
 
<syntaxhighlight lang="pascal">Application.AllowDefaultModule := False;</syntaxhighlight>
  
In that case, the fcl-web application will always require the name of the module in the URL.
+
Dans ce cas, l'application fcl-web requerra toujours le nom du module dans l'URL.
  
The name of the request variable that determines the module name (by default, this is 'module') can be set in the Application.ModuleVariable property. The following code
+
Le nom de la variable de requête qui détermine le nom du module (par défaut, c'est 'module') peut être défini dans la propriété <code>Application.ModuleVariable</code>. Le code suivant
  
 
<syntaxhighlight lang="pascal">Application.ModuleVariable := 'm';</syntaxhighlight>
 
<syntaxhighlight lang="pascal">Application.ModuleVariable := 'm';</syntaxhighlight>
  
ensures that the following URL is directed to TMyModule:
+
assure que l'URL suivante est dirigée vers <code>TMyModule</code> :
 +
 
 
  <nowiki>http://www.mysite.org/mycgi.cgi?m=location</nowiki>
 
  <nowiki>http://www.mysite.org/mycgi.cgi?m=location</nowiki>
  
If all this is not enough to determine the module to which the request should be passed, the Application.OnGetModule event can be used. It is of type TGetModuleEvent:
+
Si tout ceci n'est pas suffisant pour déterminer le module vers lequel la requête devrait être passée, l'événement <code>Application.OnGetModule</code> peut être utilisé. Il est du type <code>TGetModuleEvent</code> :
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 274: Line 269:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Creating an event handler for this event allows fine control over the module that is created to handle the request: the request (passed in ARequest) can be examined, and the 'ModuleClass' variable must be set to the class of the module that should handle the request.
+
La création d'un gestionnaire pour cet événement permet un contrôle fin sur le module qui est créé pour manipuler la requête : la requête (passée dans <code>ARequest</code>) peut être examinée et la variable <code>ModuleClass</code> doit être définie par la classe du module qui devrait manipuler la requête.
  
If 'ModuleClass' is 'Nil' on return, an error will be sent to the browser.
+
Si <code>ModuleClass</code> vaut <code>Nil</code> au retour, une erreur sera envoyée au navigateur.
  
 
== Utilisation des actions ==
 
== Utilisation des actions ==
  
A module can be used to group certain kinds of actions that logically belong together. Imagine a module TUserModule that is used to handle user management in the webpages. There can be multiple actions associated with a user:
+
Un module peut être utilisé pour grouper certaines sortes d'actions logiquement liées. Imaginez un module <code>TUserModule</code> qui est utilisé pour traiter la gestion utilisateur dans les pages Web. Il peut y avoir de multiples actions associées avec un utilisateur :
* Creating
+
* Création
* Deleting
+
* Suppression
* Editing
+
* Mise à jour
* Displaying
+
* Affichage
These different actions can be handled by the same module. One can determine the action from the URL manually, as in:
+
Ces différentes actions peuvent être maniée par le mêm module. On peut déterminer l'action depuis l'URL manuellement, comme dans :
 
  <nowiki>http://mysite/mycgi.cgi/user?action=delete&id=12</nowiki>
 
  <nowiki>http://mysite/mycgi.cgi/user?action=delete&id=12</nowiki>
This can be automated.
+
Cela peut être automatisé.
  
In order to make it easier to distinguish between various actions, the module has a property actions: this is a collection, in which each item is associated with a different response to the request. The actions have various properties:
+
Afin de rendre plus facile la distinction entre les diverses actions, le module a une propriété <code>actions</code> : c'est une collection, dans laquelle chaque article est associé avec une réponse différente à la requête. Les actions ont diverses propriétés :
; Name : The name of the action. The URL will be examined to determine the name of the action.
+
; <code>Name</code> : Le nom de l'action. L'URL sera examinée pour déterminer le nom de l'action.
; Content : A string. If set, this is sent to the browser.
+
; <code>Content</code> : Une chaîne de caractères. Si définie, c'est envoyé vers le navigateur.
; Contents :A stringlist. If set, this is sent to the browser.
+
; <code>Contents</code> : Une TStringList. c'est envoyé vers le navigateur.
; ContentProducer :If set, the contentproducer will handle the request.
+
; <code>ContentProducer</code> : Si définie, the ContentProducer maniera la requête.
; Default: if set to 'True', then this action is the default action. That means that if FCL-Web cannot determine the action name, this action will be executed.
+
; <code>Default</code>: Si définie à <code>True</code>, alors cette action est l'action par défaut. Ceci signifie que si FCL-Web ne peut pas déterminer le nom de l'action, cette action sera exécutée.
; Template : If set, this template will be processed, and the results sent to the browser.
+
; <code>Template</code> : Si définie, ce patron sera traité et les résultats envoyés vers le navigateur.
There are also some events:
 
; BeforeRequest : executed before the request is processed. Can be used to set the 'Content' or other properties.
 
; AfterRequest : executed after the request is processed.
 
; OnRequest : an event handler to handle the request. If set, the handler is used to handle the request.
 
  
Again, as in the case of multiple modules, the URL is used to determine which action to execute. The part right after the module part ("user" in this example) is used:
+
Il y a aussi quelques événements :
 +
; <code>BeforeRequest</code> : exécuté avant que la requête ne soit traitée. Peut être utilisé pour définir le 'Content' ou d'autres propriétés.
 +
; <code>AfterRequest</code> : exécuté après le traitement de la requête.
 +
; <code>OnRequest</code> : un gestionnaire d'événement pour manier la requête. Si défini, le gstionnaire est utilisé pour manier la requête.
 +
 
 +
Encore une fois, comme dans le cas de plusieurs modules, l'URL est utilisée pour déterminer quelle action exécuter. La partie juste après la partie module ("utilisateur" dans cet exemple) est utilisée:
 
  <nowiki>http://mysite/mycgi.cgi/user/delete&id=12</nowiki>
 
  <nowiki>http://mysite/mycgi.cgi/user/delete&id=12</nowiki>
would execute the action named 'delete'.
+
exécutera l'action nommée 'delete'.
 
 
The 'ActionVar' property of the module can be used to set the name of the request variable to use. Setting
 
  
 +
La propriété <code>ActionVar</code> du module peut être utilisée pour définir le nom de la variable de requête à utiliser. En affectant :
 
<syntaxhighlight lang="pascal">UserModule.ActionVar := 'a';</syntaxhighlight>
 
<syntaxhighlight lang="pascal">UserModule.ActionVar := 'a';</syntaxhighlight>
 
+
peut être utilisé pour changer l'URL du dessus en :
may be used to change the above URL to
 
 
  <nowiki>http://mysite/mycgi.cgi/user?a=delete&id=12</nowiki>
 
  <nowiki>http://mysite/mycgi.cgi/user?a=delete&id=12</nowiki>
  
If there is only one module in the application, the URL can be shortened to
+
S'il y a seulement un module dans l'application, l'URL peut être raccourci en :
 
  <nowiki>http://mysite/mycgi.cgi/delete&id=12</nowiki>
 
  <nowiki>http://mysite/mycgi.cgi/delete&id=12</nowiki>
  
 
== Utilisation des patrons HTML ==
 
== Utilisation des patrons HTML ==
For information about using templates, template tags and template tag parameters to generate response pages, please refer to the fptemplate.txt file under your FPC directory in /packages/fcl-base/texts/.
+
Pour de l'information au sujet des patrons (template), des étiquettes de patron (template tags) et des paramètres d'étiquettes de patron (template tag parameters) pour générer les pages de réponse, veuillez vous référer au fichier <code>fptemplate.txt</code> dans le répertoire FPC dans <code>/packages/fcl-base/texts/</code> (NdT : spécifique Linux)
 +
 
 +
Des projets d'exemple qui démontrent l'utilisation des patrons peuvent être trouvés sous le répertoire FPC dans <code>/packages/fcl-web/examples/fptemplate</code> (voir le README.txt dedans pour plus).
  
Example projects that demonstrate using templates can be found under your FPC directory in /packages/fcl-web/examples/fptemplate/ (see the README.txt in there for more).
+
(Dans les versions antérieures, ces exemples se trouvaient dans le répertoire Lazarus dans <code>/components/fpweb/demo/fptemplate/</code>)
(In earlier versions, these examples were in the Lazarus directory in /components/fpweb/demo/fptemplate/)
 
  
 
== Conseils & résolution de problèmes ==
 
== Conseils & résolution de problèmes ==
  
 
=== Envoi des codes de retour ===
 
=== Envoi des codes de retour ===
To send a different HTTP response than 200 OK, use '''AResponse.Code''' and '''AResponse.CodeText''', e.g.
+
Pour envoyer une réponse HTTP différente de 200 OK, utiliser <code>AResponse.Code</code> et <code>AResponse.CodeText</code>, p.ex. :
  
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
Line 332: Line 327:
  
 
=== Envoi de données binaires ===
 
=== Envoi de données binaires ===
An approach that seems to work to send e.g. a tiff file from the web server to the client - adapted from $(fpcdirectory)\packages\fcl-web\examples\jsonrpc\demo1\wmdemo.pp - something like:
+
Une approche qui semble marcher pour envoyer p.ex. un fichier tiff depuis le serveur Web vers le client - adapté de <code>$(fpcdirectory)\packages\fcl-web\examples\jsonrpc\demo1\wmdemo.pp</code> - quelque chose comme ceci :
 
 
 
<syntaxhighlight lang="pascal">
 
<syntaxhighlight lang="pascal">
 
AResponse.ContentStream := TMemoryStream.Create;
 
AResponse.ContentStream := TMemoryStream.Create;
Line 351: Line 345:
  
 
=== Erreur: "Could not determine HTTP module for request" ===
 
=== Erreur: "Could not determine HTTP module for request" ===
You may have multiple modules and multiple actions. If you specify an URL with only 1 item, like:
+
Vous pouvez avoir de multiples modules et de multiples actions. Si vous spécifiez une URL avec un seul item, comme :
 +
 
 
<syntaxhighlight lang="html4strict">http://localhost/cgi-bin/somemodule</syntaxhighlight>
 
<syntaxhighlight lang="html4strict">http://localhost/cgi-bin/somemodule</syntaxhighlight>
then fpweb assumes you're specifying an action. If you don't have a default module set, you will get a 500 internal server error (Could not determine HTTP module for request)
+
alors fpweb suppose que vous êtes en train de spécifier une action. Si vous n'avez pas défini un module par défaut, vous obtiendrez une "500 internal server error (Could not determine HTTP module for request)".
  
You can modify this behaviour to let fpweb map to a module name instead by setting the application's '''PreferModuleName''' property to true.
+
Vous pouvez modifier ce comportement pour permettre à fpweb de correspondre à un nom de module à la place en définissant la propriété <code>PreferModuleName</code> de l'application sur <code>True</code>.
  
 
=== Erreur: "response code 500 Internal Server error when trying to handle DELETE method" ===
 
=== Erreur: "response code 500 Internal Server error when trying to handle DELETE method" ===
In FPC 2.6.2 and lower, fcl-web does not accept the DELETE method and generates an error.
+
Dans FPC 2.6.2 et antérieur, fcl-web n'accepte pas la méthode DELETE et génère une erreur.
  
 
=== fpWeb/FCGI et Apache 2.4 (mode mod_proxy_fcgi) ===
 
=== fpWeb/FCGI et Apache 2.4 (mode mod_proxy_fcgi) ===
When you want to deploy FCGI application behind Apache 2.4+ reverse proxy, you need PATH_INFO variable in headers that are sent via socket to FCGI daemon.
+
Quand vous voulez déployer une application FastCGI derrière un proxy inverse Apache 2.4+, vous avez besoin de la variable PATH_INFO dans les entêtes qui sont envoyés vai une socket au démon FastCGI.
  
1, Enable following modules: setenvif_module, proxy_module and proxy_fcgi_module <br/>
+
1, Activer les modules suivants: setenvif_module, proxy_module et proxy_fcgi_module <br/>
(on CentOS 7 modules are defined in file /etc/httpd/conf.modules.d/00-base.conf and /etc/httpd/conf.modules.d/00-proxy.conf).
+
 
 +
(sur CentOS 7 modules sont définis dans le fichier <code>/etc/httpd/conf.modules.d/00-base.conf</code> et <code>/etc/httpd/conf.modules.d/00-proxy.conf)</code>.
 
<pre>
 
<pre>
 
LoadModule setenvif_module  modules/mod_setenvif.so
 
LoadModule setenvif_module  modules/mod_setenvif.so
Line 371: Line 367:
 
</pre>
 
</pre>
  
2, Reverse proxy configuration for fpWeb/FCGI listening on port 9000.<br/>
+
2, Configuration du proxy inverse pour fpWeb/FCGI écoutant sur le port 9000.<br/>
 
$1 = module name<br/>
 
$1 = module name<br/>
 
$2 = action name
 
$2 = action name
Line 380: Line 376:
  
 
=== fpWeb/FCGI et nginx ===
 
=== fpWeb/FCGI et nginx ===
For correct routing, fcl-web requires the PATH_INFO variable in headers sent from nginx. For this you have to split the whole URL into FastCGI application name and the path info part whith the configuration statement ''fastcgi_split_path_info''. The statement accepts a regular expression and puts the second match into ''$fastcgi_path_info'' configuration variable. This variable can be passed to your application with ''fastcgi_param'' statement.
+
Pour un routage correct, fcl-web requiert que la variable PATH_INFO dans les entêtes envoyés depuis nginx. Pour cela, vous devez diviser l'URL entière en nom d'application FastCGI et en partie information de chemin (path info) avec l'instruction de configuration ''fastcgi_split_path_info''. L'instruction accepte une expression régulière et pose la seconde correspondance dans la variable de configuration ''$fastcgi_path_info''. Cette variable peut être passée à votre application avec l'instruction ''fastcgi_param''.
  
The following configuration example includes a full virtual host for nginx which passes everything from ''http://myserver:8080/mycgiapp/'' to an external FastCGI application.
+
L'exemple de configuration suivante inclut un hôte virtuel complet pour nginx qui passe tout depuis ''http://myserver:8080/mycgiapp/'' vers une application FastCGI externe.
 
<pre>
 
<pre>
 
server {
 
server {
Line 426: Line 422:
  
 
== Notes ==
 
== Notes ==
 
+
* L'unité cgiapp est dépréciée, veuillez utiliser fpcgi autant que possible.
* The cgiapp unit is deprecated, please use fpcgi as much as possible.
+
* Les unités fastcgi, custfcgi et fpfcgi ne sont pas supportées sur Darwin en ce moment (Ndt: Qu'en est-il en 2020 ?), parce qu'il utilise un mécanisme qui différe de l'option MSG_NOSIGNAL pour recv() pour indiquer qu'aucun SIGPIPE ne doit être levé en cas de rupture de la connexion. Voir http://lists.apple.com/archives/macnetworkprog/2002/Dec/msg00091.html pour comment cela peut être fixé.
 
+
* Si vous déployez votre application et obtenez des erreurs comme "Error: No action name and no default action", vous devrez vous assurer qu'il y a une action affectée à l'URL, ou intercepter les actions non supportées avec une action marquée Default. Dans les deux cas, un gestionnaire d'événement <code>OnRequest</code> pour l'action qui définit <code>Handled:=true</code> devrait être utilisé.
* The fastcgi, custfcgi, and fpfcgi units are not supported on Darwin at this time, because it uses a different mechanism than the MSG_NOSIGNAL option for recv() to indicate that no SIGPIPE should be raised in case the connection breaks. See http://lists.apple.com/archives/macnetworkprog/2002/Dec/msg00091.html for how this should be fixed.
 
 
 
* If you deploy your CGI application and get errors like "Error: No action name and no default action", you should make sure there's an action assigned to the URL, or catch non-supported actions with an action marked Default. In both cases, an OnRequest event handler for the action that sets Handled:=true should be used.
 
  
 
== Voir aussi ==
 
== Voir aussi ==
 
* [[fpWeb Tutorial]]
 
* [[fpWeb Tutorial]]
* [[fphttpclient]] Part of fcl-web that can be used stand-alone in client applications
+
* [[fphttpclient]] Partie de fcl-web qui peut être utilisé de manière autonome dans des applications clientes.
* ''write me!''fphttpserver Small stand alone Object Pascal web server. Can be used to serve fcl-web CGI applications.
+
* ''write me!''fphttpserver Petit serveur Web autonome en Pascal Objet. Peut être utilisé pour servir des applications CGI fcl-web.
* [[CGI_Web_Programming#Debugging_CGI]] Information about debugging CGI applications
+
* [[CGI_Web_Programming/fr#Débogage_de_CGI|Débogage de CGI]] Information concernant le débogage des applications CGI.
 
* [https://github.com/leonardorame/Ext4-MVC-Tutorial/wiki/Lazarus-Server Part of a tutorial by Leonardo Ramé that shows how to program an fcl-web CGI application; includes example of generating JSON content]
 
* [https://github.com/leonardorame/Ext4-MVC-Tutorial/wiki/Lazarus-Server Part of a tutorial by Leonardo Ramé that shows how to program an fcl-web CGI application; includes example of generating JSON content]

Latest revision as of 01:59, 1 May 2020

English (en) español (es) français (fr) русский (ru)

Qu'est ce que fpWeb ?

fpWeb peut être utilisé pour construire des applications Web serveur. Une application serveur Web peut être l'une des suivantes:

  • Application CGI.
  • Application FastCGI.
  • Module Apache.
  • Serveur HTTP(s) autonome utilisant les composants Free Pascal HTTP server.
  • Serveur HTTP(s) autonome utilisant libmicrohttp de GNU.
  • Application Windows SysHTTP.

Dans tous les cas, le modèle de développement est le même : Vous enregistrez des gestionnaires (handlers) pour un ensemble d'URL (appelées routes) auxquels votre application saura répondre. Ensuite vous incorporez ces routes dans l'un des environnements du dessus : Ceci signifie que vous choisissez l'objet application que vous allez utilisez.

Dans l'EDI Lazarus, vous avez le choix des applications quand vous commencez un nouveau projet. Il est possible de changer le type d'application une fois que l'application a été démarrée, cela se limite souvent au changement de nom d'une unité dans la clause uses du projet.

Il est possible de prendre en charge de multiples environnement dans un unique exécutable, au prix de quelques efforts supplémentaires. fpWeb offre aussi du support non conventionnel pour un serveur de base de données REST ou pour des mécanismes JSON RPC 2.0. Ceux-ci sont construits en haut de la structure du dessus. Le cadre d'application Brook est aussi construit en haut de l'architecture exposée au dessus. Plus d'informations sur le sujet peut être trouvé dans fpWeb Tutorial.

Utilisation de fpWeb avec Lazarus

Installation du paquet Lazarus fpWeb weblaz

The first step to do is installing the package which comes in the path lazarus/components/fpweb/weblaz.lpk. As usual with design-time packages, you'll have to rebuild Lazarus.

Création d'une application CGI

Après que le paquet weblaz ait été installé, une très simple application Web CGI qui affiche une page HTML peut être créée en allant dans le menu Lazarus "Fichier" -> "Nouveau...". Dans la liste des applications possibles, sélectionnez "CGI Application" comme dans l'image ci-dessous, qui va créer un fichier de projet CGI principal et un Web module fpweb.

New cgi.PNG

Le TFPWebModule vous permet de manipuler des propriétés et des événements utilisant l'inspecteur d'objet.

Pour ajouter du code pour montrer la page, un gestionnaire de requête doit être ajouté. Pour faire ceci, double-cliquer sur la propriété OnRequest dans l'inspecteur d'objet, comme dans l'image qui suit:

Webmodule.PNG

Dans le gestionnaire d'événement, on doit écrire le code HTML qui sera affiché par le navigateur. Pour éviter de mélanger le Pascal et le HTML, cette page peut être chargée depuis le répertoire où se trouve l'exécutable CGI, en utilisant AResponse.Contents.LoadFromFile().

Le type de la réponse doit être défini dans AResponse.ContentType. Pour les pages HTML, cela devrait avoir la valeur 'text/html;charset=utf-8'.

Finalement, Handled devrait être défini à True pour indiquer que la requête a été traité avec succès (et retourne un code d'état '200 OK' au navigateur). Après l'ajout de ce code, le module Web devrait ressembler à ceci :

unit mainpage;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, HTTPDefs, websession, fpHTTP, fpWeb; 

type

  { TFPWebModule1 }

  TFPWebModule1 = class(TFPWebModule)
    procedure DataModuleRequest(Sender: TObject; ARequest: TRequest;
      AResponse: TResponse; var Handled: Boolean);
  private
    { private declarations }
  public
    { public declarations }
  end; 

var
  FPWebModule1: TFPWebModule1; 

implementation

{$R *.lfm}

{ TFPWebModule1 }

procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;
  AResponse: TResponse; var Handled: Boolean);
begin
  AResponse.ContentType := 'text/html;charset=utf-8';
  AResponse.Contents.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'mainpage.html');
  Handled := True;
end;

begin
  RegisterHTTPModule('TFPWebModule1', TFPWebModule1);
end.

Déploiement d'une application CGI

Cette section suppose que le serveur Web Apache est utilisé. Bien sûr, d'autres serveurs Web qui supportent CGI (nginx, cherokee) peuvent aussi être utilisé.

Apache peut être téléchargé ici ou installé en utilisant le gestionnaire de paquets de votre distribution.

L'installation par défaut d'Apache traitera tous les fichiers dans son répertoire cgi-bin comme des programmes CGI, afin que l'utilisateur ne puisse pas accéder aux fichiers HTML simples qui y sont placés. Ce répertoire peut être défini dans le fichier httpd.conf dans la section suivante :

   #
   # ScriptAlias: This controls which directories contain server scripts.
   # ScriptAliases are essentially the same as Aliases, except that
   # documents in the target directory are treated as applications and
   # run by the server when requested rather than as documents sent to the
   # client.  The same rules about trailing "/" apply to ScriptAlias
   # directives as to Alias.
   #
   ScriptAlias /cgi-bin/ "C:/Program Files/Apache Software Foundation/Apache2.2/cgi-bin/"

Si vous placez un exécutable appelé "mywebpage.cgi" dans ce répertoire, alors la page peut être accédée comme http://localhost/cgi-bin/mywebpage.cgi (ou à distance avec l'adresse IP correspondante ou le nom de domaine).

fcl-web avec Lazarus sur Windows produit des fichiers .exe. Pour qu'Apache serve ces fichiers, vous devez ajouter ceci:

    AddHandler cgi-script .exe

Et pour servir vos exécutables depuis un autre répertoire, vous ajoutez ceci :

   ScriptAlias /bin/ "C:/lazarus_projects/test-fclweb/bin/"
   <Directory "C:/lazarus_projects/test-fclweb/bin/">
       AllowOverride None
       Options None
       Order allow,deny
       Allow from all
   </Directory>

Formatage du HTML and lecture des champs de requête

L'exemple précédent montrait juste une simple page HTML. On pourrait désirer p.ex. :

  • changer dynamiquement la sortie de la page HTML, et
  • en lisant les variables que le navigateur a transmises à la page Web dans les champs de requête (par exemple dans les actions HTTP GET et HTTP POST).

Une solution simple pour le premier problème est l'utilisation de routine de format du Pascal standard et l'ajout des %s ou %d dans le fichier HTML aux places appropriées qui recevront les valeurs spécifiques.

Lecture des données GET

Pour lire les variables GET, on peut utiliser ARequest.QueryFields, qui est un descendant de TStrings. Chaque variable sera dans une ligne séparée de la TStrings selon le format NomVariable=Valeur, de la même façon qu'elles sont montrées dans l'adresse de la page du navigateur. Pour accéder à une variable, on utilise ARequest.QueryFields.Values[] en passant le nom de la variable dans les crochets pour recevoir en retour sa valeur, au lieu d'analyser la chaîne manuellement (NdT: Explication superflue, classe de base du Pascal Objet).

Le code résultant :

procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;
  AResponse: TResponse; var Handled: Boolean);
var
  HexText, AsciiText: string;
begin
  HexText := ARequest.QueryFields.Values['hex'];
  AsciiText := HexToAnsii(HexText);

  AResponse.ContentType := 'text/html;charset=utf-8';
  AResponse.Contents.LoadFromFile(ExtractFilePath(ParamStr(0)) + 'mainpage.html');
  AResponse.Contents.Text := Format(AResponse.Contents.Text,
    [HexText, AsciiText]);
  Handled := True;
end;

Lecture des données POST

Les données soumises par des requêtes POST peuvent être obtenues de TRequest.Content. Il viendra sans les entêtes de requête - en d'autres mots, il contient le corps de la requête.

Les données de formulaire soumises peuvent être accédées en utilisant TRequest.ContentFields qui est le contenu analysé comme des champs séparés par & et décodés. Par exemple, l'ensemble suivant de valeurs de formulaire :

login: dfg 345&&
login_senha: ====
email: dfg

Sera décodé en 'APPLICATION/X-WWW-FORM-URLENCODED' comme ceci (voir wikipedia POST (HTTP)):

login=dfg+345%26%26&login_senha=%3D%3D%3D%3D&email=dfg

Et sera disponible dans TRequest.ContentFields via l'index de ligne ou en utilisant la propriété Values, ce qui est plus pertinent :

TRequest.ContentFields[0]: login=dfg 345&&
TRequest.ContentFields[1]: login_senha=====
TRequest.ContentFields[2]: email=dfg
TRequest.ContentFields.Values['email']: dfg

En cas d'utilisation d'autres types MIME que 'MULTIPART/FORM-DATA' et 'APPLICATION/X-WWW-FORM-URLENCODED' (les types supportés par les formulaires HTML) :

  • le contenu est uniquement disponible dans TRequest.Content et non pas TRequest.ContentFields.
  • l'usage de ces types MIME lève un exception pour FPC 2.4.2 (corrigé dans FPC 2.5+).

Remarquez que HTTP POST peut aussi envoyer des champs de requête (dans l'URL), p.ex. http://server/bla?question=how, et qui sont accédés par TRequest.QueryFields comme expliqué dans la section précédente.

procedure TFPWebModule1.DataModuleRequest(Sender: TObject; ARequest: TRequest;
  AResponse: TResponse; var Handled: Boolean);
var
  lData: String;
begin
  lData := ARequest.Content;

Lecture des données binaire POST

Les fichiers téléchargés vers le serveur sont sauvés dans un emplacement temporaire avec un nom de fichier temporaire, pour conserver le fichier, vous devrez le déplacer vers un emplacement permanent.

Pour recevoir des données sur le serveur qui a été POSTé p.ex comme multipart/form-data, utilisez quelques chose comme ceci :

procedure TMainWebModule.TFPWebActions2Request(Sender: TObject;
  ARequest: TRequest; AResponse: TResponse; var Handled: Boolean);
var
  i: Integer;
begin  
  // Process all received files
  for i := 0 to ARequest.Files.Count - 1 do
  begin
    // Doing something else than writeln is highly recommended ;)
    writeln ('Received Filename: '+ARequest.Files[i].LocalFileName);
  end;
      
  Handled := true;
end;

Le client peut envoyer des données en utilisant p.ex. FileFormPost.

Modules spécialisés

La classe *TFPWebModule* (utilisée dessous) est un simple exemple de module Web quii peut être utilisé pour toutes sortes de requêtes HTTP..

Toutefois, fpweb vient avec quelques modules spécialisés, qui réalisent des tâches spécialisés :

  • La classe TSimpleFileModule dans l'unité fpwebfile.pp peut etre utilisée pour envoyer des fichiers. Vous pointez vers un répertoire et elle fait le reste.
  • La classe TFPHTMLModule dans l'unité fphtml.pp peut être utlisé pour produire du HTML.
  • La classe TProxyWebModule dans l'unité fpwebproxy.pp est un proxy de transmission (forwarding proxy) prêt à l'emploi.
  • La classe TFPWebProviderDataModule dans l'unité fpwebdata.pp sert des données au format JSON qui peut être consommé par des magasins (stores) ExtJS.
  • La classe TSQLDBRestModule dans l'unité sqldbrestmodule.pp implémente un serveur full REST appuyé par SQLDB. Voir plus d'informations dans SQLDBRestBridge.
  • La classe TJSONRPCModule dans l'unité webjsonrpc.pp implémente un service JSON-RPC.
  • La classe TExtDirectModule dans l'unité fpextdirect.pp implémente une variante Ext.Direct d'un service JSON-RPC.

Utiliser de multiples modules

Si il y a un seul module dans l'application Web, toutes les requêtes seront redirigées vers ce module.

Comme votre application Web grossit, de multiples modules peuvent être utilisés. Un nouveau module peut être ajouté en choisissant "Fichier" -> "Nouveau..." et ensuite un des 'Module Web' ou 'Module Web HTML'.

FCL-web utilise l'URL pour déterminer comment une requête HTTP qui devrait être manipulé. Il doit donc savoir quels modules Web existent dans l'application. Pour ce faire, chaque module doit être enregistré.

Chaque module est enregistré avec fcl-web dans la section 'initialisation de l'unité dans lequel il est défini:

RegisterHTTPModule('location', TMyModule);

Le module sera alors invoqué si une URL de la forme

http://www.mysite.org/mycgi.cgi/location

ou

http://www.mysite.org/mycgi.cgi?module=location

est utilisée.

Si plusieurs modules sont présents, le nom du module doit apparaître dans l'URL, ou une erreur sera levée.

Ce comportement peut aussi être forcé pour les applications qui ont seulement un unique module en définissant la propriéte AllowDefaultModule de l'application à False :

Application.AllowDefaultModule := False;

Dans ce cas, l'application fcl-web requerra toujours le nom du module dans l'URL.

Le nom de la variable de requête qui détermine le nom du module (par défaut, c'est 'module') peut être défini dans la propriété Application.ModuleVariable. Le code suivant

Application.ModuleVariable := 'm';

assure que l'URL suivante est dirigée vers TMyModule :

http://www.mysite.org/mycgi.cgi?m=location

Si tout ceci n'est pas suffisant pour déterminer le module vers lequel la requête devrait être passée, l'événement Application.OnGetModule peut être utilisé. Il est du type TGetModuleEvent :

type
  TGetModuleEvent = Procedure (Sender : TObject; ARequest : TRequest;
                               Var ModuleClass : TCustomHTTPModuleClass) of object;

La création d'un gestionnaire pour cet événement permet un contrôle fin sur le module qui est créé pour manipuler la requête : la requête (passée dans ARequest) peut être examinée et la variable ModuleClass doit être définie par la classe du module qui devrait manipuler la requête.

Si ModuleClass vaut Nil au retour, une erreur sera envoyée au navigateur.

Utilisation des actions

Un module peut être utilisé pour grouper certaines sortes d'actions logiquement liées. Imaginez un module TUserModule qui est utilisé pour traiter la gestion utilisateur dans les pages Web. Il peut y avoir de multiples actions associées avec un utilisateur :

  • Création
  • Suppression
  • Mise à jour
  • Affichage

Ces différentes actions peuvent être maniée par le mêm module. On peut déterminer l'action depuis l'URL manuellement, comme dans :

http://mysite/mycgi.cgi/user?action=delete&id=12

Cela peut être automatisé.

Afin de rendre plus facile la distinction entre les diverses actions, le module a une propriété actions : c'est une collection, dans laquelle chaque article est associé avec une réponse différente à la requête. Les actions ont diverses propriétés :

Name 
Le nom de l'action. L'URL sera examinée pour déterminer le nom de l'action.
Content 
Une chaîne de caractères. Si définie, c'est envoyé vers le navigateur.
Contents 
Une TStringList. c'est envoyé vers le navigateur.
ContentProducer 
Si définie, the ContentProducer maniera la requête.
Default
Si définie à True, alors cette action est l'action par défaut. Ceci signifie que si FCL-Web ne peut pas déterminer le nom de l'action, cette action sera exécutée.
Template 
Si définie, ce patron sera traité et les résultats envoyés vers le navigateur.

Il y a aussi quelques événements :

BeforeRequest 
exécuté avant que la requête ne soit traitée. Peut être utilisé pour définir le 'Content' ou d'autres propriétés.
AfterRequest 
exécuté après le traitement de la requête.
OnRequest 
un gestionnaire d'événement pour manier la requête. Si défini, le gstionnaire est utilisé pour manier la requête.

Encore une fois, comme dans le cas de plusieurs modules, l'URL est utilisée pour déterminer quelle action exécuter. La partie juste après la partie module ("utilisateur" dans cet exemple) est utilisée:

http://mysite/mycgi.cgi/user/delete&id=12

exécutera l'action nommée 'delete'.

La propriété ActionVar du module peut être utilisée pour définir le nom de la variable de requête à utiliser. En affectant :

UserModule.ActionVar := 'a';

peut être utilisé pour changer l'URL du dessus en :

http://mysite/mycgi.cgi/user?a=delete&id=12

S'il y a seulement un module dans l'application, l'URL peut être raccourci en :

http://mysite/mycgi.cgi/delete&id=12

Utilisation des patrons HTML

Pour de l'information au sujet des patrons (template), des étiquettes de patron (template tags) et des paramètres d'étiquettes de patron (template tag parameters) pour générer les pages de réponse, veuillez vous référer au fichier fptemplate.txt dans le répertoire FPC dans /packages/fcl-base/texts/ (NdT : spécifique Linux)

Des projets d'exemple qui démontrent l'utilisation des patrons peuvent être trouvés sous le répertoire FPC dans /packages/fcl-web/examples/fptemplate (voir le README.txt dedans pour plus).

(Dans les versions antérieures, ces exemples se trouvaient dans le répertoire Lazarus dans /components/fpweb/demo/fptemplate/)

Conseils & résolution de problèmes

Envoi des codes de retour

Pour envoyer une réponse HTTP différente de 200 OK, utiliser AResponse.Code et AResponse.CodeText, p.ex. :

AResponse.Code     := 404;
AResponse.CodeText := 'Document not found';

Envoi de données binaires

Une approche qui semble marcher pour envoyer p.ex. un fichier tiff depuis le serveur Web vers le client - adapté de $(fpcdirectory)\packages\fcl-web\examples\jsonrpc\demo1\wmdemo.pp - quelque chose comme ceci :

AResponse.ContentStream := TMemoryStream.Create;

try
  AResponse.ContentStream.LoadFromFile('/tmp/sample.tiff');
  AResponse.ContentType := 'image/tiff'; //or whatever MIME type you want to send
// to do: there is an fpweb example that gets the mime type from the file extension...
  AResponse.ContentLength:=AResponse.ContentStream.Size; //apparently doesn't happen automatically?
  AResponse.SendContent;
finally
  AResponse.ContentStream.Free;
end;

Handled := true;

Erreur: "Could not determine HTTP module for request"

Vous pouvez avoir de multiples modules et de multiples actions. Si vous spécifiez une URL avec un seul item, comme :

http://localhost/cgi-bin/somemodule

alors fpweb suppose que vous êtes en train de spécifier une action. Si vous n'avez pas défini un module par défaut, vous obtiendrez une "500 internal server error (Could not determine HTTP module for request)".

Vous pouvez modifier ce comportement pour permettre à fpweb de correspondre à un nom de module à la place en définissant la propriété PreferModuleName de l'application sur True.

Erreur: "response code 500 Internal Server error when trying to handle DELETE method"

Dans FPC 2.6.2 et antérieur, fcl-web n'accepte pas la méthode DELETE et génère une erreur.

fpWeb/FCGI et Apache 2.4 (mode mod_proxy_fcgi)

Quand vous voulez déployer une application FastCGI derrière un proxy inverse Apache 2.4+, vous avez besoin de la variable PATH_INFO dans les entêtes qui sont envoyés vai une socket au démon FastCGI.

1, Activer les modules suivants: setenvif_module, proxy_module et proxy_fcgi_module

(sur CentOS 7 modules sont définis dans le fichier /etc/httpd/conf.modules.d/00-base.conf et /etc/httpd/conf.modules.d/00-proxy.conf).

LoadModule setenvif_module   modules/mod_setenvif.so
LoadModule proxy_module      modules/mod_proxy.so
LoadModule proxy_fcgi_module modules/mod_proxy_fcgi.so

2, Configuration du proxy inverse pour fpWeb/FCGI écoutant sur le port 9000.
$1 = module name
$2 = action name

SetEnvIf Request_URI . proxy-fcgi-pathinfo=full
ProxyPassMatch "/fcgi/(.*)/(.*)" "fcgi://127.0.0.1:9000/$1/$2"

fpWeb/FCGI et nginx

Pour un routage correct, fcl-web requiert que la variable PATH_INFO dans les entêtes envoyés depuis nginx. Pour cela, vous devez diviser l'URL entière en nom d'application FastCGI et en partie information de chemin (path info) avec l'instruction de configuration fastcgi_split_path_info. L'instruction accepte une expression régulière et pose la seconde correspondance dans la variable de configuration $fastcgi_path_info. Cette variable peut être passée à votre application avec l'instruction fastcgi_param.

L'exemple de configuration suivante inclut un hôte virtuel complet pour nginx qui passe tout depuis http://myserver:8080/mycgiapp/ vers une application FastCGI externe.

server {

    listen      8080;
    listen      [::]:8080;

    server_name _;

    root    "/var/www";

    location /mycgiap/ {
        # setting up PATH_INFO
        fastcgi_split_path_info ^(/mycgiapp/)(.*)$;
        fastcgi_param  PATH_INFO          $fastcgi_path_info;

        # other parameters
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;
        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;
        fastcgi_param  REQUEST_SCHEME     $scheme;
        fastcgi_param  HTTPS              $https if_not_empty;
        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;
        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;

        # pass requests to your FastCGI application
        fastcgi_pass 127.0.0.1:9000;
    }
}

Notes

  • L'unité cgiapp est dépréciée, veuillez utiliser fpcgi autant que possible.
  • Les unités fastcgi, custfcgi et fpfcgi ne sont pas supportées sur Darwin en ce moment (Ndt: Qu'en est-il en 2020 ?), parce qu'il utilise un mécanisme qui différe de l'option MSG_NOSIGNAL pour recv() pour indiquer qu'aucun SIGPIPE ne doit être levé en cas de rupture de la connexion. Voir http://lists.apple.com/archives/macnetworkprog/2002/Dec/msg00091.html pour comment cela peut être fixé.
  • Si vous déployez votre application et obtenez des erreurs comme "Error: No action name and no default action", vous devrez vous assurer qu'il y a une action affectée à l'URL, ou intercepter les actions non supportées avec une action marquée Default. Dans les deux cas, un gestionnaire d'événement OnRequest pour l'action qui définit Handled:=true devrait être utilisé.

Voir aussi