Introduction à Flask, le micro système maousse costaud

Magazine
Marque
GNU/Linux Magazine
Numéro
166
|
Mois de parution
décembre 2013
|
Domaines


Résumé
Je sais pas pour vous, mais moi, le clicka-web, ça m'ennuie. J'éprouve un profond respect pour ces génies de l'ergnonomie qui arrivent à produire des interfaces comme GitHub ou Twitter, truffées d'Ajax/jQuery[1], super inuitives, rapides et branchées sur des systèmes d'information ultra-complexes. Récemment, j'ai eu à produire une interface de gestion de déploiement de services au sein d'un parc de machines virtuelles. Cette interface devait se brancher sur un Web-service et s'interconnecter aux mécanismes d'orchestration Fabric[2] et Salt[3], tous deux en Python. Afin de garder une certaine cohérence dans le choix des langages, j'ai finalement jeté mon dévolu sur Flask[4], le “micro framework” qui m'a fait aimer développer du clicka-web.

Body

1. C'est mou ?

Flask est décrit comme un “microframework” en Python, il est basé sur Werkzeug pour la partie serveur / WSGI[6] et sur Jinja 2[7] pour le templating. Pour ne rien gâcher, Flask, ainsi que ses dépendances précédemment citées, sont sous licence BSD.
 Puisque Flask s'appuie sur Werkzeug, il est en mesure de fonctionner de façon autonome, sans l'aide d'un serveur WSGI tiers. C'est cette méthode que nous allons utiliser au début de cet article afin de rapidement mettre le pied à l'étrier, nous verrons plus tard comment configurer le serveur uWSGI[8] de façon à disposer d'une installation prête pour la production.

Flask est disponible dans la plupart des systèmes de paquets de vos UNIX-like favoris, mais nous choisirons ici d'utiliser la version disponible via pip, ainsi nous manipulerons la dernière version en date, la 0.10 :

$ pip install Flask

Munis du framework, nous allons pouvoir écrire notre première application Flask :

$ cat glmf.py
from flask import Flask
app = Flask(__name__)
@app.route(‘/’)
def glmf_rules():
return ‘GLMF rules!\n’
if __name__ == ‘__main__’:
app.run()

Dans ce minuscule bout de code, après avoir importé puis instancié la classe Flask, nous utilisons le décorateur @app.route de façon à définir l'URL qui sera gérée par la fonction à suivre, ici, nous prenons en charge la racine du site. Comme on peut s'en douter, l'application basique que nous avons écrite répondra «GLMF rules!» lorsqu'elle sera interrogée sur l'URL déclarée. Finalement, lorsque le présent script est appelé par une application tierce, nous invoquons la fonction run() qui démarrera le serveur Web qu'embarque Flask.

On commence par démarrer le service :

$ python glmf.py
* Running on http://127.0.0.1:5000/
127.0.0.1 - - [20/Jul/2013 10:51:47] "GET /
HTTP/1.1" 200 -

Et on teste simplement l'URL définie :

$ curl -o- -s http://localhost:5000/
GLMF rules!

Nous constatons que, sans plus de paramètres passés à la fonction run(), Flask écoute sur l'interface loopback, pour modifier ce comportement, il suffit de passer un paramètre host :

if __name__ == ‘__main__’:
app.run(host=’0.0.0.0’)

Ici, l'application écoutera sur l'ensemble des interfaces réseau du système. Afin de déboguer efficacement notre application, il est également possible de passer un paramètre debug à la fonction run() :

if __name__ == ‘__main__’:
app.run(host=’0.0.0.0’, debug=True)

Ce qui aura pour effet de proposer une fenêtre de débogage interactive utilisable depuis un navigateur. Il est possible, à travers la fonction route(), de passer des arguments possiblement typés à une fonction associée à une URL :

@app.route(‘/<mag>’)
def glmf_rules(mag):
return ‘{0} rules!\n’.format(mag)

Et de tester :

$ curl -o- -s http://localhost:5000/GLMF%20
Le%20Meilleur%20Mag%20De%20La%20Galaxie
GLMF Le Meilleur Mag De La Galaxie rules!

2. Des serpents dans mon Web 2.0

Muni de ces basiques concepts, nous allons maintenant découvrir les fonctionnalités qui font la force de Flask, en particulier comment produire une véritable page Web dynamique en un temps record.

