Preface:
February 2012 Zhang Yichun (AGENTZH) gave a lecture on the theme of the "Nginx bonding environment" in Tech-club at an offline party, analyzing the trends of the enterprise Web architecture, That is, a seemingly complete web application, often in the background is split into multiple services, implemented by a number of departments, and each department provided to other departments are the HTTP protocol resful form of interface, followed by some nginx modules, finally, the introduction of LUA embedded in Nginx, The reason why the use of Nginx+lua to build is given.
RELATED links:
http://www.tech-club.org/?p=247
http://blog.zoomquiet.org/pyblosxom/oss/ openresty-intro-2012-03-06-01-13.html
http://agentzh.org/misc/slides/ngx-openresty-ecosystem/#1
Body:
Not long ago, accidentally saw this article, but also because of the previous understanding of concurrent programming concepts, the association in LUA early heard, so spent a few days to read the Lua grammar, was attracted by this small high-performance language, so decided to explore, In order to facilitate the experiment, it was downloaded directly openresty, compiled and run. Let me share some of my experience with you.
Here I write the open source anti-theft chain system (GitHub address Https://github.com/Hevienz/nginx-lua-ds-hotlink) as an example, the implementation of the anti-theft chain system has two methods, One is to check the Referer field in the HTTP header, which can only be used for general occasions, the second method is to generate accesskey for specific IP and files, and then the user accesses a particular file through a specific accesskey.
First, we configure the Nginx configuration as follows, so that application developers can easily get accesskey.
Location =/get_key {Allow 10.0.2.2; Deny all; Content_by_lua_file Lua/ds_hotlink/Get_key.lua; }
The Hotlink_get_key () function is called in the Accesskey.lua file, and the implementation of this function is placed in the Init.lua, so that the function is initialized when Nginx is started and tested to improve performance.
In Init.lua we implement the Hotlink_get_key () function, as follows:
functionHotlink_get_key ()LocalPath=Ngx.var.arg_pathif notPath ThenNgx.exit (405) End Localip=ngx.var.arg_ipif notIp ThenNgx.exit (405) End LocalTime=Ngx.now ()Localstring=Time : Path: IPLocalDigest =ngx.hmac_sha1 (Config.secret_key, String) Ngx.say (Ngx.encode_base64 (time).":".. Digest))End
The path and IP two parameters in the URL are obtained by Ngx.var.arg_path and Ngx.var.arg_ip respectively, then the hash values are generated based on the time, and the time information is appended to the client after being encoded with base64.
Then configure the following at the location where the security chain is needed:
Access_by_lua_file Lua/ds_hotlink/accesskey.lua;
In Accesskey.lua, the Hotlink_accesskey_module () function that is initialized in Init.lua is still called, as follows:
functionHotlink_accesskey_module ()Localkey=Ngx.var.arg_keyif notKey ThenLog{module_name="Hotlink_accesskey_module"} ngx.exit (405) End LocalUri=Ngx.var.request_uriLocalPath=Nil forIinch String.gmatch(URI,"[^\\?] +") DoPath=I Break End Localuser_ip=get_user_ip ()Localtime_digest=ngx.decode_base64 (Key)if notTime_digest ThenLog{module_name="Hotlink_accesskey_module"} ngx.exit (405) End if notTime_digest:match (":") ThenLog{module_name="Hotlink_accesskey_module"} ngx.exit (405) End Localtmp_dic_time_digest={} forIinch String.gmatch(Time_digest,"[^\\:]+") Do Table.insert(tmp_dic_time_digest,i)End Localtime=tmp_dic_time_digest[1] Localdigest=tmp_dic_time_digest[2] if notTimeor not Tonumber(time)or notDigestorTime+config.expiration_time < Ngx.now () ThenLog{module_name="Hotlink_accesskey_module"} ngx.exit (405) End Localstring=Time : Path: User_ipLocalReal_digest =ngx.hmac_sha1 (Config.secret_key, String)ifDigest ~=real_digest ThenLog{module_name="Hotlink_accesskey_module"} ngx.exit (405) End returnEnd
Get parameter key in URL, get time and hash information after decoding with Base64, then use Ngx.var.request_uri, User IP and parse time to determine if hash value matches, and provide the subordinate function such as timeout time and log, the related code is relatively simple , posted here:
Localconfig=require("Config") FD=Io.open(Config.logs_pwd."Hotlink.log","AB")Local functionget_user_ip ()LocalReq_headers =ngx.req.get_headers ()return(req_headers["X-real-ip"]orreq_headers["x_forwarded_for"])orngx.var.remote_addrEndLocal functionlog (args)LocalReq_headers =ngx.req.get_headers ()LocalTime=ngx.localtime ()LocalUSER_IP =get_user_ip ()LocalMethod=Ngx.req.get_method ()LocalRequest_uri=Ngx.var.request_uriLocalUser_agent=ngx.var.http_user_agentor "-" Localhttp_version=ngx.req.http_version ()Localheader_refer=req_headers["Referer"]or "-" LocalKey=ngx.var.arg_keyor "-" Localline ="[".. Args.module_name."] ".. User_ip." [".. Time:"] \"".. Method:" ".. Request_uri ." ".. Http_version ."\" \"".. User_agent."\" \"".. Header_refer."\" \"".. Key:"\ "\ n"Fd:write (line) Fd:flush ()End
The Config module includes the following:
Module("Config") Logs_pwd="/var/log/hotlink/"----refer Module----white_domains={ "geekhub\\.cc",}----accesskey Module----secret_key="naudw72h2iu34298dnawi81"Expiration_time=3600
Developers can modify the configuration, such as the log path, the domain whitelist of the refer module, the Secret_key of the accesskey module, and the time-out period.
Some people may ask what is the relationship between this and web development, in fact, from the open source software development process can be extended to the Resful form of interface development.
Openresty provides the following Lib for communication with the various upstream databases:
Lua-resty-memcached
Lua-resty-mysql
Lua-resty-redis
In addition to a variety of third-party LIB, such as the Bigplum/lua-resty-mongol for MongoDB , and so on, these Lib on their GitHub page provides examples and interface documentation, It is also very convenient to format the data from the database into JSON format, simply put the relevant data into the table (similar to the Python Array and dictionary), and then write down the following code:
Local require " Cjson " Ngx.say ("", Cjson.encode (res))
For beginners, Golgote/lua-resty-info is a great way to get information about Openresty, which provides important package.path and package.cpath information, as well as information about variables, functions, and modules. This is a demo,http://www.kembox.com/lua-resty-info.html
Thank you: In the process of exploring Openresty, got the help of Spring elder brother and many friends of open source community, only then can have this article, here Express thanks.
Ruoshan Https://github.com/ruoshan
Wendal Https://github.com/wendal
Agentzh Https://github.com/agentzh