HAProxy peut-il fonctionner en tant que serveur Web sans autre serveur Web (Apache, NGINX, par exemple)? On m'a dit pour une telle configuration, mais je ne suis pas sûr de l'exactitude des informations.
Non, HAProxy n'est pas un serveur Web et ne peut pas agir comme tel. À partir du Guide de démarrage HAProxy, Qu'est-ce qu'HAProxy est et n'est pas :
HAProxy n'est pas un serveur web:
Au démarrage, il s’isole dans une prison chroot et supprime ses privilèges, de sorte qu’il n’effectuera aucun accès au système de fichiers une fois démarré. En tant que tel, il ne peut pas être transformé en serveur Web. Il existe d'excellents logiciels open-source pour cela, tels qu'Apache ou Nginx, et HAProxy peut être installé devant eux pour fournir un équilibrage de charge et une haute disponibilité.
La réponse acceptée de "non, ce n'est pas fait pour cela" est correcte.
Mais le logiciel étant ce qu’il est, si vous voulez quand même le faire, il existe une solution de contournement.
Vous avez besoin d'une liste de contrôle d'accès pointant la demande vers un serveur personnalisé. Pour cet exemple, disons que vous vouliez servir un fichier robots.txt
frontend port80
acl is_robotstxt path /robots.txt
use_backend robots if is_robotstxt
backend robots
mode http
errorfile 503 /etc/haproxy/errors/robots.http
Notez qu'il n'y a pas de serveurs définis pour ce moteur, donc quand /robots.txt est demandé et qu'haproxy l'utilise, il génère une erreur 503. Nous spécifions que 503 erreurs doivent servir /etc/haproxy/errors/robots.http, qui, heureusement, spécifie les en-têtes de sortie HTTP complets et tous.
Donc, dans ce dossier, nous mettons
HTTP/1.0 200 Found
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
Content here
alors maintenant, ce qui devrait être une erreur 503 est en fait une réponse 200 Found, contenu et tout.
Notez que cela n'est pas vraiment recommandé et vient avec de nombreuses limitations. Le plus évident est que vous ne pouvez servir qu'un seul fichier de cette manière par serveur. Ce qui est moins évident, c'est que ce fichier doit tenir dans BUFSIZE de haproxy, qui est généralement de 8 ou 16 ko. Haproxy ne fait pas non plus de désinfection sur le fichier servi de cette façon, il vous incombe donc de servir les bons en-têtes de la bonne façon. Si vos clients ont besoin de\r\n au lieu de\n, c’est à vous de les gérer.
Vous feriez bien mieux de mettre en place une copie de votre serveur Web de choix et de simplement avoir un "backend d'actifs statique" que haproxy peut acheminer.
tout d’abord - et c’est important - HA-Proxy n’est pas un serveur Web. Cela devrait être très clair maintenant. Cependant, il existe des moyens de servir des fichiers via LUA. Je suis venu avec la solution suivante:
Configuration HA-Proxy:
lua-load /etc/haproxy/lua/load-file.lua
...
backend lua-load-file
http-request set-header X-LUA-LOADFILE-DOCROOT /etc/haproxy/docroot
http-request use-service lua.load-file
Comme vous pouvez le voir, je charge un fichier Lua appelé load-file.lua. Le contenu de ce fichier est le suivant:
core.register_service("load-file", "http", function(applet)
local docroot
local location
local file
local retval
local response
local extension
if(applet.path == nil or applet.headers["x-lua-loadfile-docroot"] == nil or applet.headers["x-lua-loadfile-docroot"][0] == "") then
retval = 500
response = "Internal Server Error"
else
docroot = applet.headers["x-lua-loadfile-docroot"][0]
location = applet.path
if(location == "" or location == "/") then
location = "/index.html"
end
file = io.open(docroot .. location, "r")
if(file == nil) then
retval = 404
response = "File Not Found"
else
retval = 200
response = file:read("*all")
file:close()
end
end
extension = string.match(location, ".(%w+)$")
if extension == "css" then applet:add_header("content-type", "text/css")
elseif extension == "gif" then applet:add_header("content-type", "image/gif")
elseif extension == "htm" then applet:add_header("content-type", "text/html")
elseif extension == "html" then applet:add_header("content-type", "text/html")
elseif extension == "ico" then applet:add_header("content-type", "image/x-icon")
elseif extension == "jpg" then applet:add_header("content-type", "image/jpeg")
elseif extension == "jpeg" then applet:add_header("content-type", "image/jpeg")
elseif extension == "js" then applet:add_header("content-type", "application/javascript; charset=UTF-8")
elseif extension == "json" then applet:add_header("content-type", "application/json")
elseif extension == "mpeg" then applet:add_header("content-type", "video/mpeg")
elseif extension == "png" then applet:add_header("content-type", "image/png")
elseif extension == "txt" then applet:add_header("content-type", "text/plain")
elseif extension == "xml" then applet:add_header("content-type", "application/xml")
elseif extension == "Zip" then applet:add_header("content-type", "application/Zip")
end
applet:set_status(retval)
if(response ~= nil and response ~= "") then
applet:add_header("content-length", string.len(response))
end
applet:start_response()
applet:send(response)
end)
Fondamentalement, ce code lit les fichiers depuis un emplacement de racine de document spécifié dans le système de fichiers en fonction de la chaîne de requête et génère les réponses HTTP appropriées, comme le ferait un serveur Web normal. C'est pourquoi le script a besoin d'une racine de document qui doit être configurée via l'en-tête HTTP X-LUA-LOADFILE-DOCROOT. Cet en-tête est défini via la configuration haproxy, comme indiqué dans les exemples. En outre, le code gère également des types de base de types MIME très élémentaires - étendez la liste selon vos besoins. J'espère que quelqu'un trouvera cela utile.
à votre santé!