La fonction route() utilisée dans les décorateurs de fonctions accepte le paramètre methods, c'est à travers ce dernier que l'on pourra choisir, au sein de la fonction, l'action à mener lorsqu'on atterrit sur l'URL déclarée. On passe au paramètre methods un tableau contenant la liste des méthodes supportées par la fonction :

@app.route(‘/’, methods=[‘GET’, ‘POST’])

On choisit ensuite l'action à mener grace à la variable request.method. L'objet global request devra être importé, comme l'objet Flask :

from flask import Flask, request
@app.route(‘/)
def entree():
if request.method == ‘GET’:
return fais_des_trucs()
else:
return fais_d_autres_trucs()

L'objet request, comme on peut s'en douter, regroupe les informations relatives à la requête effectuée, par exemple on accède aux paramètres passés via la méthode GET à l'aide de request.args.get :

def test():
return ‘{0}\n’.format(request.args.get(‘foo’))
...
$ curl -o- -s http://localhost:5000/?foo=bar
bar

Ou encore aux valeurs d'un formulaire en appelant request.form['champs'], nous reviendrons sur cette fonctionnalité plus tard.

3. Structure d'un projet Flask

Un projet Flask typique consiste en l'arborescence suivante :

|-- gmlf.py
|-- static
| |-- style.css
`-- templates
|-- layout.html
`-- site.html

À la racine du projet on trouve le ou les fichiers Python moteur de l'application, un repertoire static qui, comme son nom l'indique, regroupe les fichiers statiques utilisés, et un répertoire template contenant les templates au format Jinja 2 qui seront utilisés pour générer des pages HTML de façon simple et intuitive.

C'est cette capacité que nous allons explorer immédiatement, afin de rapidement s'apercevoir du potentiel de ce microframework.

3.1 Templates

Il serait évidemment extrêmement fastidieux d'écrire l'intégralité du code HTML au sein du moteur lui même, aussi, la pierre angulaire du rendu de pages passe par l'écriture de simples templates qui savent récupérer des variables, voire des fonctions, issues du moteur de l'application. Créons pour l'occasion un template simpliste qui affichera dans une page HTML correctement formatée l'argument passé au paramètre foo via la méthode GET :

$ cat templates/main.html
<!doctype html>
<title>En voila une belle page</title>
Valeur de foo: {{ foo }}
$ cat glmf.py
from flask import Flask, request, render_
template
app = Flask(__name__)
@app.route(‘/’)
def test():
return render_template(‘main.html’,
foo=request.args.get(‘foo’))
if __name__ == ‘__main__’:
app.run(debug=True)

On remarquera l'import d'un nouvel objet render_template, qui très naturellement est l'objet utilisé pour réaliser le rendu du template Jinja. L'appel à la fonction associée est limpide, on passe en premier paramètre le nom du template, puis ensuite la liste des paramètres que l'on souhaite manipuler au sein du template, ici uniquement la variable foo à laquelle on affecte le contenu du paramètre passé en GET. On vérifie simplement le bon fonctionnement du mécanisme :

$ curl -o- -s http://localhost:5000/?foo=bar
<!doctype html>
<title>En voila une belle page</title>
Valeur de foo: bar

Ceux d'entre vous ayant fait l'acquisition du GNU/Linux Magazine hors série sur Python le savent probablement déjà, Jinja 2 propose une panoplie d'outils bien plus puissants que le simple affichage de variables passées au template, en l'occurrence, nous bénéficions ici d'un mini-langage de programmation muni entre autres de boucles, conditions et opérations sur chaînes basiques. Modifions notre exemple en ce sens :

$ cat templates/main.html
<!doctype html>
<title>En voila une belle page</title>
{% if foo %}
Valeur de foo: {{ foo }}
{% else %}
J’ai rien dans foo, par contre, j’ai :
{% for arg in request.args %}
- {{ arg }} qui contient {{ request.args.get(arg) }}
{% endfor %}
{% endif%}
...
$ curl -o- -s "http://localhost:5000/?fox=bar&foy=baz"
<!doctype html>
<title>En voila une belle page</title>
J’ai rien dans foo, par contre, j’ai :
- fox qui contient bar
- foy qui contient baz

Ah oui là tout de suite ça cause un peu plus. Comme on peut le voir, nous avons un accès total à l'objet request depuis le template Jinja en plus de la variable explicitement passée. Dans ce template nous testons l'existence d'une variable et bouclons sur les différents paramètres “GET” disponibles à travers l'objet request, une belle liste de possibilités en perspective…

