http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9a3e5de5/plugins/experimental/lua/state.h ---------------------------------------------------------------------- diff --git a/plugins/experimental/lua/state.h b/plugins/experimental/lua/state.h deleted file mode 100644 index 3cdf810..0000000 --- a/plugins/experimental/lua/state.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - Licensed to the Apache Software Foundation (ASF) under one - or more contributor license agreements. See the NOTICE file - distributed with this work for additional information - regarding copyright ownership. The ASF licenses this file - to you under the Apache License, Version 2.0 (the - "License"); you may not use this file except in compliance - with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -#ifndef LUA_STATE_H_ -#define LUA_STATE_H_ - -#include <string> -#include <vector> -#include <utility> -#include <pthread.h> -#include <lua.hpp> - -/* - -Lua Plugin threading model - -For remapping, we need to support multiple indepedent Lua plugin -instances. Each instance is handled by a LuaPluginInstance object. -Each plugin instance maintains a pool of lua_States which are -independent Lua interpeters. The LuaThreadState object owns a single -lua_State, holding additional hook data that is needed to de-multiplex -events. - -There are two basic code paths to obtaining a LuaThreadState. If -we already have a lua_State, then we can use the __instanceid and -__threadid global variables to identify the LuaThreadState object. -If we don't have a lua_State, then we know the instance ID from the -hook continuation data (attached per LuaPluginInstance), and we -choose a state by hashing the thread ID. - - Traffic Server +-> LuaPluginInstance[0] - | +-> LuaThreadState[0] - | +-> LuaThreadState[1] - | +-> LuaThreadState[2] - | +-> LuaThreadState[3] - | - +-> LuaPluginInstance[1] - | +-> LuaThreadState[0] - | +-> LuaThreadState[1] - | +-> LuaThreadState[2] - | +-> LuaThreadState[3] - | - +-> LuaPluginInstance[2] - +-> LuaThreadState[0] - +-> LuaThreadState[1] - +-> LuaThreadState[2] - +-> LuaThreadState[3] - -*/ - -typedef uint32_t instanceid_t; - -struct LuaThreadState; -struct LuaPluginInstance; - -// Per-thread lua_State. Used to execute Lua-side code in ethreads. -struct LuaThreadState -{ - lua_State * lua; - int hookrefs[TS_HTTP_LAST_HOOK]; - LuaPluginInstance * instance; - - pthread_mutex_t mutex; - - LuaThreadState(); - ~LuaThreadState(); - - bool alloc(LuaPluginInstance *, unsigned); - bool init(LuaPluginInstance *); - void release(); - -private: - LuaThreadState(const LuaThreadState&); // disable - LuaThreadState& operator=(const LuaThreadState&); // disable -}; - -struct LuaPluginInstance -{ - typedef std::vector<std::string> pathlist_t; - typedef TSCont demux_table_t[TS_HTTP_LAST_HOOK]; - - LuaPluginInstance(); - ~LuaPluginInstance(); - - void invalidate(); - void init(unsigned argc, const char ** argv); - - struct { - demux_table_t global; - demux_table_t txn; - demux_table_t ssn; - } demux; - - instanceid_t instanceid; - pathlist_t paths; - std::vector<LuaThreadState *> states; - -private: - LuaPluginInstance(const LuaPluginInstance&); // disable - LuaPluginInstance& operator=(const LuaPluginInstance&); // disable -}; - -instanceid_t LuaPluginRegister(unsigned argc, const char ** argv); -void LuaPluginUnregister(instanceid_t instanceid); - -// Acquire a locked Lua thread state belonging to the given instance. -std::pair<LuaThreadState *, LuaPluginInstance *> LuaThreadStateAcquire(instanceid_t); -std::pair<LuaThreadState *, LuaPluginInstance *> LuaThreadStateAcquire(lua_State *); -// Return the previously acquired Lua thread state. -void LuaThreadStateRelease(LuaThreadState *); - -struct ScopedLuaState -{ - explicit ScopedLuaState(instanceid_t instanceid) - : ptr(LuaThreadStateAcquire(instanceid)) { - } - - explicit ScopedLuaState(lua_State * lua) - : ptr(LuaThreadStateAcquire(lua)) { - } - - ~ScopedLuaState() { - LuaThreadStateRelease(this->ptr.first); - } - - operator bool() const { - return this->ptr.first != NULL; - } - - LuaThreadState * operator->() const { - return this->ptr.first; - } - - LuaPluginInstance * instance() const { - return this->ptr.second; - } - -private: - std::pair<LuaThreadState *, LuaPluginInstance *> ptr; -}; - -#endif // LUA_STATE_H_
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/9a3e5de5/plugins/experimental/ts_lua/README.md ---------------------------------------------------------------------- diff --git a/plugins/experimental/ts_lua/README.md b/plugins/experimental/ts_lua/README.md index a0fc7fc..6efbbd1 100644 --- a/plugins/experimental/ts_lua/README.md +++ b/plugins/experimental/ts_lua/README.md @@ -3,544 +3,7 @@ Name ts-lua - Embed the Power of Lua into TrafficServer. -Status +Documentation ====== -This module is being tested under our production environment. - -Version -====== -ts-lua has not been released yet. - -Synopsis -====== - -**test_hdr.lua** - - function send_response() - ts.client_response.header['Rhost'] = ts.ctx['rhost'] - return 0 - end - - - function do_remap() - local req_host = ts.client_request.header.Host - - if req_host == nil then - return 0 - end - - ts.ctx['rhost'] = string.reverse(req_host) - - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - - return 0 - end - - - -**test_transform.lua** - - function upper_transform(data, eos) - if eos == 1 then - return string.upper(data)..'S.H.E.\n', eos - else - return string.upper(data), eos - end - end - - function send_response() - ts.client_response.header['SHE'] = ts.ctx['tb']['she'] - return 0 - end - - - function do_remap() - local req_host = ts.client_request.header.Host - - if req_host == nil then - return 0 - end - - ts.ctx['tb'] = {} - ts.ctx['tb']['she'] = 'wo ai yu ye hua' - - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - ts.hook(TS_LUA_RESPONSE_TRANSFORM, upper_transform) - - ts.http.resp_cache_transformed(0) - ts.http.resp_cache_untransformed(1) - return 0 - end - - - -**test_cache_lookup.lua** - - function send_response() - ts.client_response.header['Rhost'] = ts.ctx['rhost'] - ts.client_response.header['CStatus'] = ts.ctx['cstatus'] - end - - - function cache_lookup() - local cache_status = ts.http.get_cache_lookup_status() - ts.ctx['cstatus'] = cache_status - end - - - function do_remap() - local req_host = ts.client_request.header.Host - - if req_host == nil then - return 0 - end - - ts.ctx['rhost'] = string.reverse(req_host) - - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) - - return 0 - end - - - -**test_ret_403.lua** - - function send_response() - ts.client_response.header['Now'] = ts.now() - return 0 - end - - - function do_remap() - - local uri = ts.client_request.get_uri() - - pos, len = string.find(uri, '/css/') - if pos ~= nil then - ts.http.set_resp(403, "Document access failed :)\n") - return 0 - end - - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - - return 0 - end - - - -**sethost.lua** - - HOSTNAME = '' - - function __init__(argtb) - - if (#argtb) < 1 then - print(argtb[0], 'hostname parameter required!!') - return -1 - end - - HOSTNAME = argtb[1] - end - - function do_remap() - local req_host = ts.client_request.header.Host - - if req_host == nil then - return 0 - end - - ts.client_request.header['Host'] = HOSTNAME - - return 0 - end - - -**test_intercept.lua** - - require 'os' - - function send_data() - local nt = os.time()..' Zheng.\n' - local resp = 'HTTP/1.1 200 OK\r\n' .. - 'Server: ATS/3.2.0\r\n' .. - 'Content-Type: text/plain\r\n' .. - 'Content-Length: ' .. string.len(nt) .. '\r\n' .. - 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. - 'Connection: keep-alive\r\n' .. - 'Cache-Control: max-age=7200\r\n' .. - 'Accept-Ranges: bytes\r\n\r\n' .. - nt - - ts.sleep(1) - return resp - end - - function do_remap() - ts.http.intercept(send_data) - return 0 - end - - -**test_server_intercept.lua** - - require 'os' - - function send_data() - local nt = os.time()..'\n' - local resp = 'HTTP/1.1 200 OK\r\n' .. - 'Server: ATS/3.2.0\r\n' .. - 'Content-Type: text/plain\r\n' .. - 'Content-Length: ' .. string.len(nt) .. '\r\n' .. - 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. - 'Connection: keep-alive\r\n' .. - 'Cache-Control: max-age=30\r\n' .. - 'Accept-Ranges: bytes\r\n\r\n' .. - nt - return resp - end - - function do_remap() - ts.http.server_intercept(send_data) - return 0 - end - - -Description -====== -This module embeds Lua, via the standard Lua 5.1 interpreter, into Apache Traffic Server. This module acts as remap plugin of Traffic Server, so we should realize **'do_remap'** function in each lua script. We can write this in remap.config: - -map http://a.tbcdn.cn/ http://inner.tbcdn.cn/ @plugin=/usr/lib64/trafficserver/plugins/libtslua.so @pparam=/etc/trafficserver/script/test_hdr.lua - -Sometimes we want to receive parameters and process them in the script, we should realize **'\__init__'** function in the lua script(sethost.lua is a reference), and we can write this in remap.config: - -map http://a.tbcdn.cn/ http://inner.tbcdn.cn/ @plugin=/usr/lib64/trafficserver/plugins/libtslua.so @pparam=/etc/trafficserver/script/sethost.lua @pparam=img03.tbcdn.cn - - - -TS API for Lua -====== -Introduction ------- -The API is exposed to Lua in the form of one standard packages ts. This package is in the default global scope and is always available within lua script. - - - -ts.now ------- -**syntax**: *val = ts.now()* - -**context**: global - -**description**: This function returns the time since the Epoch (00:00:00 UTC, January 1, 1970), measured in seconds. - -Here is an example: - - function send_response() - ts.client_response.header['Now'] = ts.now() - return 0 - end - - -ts.debug ------- -**syntax**: *ts.debug(MESSAGE)* - -**context**: global - -**description**: Log the MESSAGE to traffic.out if debug is enabled. - -Here is an example: - - function do_remap() - ts.debug('I am in do_remap now.') - return 0 - end - -The debug tag is ts_lua and we should write this in records.config: - - CONFIG proxy.config.diags.debug.tags STRING ts_lua - - -ts.hook ------- -**syntax**: *ts.hook(HOOK_POINT, FUNCTION)* - -**context**: do_remap or later - -**description**: Hooks are points in http transaction processing where we can step in and do some work. -FUNCTION will be called when the http transaction steps in to HOOK_POINT. - -Here is an example: - - function send_response() - s.client_response.header['SHE'] = 'belief' - end - - function do_remap() - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - end - -Hook point constants ------- -**context**: do_remap or later - - TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE - TS_LUA_HOOK_SEND_REQUEST_HDR - TS_LUA_HOOK_READ_RESPONSE_HDR - TS_LUA_HOOK_SEND_RESPONSE_HDR - TS_LUA_REQUEST_TRANSFORM - TS_LUA_RESPONSE_TRANSFORM - -These constants are usually used in ts.hook method call. - - -ts.ctx ------- -**syntax**: *ts.ctx[KEY]* - -**context**: do_remap or later - -**description**: This table can be used to store per-request Lua context data and has a life time identical to the current request. - -Here is an example: - - function send_response() - ts.client_response.header['RR'] = ts.ctx['rhost'] - return 0 - end - - function do_remap() - local req_host = ts.client_request.header.Host - ts.ctx['rhost'] = string.reverse(req_host) - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - return 0 - end - - -ts.http.get_cache_lookup_status ------- -**syntax**: *ts.http.get_cache_lookup_status()* - -**context**: function @ TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE hook point - -**description**: This function can be used to get cache lookup status. - -Here is an example: - - function send_response() - ts.client_response.header['CStatus'] = ts.ctx['cstatus'] - end - - function cache_lookup() - local cache_status = ts.http.get_cache_lookup_status() - if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH: - ts.ctx['cstatus'] = 'hit' - else - ts.ctx['cstatus'] = 'not hit' - end - end - - function do_remap() - ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) - ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) - return 0 - end - - -Http cache lookup status constants ------- -**context**: global - - TS_LUA_CACHE_LOOKUP_MISS (0) - TS_LUA_CACHE_LOOKUP_HIT_STALE (1) - TS_LUA_CACHE_LOOKUP_HIT_FRESH (2) - TS_LUA_CACHE_LOOKUP_SKIPPED (3) - - -ts.http.set_cache_url ------- -**syntax**: *ts.http.set_cache_url(KEY_URL)* - -**context**: do_remap - -**description**: This function can be used to modify the cache key for the request. - -Here is an example: - - function do_remap() - ts.http.set_cache_url('http://127.0.0.1:8080/abc/') - return 0 - end - - -ts.http.resp_cache_transformed ------- -**syntax**: *ts.http.resp_cache_transformed(BOOL)* - -**context**: do_remap or later - -**description**: This function can be used to tell trafficserver whether to cache the transformed data. - -Here is an example: - - function upper_transform(data, eos) - if eos == 1 then - return string.upper(data)..'S.H.E.\n', eos - else - return string.upper(data), eos - end - end - - function do_remap() - ts.hook(TS_LUA_RESPONSE_TRANSFORM, upper_transform) - ts.http.resp_cache_transformed(0) - ts.http.resp_cache_untransformed(1) - return 0 - end - -This function is usually called after we hook TS_LUA_RESPONSE_TRANSFORM. - - -ts.http.resp_cache_untransformed ------- -**syntax**: *ts.http.resp_cache_untransformed(BOOL)* - -**context**: do_remap or later - -**description**: This function can be used to tell trafficserver whether to cache the untransformed data. - -Here is an example: - - function upper_transform(data, eos) - if eos == 1 then - return string.upper(data)..'S.H.E.\n', eos - else - return string.upper(data), eos - end - end - - function do_remap() - ts.hook(TS_LUA_RESPONSE_TRANSFORM, upper_transform) - ts.http.resp_cache_transformed(0) - ts.http.resp_cache_untransformed(1) - return 0 - end - -This function is usually called after we hook TS_LUA_RESPONSE_TRANSFORM. - - -ts.client_request.client_addr.get_addr ------- -**syntax**: *ts.client_request.client_addr.get_addr()* - -**context**: do_remap or later - -**description**: This function can be used to get socket address of the client. - -Here is an example: - - function do_remap - ip, port, family = ts.client_request.client_addr.get_addr() - return 0 - end - -The ts.client_request.client_addr.get_addr function returns three values, ip is a string, port and family is number. - - -ts.client_request.get_method ------- -**syntax**: *ts.client_request.get_method()* - -**context**: do_remap or later - -**description**: This function can be used to retrieve the current request's request method name. String like "GET" or -"POST" is returned. - - -ts.client_request.set_method ------- -**syntax**: *ts.client_request.set_method(METHOD_NAME)* - -**context**: do_remap - -**description**: This function can be used to override the current request's request method with METHOD_NAME. - - -ts.client_request.get_url ------- -**syntax**: *ts.client_request.get_url()* - -**context**: do_remap or later - -**description**: This function can be used to retrieve the whole request's url. - - -ts.client_request.get_uri ------- -**syntax**: *ts.client_request.get_uri()* - -**context**: do_remap or later - -**description**: This function can be used to retrieve the request's path. - - -ts.client_request.set_uri ------- -**syntax**: *ts.client_request.set_uri(PATH)* - -**context**: do_remap - -**description**: This function can be used to override the request's path. - - -ts.client_request.get_uri_args ------- -**syntax**: *ts.client_request.get_uri_args()* - -**context**: do_remap or later - -**description**: This function can be used to retrieve the request's query string. - - -ts.client_request.set_uri_args ------- -**syntax**: *ts.client_request.set_uri_args(QUERY_STRING)* - -**context**: do_remap - -**description**: This function can be used to override the request's query string. - - -ts.client_request.header.HEADER ------- -**syntax**: *ts.client_request.header.HEADER = VALUE* - -**syntax**: *ts.client_request.header[HEADER] = VALUE* - -**syntax**: *VALUE = ts.client_request.header.HEADER* - -**context**: do_remap or later - -**description**: Set, add to, clear or get the current request's HEADER. - -Here is an example: - - function do_remap() - local req_host = ts.client_request.header.Host - ts.client_request.header['Host'] = 'a.tbcdn.cn' - end - - -TODO -======= -Short Term ------- -* non-blocking I/O operation -* ts.fetch - -Long Term ------- -* ts.regex +http://trafficserver.readthedocs.org/en/latest/reference/plugins/ts_lua.en.html
