Objectif

J’ai présenté dans un précédant billet comment mettre en œuvre un serveur web WSAPI-Xavante. L’objectif de ce billet est de présenter plus en détail la mise en œuvre d’une fonction permettant de répondre à une requête de type GET ou POST en s’appuyant sur la librairie WSAPI.
L’intérêt d’utiliser WSAPI est de bénéficier de librairies facilitant l’interprétation de la requête ainsi que la génération et la bufferisation de la sortie.
Site web du tutoriel
---------------------------------------------------------------- -- Exemple de mise en oeuvre de WSAPI et Xavante (tuto03.lua) -- ---------------------------------------------------------------- local xavante = require("xavante") local wsx = require("wsapi.xavante") local wsr = require("wsapi.request") -- Formatage sous forme de chaîne de caractères du contenu d'une variable local function tostr(variable, indent) local str = "" indent = indent or "" local incindent = " " if (type(variable) ~= "table") then if (type(variable) == "string") then str = string.format("%q", variable) else str = tostring(variable) end else local separateur = "" for i, v in pairs(variable) do str = str .. separateur separateur = ", \n" if(type(i) == "number") then str = str .. indent .. incindent .. tostr(v, indent .. incindent) else str = str .. indent .. incindent .. tostr(i, indent .. incindent) .. " = " .. tostr(v, indent .. incindent) end end str = "{\n" .. str .. "\n" .. indent .. "}" end return str end -- La fonction WSAPI permettant de répondre à des requêtes GET ou POST function fonctionWSAPI(wsapi_env) local req = wsr.new(wsapi_env) local headers = { ["Content-type"] = "text" } local function fonction() coroutine.yield(string.format("\nwsapi_env = %s\n", tostr(wsapi_env))) coroutine.yield(string.format("\nreq = %s\n\n", tostr(req))) end return 200, headers, coroutine.wrap(fonction) end local mesRegles = { { -- Gestionnaire de fonction WSAPI (http://localhost:8080/fwsapi) match = { "/fwsapi$", "/fwsapi/"}, with = wsx.makeHandler(fonctionWSAPI) }, } -- Message de départ xavante.start_message( function(ports) local date = os.date("[%Y-%m-%d %H:%M:%S]") print(string.format("%s Xavante started on port(s) %s", date, table.concat(ports, ", "))) end ) -- Configuration xavante.HTTP{ server = { host = "*", port = 8080 }, defaultHost = { rules = mesRegles }, } -- Démarrage (Dans un terminal : wsapi -c tuto03.lua -p 8080) xavante.start() -- curl --data "pname1=pvalue1&pname2=pvalue2" "http://localhost:8080/fwsapi/path1?gname1=gvalue1&gname2=gvalue2" -- curl -H "content-type: text/plain" --data "Données en POST" "http://localhost:8080/fwsapi" |
Le résultat
Bien entendu, la première étape consiste à lancer le serveur web : wsapi -c tuto03.lua -p 8080
Dans le code ci-dessus, la fonction fonctionWSAPI(wsapi_env)
traite les informations des requêtes GET ou POST.
On peut tester une requête POST sur cette fonction en saisissant dans un terminal la commande suivante :
curl --data "pname1=pvalue1&pname2=pvalue2" "http://localhost:8080/fwsapi/path1?gname1=gvalue1&gname2=gvalue2" |
wsapi_env = { "SCRIPT_NAME" = "", "QUERY_STRING" = "gname1=gvalue1&gname2=gvalue2", "APP_PATH" = "", "HTTP_COOKIE" = "", "CONTENT_LENGTH" = "29", "CONTENT_TYPE" = "application/x-www-form-urlencoded", "DOCUMENT_ROOT" = "", "input" = { "length" = 29, "read" = function: 0xc852a0 }, "PATH_INFO" = "/fwsapi/path1", "error" = file (0x7f5f13d711c0), "REQUEST_METHOD" = "POST" } req = { "method" = "POST", "query_string" = "gname1=gvalue1&gname2=gvalue2", "app_path" = "", "GET" = { "gname2" = "gvalue2", "gname1" = "gvalue1" }, "env" = { "SCRIPT_NAME" = "", "QUERY_STRING" = "gname1=gvalue1&gname2=gvalue2", "APP_PATH" = "", "HTTP_COOKIE" = "", "CONTENT_LENGTH" = "29", "CONTENT_TYPE" = "application/x-www-form-urlencoded", "DOCUMENT_ROOT" = "", "input" = { "length" = 29, "read" = function: 0xc852a0 }, "PATH_INFO" = "/fwsapi/path1", "error" = file (0x7f5f13d711c0), "REQUEST_METHOD" = "POST" }, "path_info" = "/fwsapi/path1", "cookies" = { }, "script_name" = "", "POST" = { "pname1" = "pvalue1", "pname2" = "pvalue2" }, "parse_post" = function: 0xc86050, "doc_root" = "", "params" = { } } |
On peut voir que les parties GET et POST ont été correctement décomposées ce qui facilite leur manipulation.
WSAPI se base sur le champ wsapi_env.CONTENT_TYPE
pour savoir comment interpréter le POST. Trois cas de figure sont à distinguer :
wsapi_env.CONTENT_TYPE
contient la chaînex-www-form-urlencoded
;wsapi_env.CONTENT_TYPE
contient la chaînemultipart/form-data
;- les autres cas.
Dans les deux premiers cas WSAPI interprète le POST. Si ce dernier est mal formaté, on n’obtient rien (le POST est perdu), ou pire, une erreur d’exécution peut survenir. Dans le troisième cas, WSAPI retourne le POST de manière littérale :
curl -H "content-type: text/plain" --data "Données en POST" "http://localhost:8080/fwsapi" |
wsapi_env = { "SCRIPT_NAME" = "", "QUERY_STRING" = "", "APP_PATH" = "", "HTTP_COOKIE" = "", "CONTENT_LENGTH" = "16", "CONTENT_TYPE" = "text/plain", "DOCUMENT_ROOT" = "", "input" = { "length" = 16, "read" = function: 0x20f2a80 }, "PATH_INFO" = "/fwsapi", "error" = file (0x7f9cdea011c0), "REQUEST_METHOD" = "POST" } req = { "method" = "POST", "query_string" = "", "app_path" = "", "GET" = { }, "env" = { "SCRIPT_NAME" = "", "QUERY_STRING" = "", "APP_PATH" = "", "HTTP_COOKIE" = "", "CONTENT_LENGTH" = "16", "CONTENT_TYPE" = "text/plain", "DOCUMENT_ROOT" = "", "input" = { "length" = 16, "read" = function: 0x20f2a80 }, "PATH_INFO" = "/fwsapi", "error" = file (0x7f9cdea011c0), "REQUEST_METHOD" = "POST" }, "path_info" = "/fwsapi", "cookies" = { }, "script_name" = "", "POST" = { "post_data" = "Données en POST" }, "parse_post" = function: 0x2138570, "doc_root" = "", "params" = { } } |
Références
GitHub : keplerproject/xavante
GitHub : keplerproject/wsapi
Wikipedia : Type MIME
Billet sur ce blog : WSAPI et Xavante : serveur Web Lua
Sommaire Domotique sur ce blog