3.2 Fichiers statiques

Nous l'avons vu, un projet Flask peut contenir dans son arborescence un repertoire static, ce dernier contiendra par exemple des fichiers JavaScript, CSS ou encore des fichiers média. Il sera de bon ton de ne pas simplement déclarer un fichier statique via son chemin relatif ou absolu dans le template mais d'utiliser plutôt la fonction url_for(), qu'il conviendra d'importer également dans l'application :

$ head -1 glmf.py
from flask import Flask, request, render_template, url_for
...
$ head -3 templates/main.html
<!doctype html>
<title>En voila une belle page</title>
<link rel=stylesheet type=text/css href="{{ url_for(‘static’,
filename=’style.css’) }}">

Le mot clé static, passé à la fonction url_for est défini par Flask, cependant, url_for() est utilisable à souhaits tant dans le code de l'application que dans les templates, cette fonction très pratique renvoie simplement l'URL à laquelle correspond une fonction, soit donc la route associée.

4. Et maintenant, on mélange

Pour se familiariser avec les notions que nous venons de découvrir, nous allons réaliser un minuscule formulaire qui pourrait servir de page d'authentification simple d'un système d'information. Le moteur Jinja 2 permet l'utilisation de blocks, ce qui permet d'écrire des templates minimaux qui viendront s'imbriquer les uns aux autres. Voici par exemple une structure générique qui accueillera l'ensemble des blocks spécifiques :

$ cat templates/layout.html
<!doctype html>
<title>Bienvenue, visiteur du futur !</title>
<link rel=stylesheet type=text/css href="{{ url_for(‘static’,
filename=’style.css’) }}">
<div class="page">
{% block body %}{% endblock %}
</div>

Ici, les directives {% block body %}{% endblock %} indiquent où pourra se raccrocher un block fils qui portera le nom body. Dans notre cas, login.html aura la forme suivante :

$ cat templates/login.html
{% extends "layout.html" %}
{% block body %}
<h2>Identification</h2>
<hr>
<form method="POST" action="/">
<label>Utilisateur</label><br />
<input type="text" name="user" id="user"><br />
<label>Mot de passe</label><br />
<input type="password" name="passwd" id="passwd"><br />
<input type="submit" name="action" value="login">
</form>
{% endblock %}

Le formalisme de ce template est assez explicite, on étend le template layout.html avec un block nommé body, que Jinja identifiera comme étant à insérer dans le block du même nom. Maintenant que nous disposons de nos templates de base, passons au code Python de l'application :

from flask import Flask, request, render_template, url_for, \
session, redirect, abort
app = Flask(__name__)
app.secret_key = ‘la cle en toc’
lps = { ‘imil’: ‘passpourri’, ‘jeanclaude’: ‘tergal’, ‘pascal’:
‘brutal’ }
@app.route(‘/welcome’)
def welcome():
if ‘user’ in session:
return "Identification reussie, {0} !\n".format(session[‘user’])
else:
return "Dehors, manant\n"
@app.route(‘/’, methods=[‘GET’, ‘POST’])
def login():
if request.method == ‘POST’:
for u in lps.keys():
if u == request.form[‘user’] and lps[u] == request.form[‘passwd’]:
session[‘user’] = request.form[‘user’]
return redirect(url_for(‘welcome’))
return abort(401)
else:
return render_template(‘login.html’)
if __name__ == ‘__main__’:
app.run(debug=True)

Quelques explications s'imposent. Nous importons en premier lieu trois nouveaux objets :

- session contiendra des éléments de session propres à l'utilisateur, nous nous contenterons d'y stocker le nom de l'utilisateur ayant réussi son identification. Comme il est évidemment nécessaire de sécuriser cette session et les informations qu'elle transporte, il est impératif de déclarer une clé secrète au sein de l'application.

- redirect permet de rediriger la navigation à travers un code HTTP 302.

- abort stoppe toute activité de navigation en envoyant un code de retour au navigateur.

Comme cela est nécessaire dans un contexte de session, nous plaçons une clé secrète dans la variable app.secret_key. Suite à quoi, pour les besoins de ce test basique, nous codons en dur quelques utilisateurs dans un dictionnaire Python. Ces prérequis honorés, nous déclarons une fonction qui n'aura pour seul but que de signaler à l'utilisateur qu'il a réussi son identification en vérifiant si le nom login est bien présent dans la session en cours.

