Xavante : Handler de type fonction WSAPI

Objectif

wsapi

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 :

  1. wsapi_env.CONTENT_TYPE contient la chaîne x-www-form-urlencoded ;
  2. wsapi_env.CONTENT_TYPE contient la chaîne multipart/form-data ;
  3. 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

Cette entrée a été publiée dans Domotique, Tutoriels, Eloise and taguée . Placez un signet sur le permalien.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *