[solved] nginx template modul

Olyan Nginx modult keresek, ami minden requestnél betölt a kiszolgálandó fájl mellől (opcionálisan a szülő könyvtárakból is) egy kulcs-érték párokat tartalmazó fájlt, pl. template.ini.
és az ebben lévő stringeket
A) vagy betölti $tmpl_* nginx válozókba, amiket SSI-vel fel tudok használni (<!--# echo var="tmpl_title" -->),
B) vagy filtereli a http választ kicserélve a "{kulcs}", vagy "<!--% kulcs -->" előforulásokat a template.ini-ből betöltött értékekkel.
Fastcgi használata nélkül.

Hozzászólások

Ez a template.ini egy nginx-konfig lenne?

nem.
ez egy teljesen user defined fájl lenne a webroot alatt, amit minden lekéréskor betöltene (persze cache-elheti amíg a file mtime nem változik) az nginx.
SSI-vel meg lehetne oldani, de nem elég felhasználóbarát és én szeretnék egy olyan definíciós fájlt szeretnék, ami sallangoktól mentes, pl. ini formátum.

page.html:
<!--# include file="_templates.html" wait="yes" -->
<html>
<head>
<title><!--# echo var="title" -->
...

_templates.html:
<!--# set var="title" value="Hello World" -->
...

ezzel az a baj, hogy a page.html ejelén be kell hivatkozni a _templates.html-t és a templates fájlban SSI tag-ekkel kell megadni a válozókat, valamint nem csak változódefiníciókat lehet benne megadni.

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

erről nem tudok. arra gondolsz hogy indításkor generál konfig fájlt amit asztán betölt?
mindegy is, ez nem lenne megoldás, mert egy nginx konfigban bármi lehet, nem csak változók; nekem minden lekérésnél fel kéne dolgozni a template változókat tartalmazó fájlt - nem megengedhető egy template változó cseréjekor az egész webszervert reload-olni.

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

igazad van, én se mondanám teljes egészében webszerver feladatnak.
tipikusan valamilyen cgi backendek szokták végezni.
viszont az nginx SSI-je már elég hasonló képesség, továbbá van jópár filter modulja is (subs, addition), amik kimondottan a response átírására valóak. szerintem egy template kezelés is elfér ezek mellé.

lua-t nézegettem, de csak meghatározott válozókat tud beállítani (set_by_lua), így nem definiálhatok akármennyi, akármilyen nevű template változót; vagy csinálhatok olyan hogy az egész content-et a lua állítja össze (content_by_lua), ezesetben ugyan kedvemre filter-elhetem a kért tartalmat, de elveszlik az nginx saját kiszolgálási mechnizmusa (hozzáférés ellenőrzés, header-ek manipulálása, magának a fájlnak a megtalálása, try_files, stb).

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

van egy ilyen direktíva is: body_filter_by_lua
efölött átsiklottam. még akár jó is lehet!
kár hogy a perl modulban nincs filter lehetőség - abban könnyebben megírnám az ini felolvasást és string kicserélgetést, mint lua-ban.

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

sikerült összedobni a lua kódot.
egyetlen hátránya, hogy header_filter_by_lua -ban törölni kell a Content-Length -et, mert változhat a content mérete; amit végülis kibirok, mert kis html fájloknál általában nincs rá szükség.
egyelőre csak az aktuális kvt-ból veszi a template.ini-t, nem ellenőrzi a parentokat. és <!--{title}--> formájú stringeket cserél ki.
kell arra számítanom, hogy ha a body_filter_by_lua_file darabonként kapja meg a body-t, akkor egy ilyen template válozót kettévághat két chunk határa?

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

inifile modul innen van: http://santos.nfshost.com/inifile.html


 	require 'inifile'

	if ngx.header.content_type == "text/html" then
		local file = ngx.var.request_filename
		local dir, cnt, err = ngx.re.gsub(file, "[^/]+$", "")
		local ini = dir .. "template.ini"

		local fh = io.open(ini, "r")
		if fh ~= nil then
		    io.close(fh)

			if ngx.get_phase() == "header_filter" then
				ngx.header.content_length = nil

			elseif ngx.get_phase() == "body_filter" then
				local tmpl = ngx.ctx.template_variables
				local buff = ngx.ctx.chunk_buffer
				local matched = 0
				local last_chunk = ngx.arg[2]
				
				if not tmpl then
					tmpl = inifile.parse(ini, false)
					ngx.ctx.template_variables = tmpl
				end
				if buff then
					ngx.arg[1] = buff .. ngx.arg[1]
				end

				if not last_chunk then
					grp, err = ngx.re.match(ngx.arg[1], "<(!(-(-(\\{([^\\}]+(\\}(-(-(>)?)?)?)?)?)?)?)?)?$")
					if err then
						ngx.log(ngx.ERR, "re.match error: ", err)
					else
						ngx.log(ngx.DEBUG, "possible chunked template tag: ", grp[0])
						matched = 1
					end
				end
				if not last_chunk and matched then
					buff = ngx.arg[1]
					ngx.arg[1] = nil
				else
					for tmplvar, tmplstr in pairs(tmpl["html"]) do
						local str, cnt, err = ngx.re.gsub(ngx.arg[1], "<!--\\{" .. tmplvar .. "\\}-->", tmplstr)
						if str then
							ngx.arg[1] = str
						else
							ngx.log(ngx.ERR, "re.gsub error: ", err)
						end
					end
				end
				
				ngx.ctx.chunk_buffer = buff
			end
		end
	end

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack

nincs php cgi ott ahol ezt használom, de egész biztosan állítom, hogy az nginx-be ágyazott lua gyorsabb kell h legyen, mint egy php cgi-os megoldás. kezdve ott, hogy a php minden forrás fájlt minden request-nél beolvas, a lua kód meg memóriában van (abból gondolom, mert az nginxt reload-olni kell ha változtatok a lua kódon). a folyamat más részeiben nem látok jelentős teljesítménykülönbségre lehetőséget: fájlművelet, sztringművelet... esetleg a regexp implementáción múlhat valami.

~~~~~~~~
deb http://deb.uucp.hu/ wheezy yazzy repack