login-shot

Le vrai travail s'effectue dans la fonction d'entrée, login, déclarée comme la racine du “site”. S'il s'agit d'une requête de type POST, et donc qu'il s'agit très certainement du résultat de notre formulaire dûment rempli, nous parcourons l'ensemble des couples utilisateur / mots de passe du dictionnaire lps. Si l'un des couples correspond aux valeurs passées dans le formulaire et récupérées via request.form, nous déclarons l'utilisateur dans la session courante, puis le redirigeons sur la route qui tient la fonction welcome qui lui affichera un message de bienvenue. Si l'utilisateur n'est pas reconnu, nous utiliserons la fonction abort qui renverra le code HTTP de retour passé en paramètre, ici 401, code classiquement utilisé pour signifier un échec d'authentification.

Évidemment, il est non seulement possible mais largement conseillé d'utiliser des méthodes d'authentification autrement plus sophistiquées, et il existe pour cela un module Flask tout trouvé répondant au nom de Flask-login[9]. J'ai moi-même utilisé ce module pour les besoins de notre système de déploiement et couplé à ce dernier le module simpleldap[10], un exemple d'utilisation prêt à l'emploi de ce combo est visible sur mon blog[11].

5. Allez, on met en prod

Si l'utilisation du moteur HTTP Werkzeug embarqué dans Flask rend très pratique la phase de débogage, il est évidemment hors de question de reposer sur un système démarré “à la main” en production. Nous nous appuierons sur deux briques connues et robustes pour diffuser notre application sur le réseau: nginx et uWSGI.

Le fâmeux serveur HTTP nginx dispose en effet d'une fonctionnalité lui permettant de s'adresser à un serveur WSGI, la seule configuration requise est la suivante :

location / {
include uwsgi_params;
uwsgi_pass unix:///var/run/uwsgi/app/
gmlf/socket;
}

Ces quatre lignes sont à placer dans le virtual host de votre choix au sein de la configuration du serveur nginx. Le chemin déclaré pour la directive uwsgi_pass est variable selon l'installation de uWSGI réalisée par votre distribution et/ou UNIX-like favori, dans le cas présent il s'agit d'une machine Debian GNU/Linux. J'ai choisi ici d'utiliser une socket UNIX mais il est bien sûr également possible de communiquer avec le serveur WSGI sur une socket TCP.

La configuration du serveur WSGI uWSGI, sur une machine Debian, requiert la création d'un fichier .ini dans le répertoire /etc/uwsgi/apps-available puis un lien logique du fichier créé dans /etc/uwsgi/apps-enabled/ :

$ cat /etc/uwsgi/apps-available/glmf.ini
[uwsgi]
workers = 2
log-date = true
plugins = python
chdir = /var/www/glmf
module = gmlf
callable = app

Où :

- workers représente le nombre de processus uWSGI démarrés,

- log-date demande de préfixer les lignes de logs par la date,

- plugins demande le chargement du plugin Python,

- chdir change le repertoire de travail à la valeur assignée,

- module est le nom du module à charger,

- callable donne le nom de l'application WSGI à appeler par défaut.

Il n'est pas rare de lire les fichiers .ini uWSGI concaténant module et callable de cette façon :

module = gmlf:app

Une fois les deux serveurs configurés, il ne nous reste plus qu'à les (re-)démarrer, ce qui nous donne chez Debian :

$ sudo /etc/init.d/uwsgi restart
$ sudo /etc/init.d/nginx restart

Cette fois, notre application écoute, à travers nginx, sur le port 80 (si ce dernier à été configuré ainsi) et dispose d'un système de gestion de service digne de ce nom. À nous la prod !

6. Il est pourri ton Web 2.0 mec...

Oui, bon, ok, ça fait pas encore des animations au chargement et ça autocomplète pas les champs, mais ne jugez pas trop vite, car Flask coopère nativement parfaitement avec des bibliothèques comme jQuery, en effet, à l'aide de la fonction jsonify(), il est aisé de déclarer des routes spécialement dédiées à répondre à des appels AJAX et ainsi remplir «automagiquement» un drop-down menu ou encore pré-remplir des listes afin de proposer des champs disposant de fonctions d'autocomplete. Ajoutons à cela plus de 250 plugins permettant d'interfacer à peu près n'importe quoi, après avoir passé quelques heures à manipuler ce soit-disant microframework et quelques-unes de ses extensions, on s'aperçoit que ses possibilités sont à la mesure de son accessibilité.

