• Open-Source (licença BSD) …com suporte comercial • Corre em Linux, FreeBSD, etc. …em Windows não está production-ready • Existe há mais de 10 anos …com um nível crescente de utilização ** www.kegel.com/c10k.html! * nginx.org! milhão de sites mais ac.vos (Netcra4, Abril de 2015)
(mainline) 1.6.x (stable) 1.5.x (mainline) • Ambos os branches são usáveis em produção …mas a versão stable é mais previsível (só correcções importantes) • Ambos têm repositórios de pacotes binários standard para Linux …que costumam ser rapidamente actualizados após cada release
para usos avançados …orientada para scripting embebido • Implementação minimalista, rápida e universal …menos de 200 KB para a totalidade do runtime standard* …com o LuaJIT** como alternativa ainda mais rápida • Open-Source (licença MIT) …sem restrições à integração em software proprietário • Mais de 20 anos de existência …com uma grande (mas pouco visível) base de utilização — ** luajit.org! * www.lua.org!
5.2 (Dez. 2011) 5.1.5 (Fev. 2012) 5.1 (Fev. 2006) • Desenvolvimento contínuo de novas funcionalidades …as versões mais antigas só recebem correcções • A versão 5.1 continua a ser a mais popular …porque é a especificação implementada pelo LuaJIT
1, x) -‐-‐ true false nil if "" and 0 and {} then print("ok") end -‐-‐ só nil e false são false if not (nil == false) then print("ok") end -‐-‐ mas nil ≠ false -‐-‐[[ A tabela é o único tipo estruturado nativo em Lua e serve de base a tudo o resto, incluindo algumas funcionalidades da própria linguagem. -‐-‐]] local a = {10, 20, 30} -‐-‐ tabela como array simples for index, value in pairs(a) do -‐-‐ índice “index” começa em 1 print(index .. " -‐> " .. value) end local t = {["key one"]=1, key_two=2, [3]=3} -‐-‐ tabela como array associativo for key, value in pairs(t) do -‐-‐ índice “key” sem ordem definida print(string.format("%s -‐> %d", key, value)) end lua-users.org/wiki/LuaTutorial!
1 then return 1 else return n * fact1(n -‐ 1) end end local fact2 = function(n) -‐-‐ as variáveis (e funções) são globais por omissão local f = 1 -‐-‐ mas o acesso a variáveis locais é mais eficiente while n > 1 do f = f * n n = n -‐ 1 end return f end for i = 1, 10, 1 do print(string.format("%d! = %d == %d", i, fact1(i), fact2(i))) end lua-users.org/wiki/LuaTutorial!
-‐-‐ função local ao módulo return n + i end return { -‐-‐ tabela de exports do módulo add = add } -‐-‐ test_module.lua local m = require("module") m.add(10, 1) lua-users.org/wiki/LuaTutorial!
-‐-‐ representação da classe e metatable das instâncias Class.__index = Class -‐-‐ fallback do lookup de atributos (métodos) na classe function Class.new(n) local self = setmetatable({}, Class) -‐-‐ a metatable adiciona “magia” à tabela que self.n = n; return self -‐-‐ pode incluir, p.ex. operator overloading end function Class.add(self, i) self.n = self.n + i; return self.n end return Class -‐-‐ test_class.lua local class = require("class") local instance = class.new(10) instance:add(1) -‐-‐ sintaxe equivalente a “instance.add(instance, 1)” lua-users.org/wiki/LuaTutorial!
eliminando a necessidade de módulos extra • Permite trazer lógica para a camada de entrega …partes que devem estar a cargo dos devops …ou para maximizar o desempenho do serviço • Fiável e com impacto mínimo nos tempos de resposta …o projecto arrancou no Taobao (grupo Alibaba) …usado intensivamente pela CloudFlare (actual patrocinador) • OpenResty Bundle* ou “Do-It-Yourself”** * openresty.org! ** github.com/openresty/lua-nginx-module!
de contexto per-request entre elas …controlo do fluxo e conteúdo final das respostas • API interna exposta em Lua* …com regexes compiladas, timers, encoding, etc. …com sub-requests, co-sockets e shared dictionaries …quase tudo main-loop friendly (não-bloqueante) • Suficiente para uma framework** completa * wiki.nginx.org/HttpLuaModule! log body filter / content header filter access rewrite set ** leafo.net/lapis!
{} http { server { listen *:80; server_name _; location / { set $backend "http://10.0.0.1"; rewrite_by_lua '[...]'; # com variáveis requer URL completo: proxy_pass "$backend$uri$is_args$args"; } } } -‐-‐ fase de rewrite local uri = ngx.var.uri local regex = "^/user/([0-‐9]+)$"; local m = ngx.re.match(uri, regex, "o") if m then ngx.req.set_uri("/profile") ngx.req.set_uri_args("id=" .. m[1]) ngx.var.backend = "https://10.0.0.2" end
{} http { lua_shared_dict counters 1m; server { listen *:80; server_name _; location / { default_type text/plain; access_by_lua '[...]'; header_filter_by_lua '[...]'; content_by_lua '[...]'; } } } -‐-‐ fase de controlo de acesso local counters = ngx.shared.counters local client = ngx.var.remote_addr counters:add(client, 0, 20) -‐-‐ expira em 20s local hits = counters:incr(client, 1) if hits > 10 then return ngx.exit(429) end ngx.ctx["hits"] = hits -‐-‐ contexto do pedido -‐-‐ fase de manipulação de headers ngx.header["X-‐Hits"] = ngx.ctx["hits"] -‐-‐ fase de output de conteúdo ngx.say(ngx.localtime())