Références

[1] http://jquery.com/

[2] http://docs.fabfile.org/en/1.6/

[3] http://saltstack.com/community.html

[4] http://flask.pocoo.org/

[5] http://werkzeug.pocoo.org/

[6] http://fr.wikipedia.org/wiki/Web_Server_Gateway_Interface

[7] http://jinja.pocoo.org/

[8] http://uwsgi-docs.readthedocs.org/en/latest/

[9] https://flask-login.readthedocs.org/en/latest/

[10] https://pypi.python.org/pypi/simpleldap

[11] http://imil.net/wp/2013/07/06/ldap-flask-login-snippet/


Sur le même sujet

À nous, Markdown !

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
109
|
Mois de parution
juillet 2020
|
Domaines
Résumé

Le Markdown est devenu incontournable. Il est facilement manipulable, stockable, versionnable et partageable. Un moteur de rendu automatique peut transformer toute la substantifique moelle de l’auteur en un ouvrage broché digne de la Bible de Gutenberg. Alors, pourquoi ne pas appliquer ce modèle à l’écriture de nouveaux articles pour notre cher magazine ?

Gesturefy : utilisez la navigation « gestuelle » pour gagner en rapidité

Magazine
Marque
Linux Pratique
Numéro
120
|
Mois de parution
juillet 2020
|
Domaines
Résumé

Voilà un module original à ajouter à votre navigateur web : Gesturefy va en effet vous permettre de personnaliser votre navigation en configurant des gestes à réaliser à l’aide de votre souris, le but étant évidemment de vous permettre de gagner en rapidité lors de vos explorations sur le Web.

L’exponentielle : sa vie, son œuvre

Magazine
Marque
GNU/Linux Magazine
Numéro
239
|
Mois de parution
juillet 2020
|
Domaines
Résumé

L’exponentielle est au cœur de nombreuses méthodes dans le domaine de la data science, et nous avons connu ces derniers mois ses effets très directement à travers la propagation du SARS-Cov-2.

Interactions dans un environnement 3D

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
109
|
Mois de parution
juillet 2020
|
Domaines
Résumé

Pour interagir avec des éléments 3D, il va falloir créer un environnement 3D et connecter les objets à du code GDScript pour effectuer diverses actions. La partie la plus importante sera la modélisation 3D en utilisant l'IDE fourni par Godot.

Utilisez tout le potentiel de l'interface d'administration Django

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
109
|
Mois de parution
juillet 2020
|
Domaines
Résumé

Django est le socle d’applications bâti au-dessus d’une base de données relationnelle qui est le plus populaire en Python. C’est d’ailleurs l’un des plus demandés sur le marché du travail, pour ceux qui souhaitent faire du Python.L’objectif de cet article est de présenter son interface d’administration et la manière de la personnaliser.

Partagez vos fichiers volumineux facilement et de manière sécurisée avec Firefox Send

Magazine
Marque
Linux Pratique
Numéro
120
|
Mois de parution
juillet 2020
|
Domaines
Résumé

Firefox Send est un service de Mozilla de partage de fichiers en ligne. Pour des utilisateurs non techniques, qui ne sauraient pas utiliser un serveur FTP ou tout autre partage réseau, c’est une très bonne alternative web pour mettre en ligne des fichiers volumineux de manière simple. Il existe déjà de nombreux services similaires, parfois gratuits et souvent propriétaires. Dans cet article, nous allons voir comment utiliser ce service pour partager de manière sécurisée vos fichiers, et surtout pour héberger votre instance.

Par le même auteur

Amazon <3 Linux

Magazine
Marque
GNU/Linux Magazine
Numéro
207
|
Mois de parution
septembre 2017
|
Domaines
Résumé
Qui d'entre vous n'a jamais entendu parler de AWS (Amazon Web Services), LE cloud public qui domine le marché, la panacée du DevOps, le destructeur de toute une industrie, l'hébergeur qui soutient désormais un bon 40% du Web mondial ? Si tu réponds « moi » à cette question, tu devrais visiter autre chose que des sites en HTML v2 et cesser d’éditer tes fichiers de conf à la main.La triple pique d'entrée de jeu c'est gratos, ça me fait plaisir. AWS, c'est le rouleau compresseur, et cette position de leader n'est pas liée à la chance, puisque comme nombre de solutions disruptives, les analystes les plus pointus proféraient à son lancement que « ça marchera jamais » ©®™ ; non, le succès de ce cloud réside en grande partie dans son API, ses outils, le plus souvent libres, et la puissante communauté qui s'est construite autour. Ce que je vous propose dans cet article, c'est de faire connaissance avec ces outils, et en particulier l'AWS cli [1] basée sur boto3[2], tous les deux sous licence Apache 2[3].

Des bits comme s'il en pleuvait : une appliance SAN/NAS sous NetBSD

Magazine
Marque
GNU/Linux Magazine
Numéro
181
|
Mois de parution
avril 2015
|
Domaines
Résumé
À Noël, je suis le désespoir de ma famille. En effet, là où d'autres demandent des Blu-ray, de quoi s'habiller en hiver ou encore une nouvelle poêle à frire, moi je demande des composants. Des disques, des cartes, des trucs super pas excitants pour les personnes qui vous les offrent. Cette année, je voulais plus de place sur mon NAS [1], plein de bits pour y coller des documents à haute teneur multimédia.

NetBSD, le système du futur du subjonctif

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
74
|
Mois de parution
septembre 2014
|
Domaines
Résumé
« The Original UNIX », c'est pour cette punchline que j'avais voté lorsque le groupe chargé du marketing chez NetBSD cherchait une approche différente du classique « of course it runs NetBSD » ; néanmoins, s'il est l'héritier le plus direct des travaux du CSRG [1] et l'un des plus grands défenseurs de la portabilité du code, le projet NetBSD n'est certainement pas un système d'exploitation du passé, loin s'en faut. Bénéficiant des avancées standards d'autres OS, NetBSD dispose en outre d'avantages uniques dont l'administrateur système aguerri saura faire usage. Dans cet article, nous allons monter un serveur web articulé autour de briques modernes, et allons dans notre périple découvrir l'ensemble des éléments nécessaires au déploiement d'un système aussi réactif que respectueux des standards.

Préface

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
74
|
Mois de parution
septembre 2014
|
Résumé

Huit ans. Huit ans se sont écoulés depuis les deux derniers numéros hors-séries BSD et le mook que vous tenez entre les mains. Il y a huit ans, il est probable qu'une bonne partie d'entre vous n'avait même jamais touché un système UNIX/Linux, et réalisait plutôt son grand œuvre Lego(c)(tm).

Pendant ces huit années, le monde du Libre a proprement explosé, il est partout, omniprésent sur vos mobiles, vos tablettes, votre télé ou votre point d'accès Wi-Fi ; et si des sociétés telles que Google ne se cachent pas d'utiliser le système GNU/Linux comme socle entre l'espace utilisateur et le matériel, d'autres, sans totalement le masquer, ne font pas étalage des technologies libres constituant la pierre angulaire de leurs systèmes. En tête de liste notons particulièrement la société Apple, dont l'espace utilisateur du système d'exploitation Mac OS X est directement issu de FreeBSD.

Les différents BSD

Magazine
Marque
GNU/Linux Magazine
HS n°
Numéro
74
|
Mois de parution
septembre 2014
|
Domaines
Résumé

« Salut, je voudrais installer *BSD, vous me conseillez quoi ? »Cette phrase, lue et relue des centaines, des milliers de fois, est fondamentalement incorrecte. *BSD n'existe pas. Plus important, lorsque l'on souhaite mettre le pied à l'étrier d'un système BSD, un minimum de contexte est nécessaire, car chacun des héritiers de BSD UNIX suit une philosophie bien définie, et si chacun d'entre eux s'avère éminemment versatile, certains seront plus adaptés et faciles d'accès fonction de l'utilisation souhaitée. Nous allons ici faire connaissance avec les trois systèmes BSD les plus connus, NetBSD, FreeBSD et OpenBSD et évoquer leurs forces et faiblesses afin de guider votre choix de façon la plus objective possible.

Jouons un peu (plus) avec nginx

Magazine
Marque
GNU/Linux Magazine
Numéro
172
|
Mois de parution
juin 2014
|
Domaines
Résumé
Il existe pour le serveur web / proxy inverse nginx une foule de modules tierce partie, à ajouter au besoin, pas encore intégrés upstream mais pourtant de très bonne facture. Parmi les auteurs de ces modules, il en est un qui sort du lot par la quantité mais surtout la qualité de ses contributions, il s'agit de Yichun Zhang, plus connu sous son pseudo : agentzh.