You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2014/05/30 23:04:35 UTC

[03/50] [abbrv] git commit: TS-2555: more features for ts_lua - support function to add global hook, use TSError, support TSSkipRemappingSet

TS-2555: more features for ts_lua - support function to add global hook, use TSError, support TSSkipRemappingSet


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/14c484b4
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/14c484b4
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/14c484b4

Branch: refs/heads/5.0.x
Commit: 14c484b414ea3be02bc5aebee650cb626fc6cc58
Parents: e5b33fa
Author: Kit Chan <ki...@apache.org>
Authored: Sun May 25 00:16:57 2014 -0700
Committer: Kit Chan <ki...@apache.org>
Committed: Sun May 25 00:16:57 2014 -0700

----------------------------------------------------------------------
 doc/reference/plugins/ts_lua.en.rst             |  81 ++++++-
 .../ts_lua/example/test_closure.lua             |  23 ++
 plugins/experimental/ts_lua/ts_lua.c            | 224 ++++++++++---------
 plugins/experimental/ts_lua/ts_lua_common.h     |   5 +-
 plugins/experimental/ts_lua/ts_lua_hook.c       | 176 ++++++++++-----
 plugins/experimental/ts_lua/ts_lua_http.c       |  21 +-
 .../experimental/ts_lua/ts_lua_http_intercept.c |   8 +-
 plugins/experimental/ts_lua/ts_lua_package.c    |   4 +-
 plugins/experimental/ts_lua/ts_lua_transform.c  |   2 +-
 plugins/experimental/ts_lua/ts_lua_util.c       | 118 ++++++++--
 10 files changed, 473 insertions(+), 189 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/doc/reference/plugins/ts_lua.en.rst
----------------------------------------------------------------------
diff --git a/doc/reference/plugins/ts_lua.en.rst b/doc/reference/plugins/ts_lua.en.rst
index 8e8c329..c7bcf12 100644
--- a/doc/reference/plugins/ts_lua.en.rst
+++ b/doc/reference/plugins/ts_lua.en.rst
@@ -81,14 +81,14 @@ write this in remap.config:
 
 ::
 
-    map http://a.tbcdn.cn/ http://inner.tbcdn.cn/ @plugin=/XXX/libtslua.so @pparam=/XXX/test_hdr.lua
+    map http://a.tbcdn.cn/ http://inner.tbcdn.cn/ @plugin=/XXX/tslua.so @pparam=/XXX/test_hdr.lua
 
 Sometimes we want to receive parameters and process them in the script, we should realize '__init__' function in the lua
 script, and we can write this in remap.config:
 
 ::
 
-    map http://a.x.cn/ http://b.x.cn/ @plugin=/X/libtslua.so @pparam=/X/sethost.lua @pparam=a.st.cn
+    map http://a.x.cn/ http://b.x.cn/ @plugin=/X/tslua.so @pparam=/X/sethost.lua @pparam=a.st.cn
 
 This module can also act as a global plugin of Traffic Server. In this case we should provide one of these functions in
 each lua script:
@@ -184,10 +184,10 @@ ts.hook
 -------
 **syntax:** *ts.hook(HOOK_POINT, FUNCTION)*
 
-**context:** do_remap or do_global_* or later
+**context:** global or do_remap or do_global_* or later
 
 **description**: Hooks are points in http transaction processing where we can step in and do some work. FUNCTION will be
-called called when the http transaction steps in to HOOK_POINT.
+called when the http transaction steps in to HOOK_POINT.
 
 Here is an example
 
@@ -212,6 +212,30 @@ Then the client will get the response like this:
     Connection: Keep-Alive
     ...
 
+You can create global hook as well
+
+::
+
+    function do_some_work()
+       ts.debug('do_some_work')
+       return 0  
+    end
+
+    ts.hook(TS_LUA_HOOK_READ_REQUEST_HDR, do_some_work)
+
+Or you can do it this way
+
+    ts.hook(TS_LUA_HOOK_READ_REQUEST_HDR, 
+        function()
+            ts.debug('do_some_work')
+            return 0
+        end
+    )
+
+Also the return value of the function will control how the transaction will be re-enabled. Return value of 0 will cause
+the transaction to be re-enabled normally (TS_EVENT_HTTP_CONTINUE). Return value of 1 will be using TS_EVENT_HTTP_ERROR
+instead.
+
 `TOP <#ts-lua-plugin>`_
 
 Hook point constants
@@ -234,7 +258,7 @@ Hook point constants
     TS_LUA_REQUEST_TRANSFORM
     TS_LUA_RESPONSE_TRANSFORM
 
-These constants are usually used in [ts.hook](#tshook) method call.
+These constants are usually used in ts.hook method call.
 
 `TOP <#ts-lua-plugin>`_
 
@@ -1402,6 +1426,43 @@ This function is usually called after we hook TS_LUA_RESPONSE_TRANSFORM.
 
 `TOP <#ts-lua-plugin>`_
 
+ts.http.set_remapping_set
+-------------------------
+**syntax:** *ts.http.set_remapping_set(BOOL)*
+
+**context:** do_global_read_request
+
+**description**: This function can be used to tell trafficserver to skip doing remapping
+
+Here is an example:
+
+::
+
+    function do_global_read_request()
+        ts.http.set_remapping_set(0);
+        ts.client_request.header['Host'] = 'www.yahoo.com'
+        return 0
+    end
+
+This function is usually called in do_global_read_request function
+
+ts.http.is_internal_request
+---------------------------
+**syntax:** *ts.http.is_internal_request()*
+
+** context:** do_remap or do_global_* or later
+
+** description**: This function can be used to tell is a request is internal or not
+
+Here is an example:
+
+::
+
+    function do_global_read_request()
+        local internal = ts.http.is_internal_request()
+        ts.debug(internal)
+        return 0
+    end
 
 ts.add_package_path
 -------------------
@@ -1706,7 +1767,8 @@ ts.server_intercept
 
 **description:** Intercepts the server request and acts as the origin server.
 
-We should construct the response for the server request, so the request will be processed within FUNCTION in case of miss for the cache lookup.
+We should construct the response for the server request, so the request will be processed within FUNCTION in case of
+miss for the cache lookup.
 
 Here is an example:
 
@@ -2004,6 +2066,13 @@ Todo
 * ts.cache_xxx
 * `support lua-5.2 <https://github.com/portl4t/ts-lua/wiki/support-Lua-5.2>`_
 
+Currently when we use ts_lua as a global plugin, each global hook is using a separate lua state for the same
+transaction. This can be wasteful. Also the state cannot be reused for the same transaction across the global hooks. The
+alternative will be to use a TXN_START hook to create a lua state first and then add each global hook in the lua script
+as transaction hook instead. But this will have problem down the road when we need to have multiple plugins to work
+together in some proper orderings. In the future, we should consider different approach, such as creating and
+maintaining the lua state in the ATS core. 
+
 `TOP <#ts-lua-plugin>`_
 
 More docs

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/example/test_closure.lua
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/example/test_closure.lua b/plugins/experimental/ts_lua/example/test_closure.lua
new file mode 100644
index 0000000..edd973d
--- /dev/null
+++ b/plugins/experimental/ts_lua/example/test_closure.lua
@@ -0,0 +1,23 @@
+--  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.
+
+ts.hook(TS_LUA_HOOK_READ_REQUEST_HDR, 
+    function()
+       ts.debug('read_request')
+       return 0
+    end
+)
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua.c b/plugins/experimental/ts_lua/ts_lua.c
index cde8902..49930b7 100644
--- a/plugins/experimental/ts_lua/ts_lua.c
+++ b/plugins/experimental/ts_lua/ts_lua.c
@@ -80,7 +80,7 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s
 
   ts_lua_instance_conf *conf = TSmalloc(sizeof(ts_lua_instance_conf));
   if (!conf) {
-    fprintf(stderr, "[%s] TSmalloc failed !!\n", __FUNCTION__);
+    strncpy(errbuf, "[TSRemapNewInstance] TSmalloc failed!!", errbuf_size - 1);
     return TS_ERROR;
   }
 
@@ -98,7 +98,7 @@ TSRemapNewInstance(int argc, char *argv[], void **ih, char *errbuf, int errbuf_s
   ret = ts_lua_add_module(conf, ts_lua_main_ctx_array, TS_LUA_MAX_STATE_COUNT, argc - 2, &argv[2]);
 
   if (ret != 0) {
-    fprintf(stderr, "[%s] ts_lua_add_module failed\n", __FUNCTION__);
+    strncpy(errbuf, "[TSRemapNewInstance] ts_lua_add_module failed", errbuf_size - 1);
     return TS_ERROR;
   }
 
@@ -145,6 +145,12 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo * rri)
   http_ctx->client_request_hdrp = rri->requestHdrp;
   http_ctx->client_request_url = rri->requestUrl;
   http_ctx->remap = 1;
+  http_ctx->has_hook = 0;
+
+  contp = TSContCreate(ts_lua_http_cont_handler, NULL);
+  TSContDataSet(contp, http_ctx);
+  http_ctx->main_contp = contp;
+
   l = http_ctx->lua;
 
   lua_getglobal(l, TS_LUA_FUNCTION_REMAP);
@@ -153,18 +159,21 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo * rri)
     return TSREMAP_NO_REMAP;
   }
 
-  contp = TSContCreate(ts_lua_http_cont_handler, NULL);
-  TSContDataSet(contp, http_ctx);
-  http_ctx->main_contp = contp;
-
   if (lua_pcall(l, 0, 1, 0) != 0) {
-    fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+    TSError("lua_pcall failed: %s", lua_tostring(l, -1));
   }
 
   ret = lua_tointeger(l, -1);
   lua_pop(l, 1);
 
-  TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, contp);
+  if(http_ctx->has_hook) {
+    TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__);
+    TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, contp);
+  } else {    
+    TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__);
+    ts_lua_destroy_http_ctx(http_ctx); 
+    TSContDestroy(contp);
+  }
 
   TSMutexUnlock(main_ctx->mutexp);
 
@@ -172,19 +181,36 @@ TSRemapDoRemap(void *ih, TSHttpTxn rh, TSRemapRequestInfo * rri)
 }
 
 static int
-globalHookHandler(TSCont contp, TSEvent event, void *edata)
+globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata)
 {
   TSHttpTxn txnp = (TSHttpTxn) edata;
 
-  int ret = 0;
+  TSMBuffer bufp;
+  TSMLoc hdr_loc;
+  TSMLoc url_loc;
+
+  int ret;
+  uint64_t req_id;
+  TSCont txn_contp;
 
   lua_State *l;
 
-  ts_lua_http_ctx *http_ctx = (ts_lua_http_ctx *) TSContDataGet(contp);
+  ts_lua_main_ctx *main_ctx;
+  ts_lua_http_ctx *http_ctx;
+
+  ts_lua_instance_conf *conf = (ts_lua_instance_conf *) TSContDataGet(contp);
 
-  TSMBuffer bufp;
-  TSMLoc hdr_loc;
-  TSMLoc url_loc;
+  req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1);
+
+  main_ctx = &ts_lua_g_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT];
+
+  TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id);
+  TSMutexLock(main_ctx->mutexp);
+
+  http_ctx = ts_lua_create_http_ctx(main_ctx, conf);
+  http_ctx->txnp = txnp;
+  http_ctx->remap = 0;
+  http_ctx->has_hook = 0;
 
   if (!http_ctx->client_request_bufp) {
     if (TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc) == TS_SUCCESS) {
@@ -202,6 +228,10 @@ globalHookHandler(TSCont contp, TSEvent event, void *edata)
     return 0;
   }
 
+  txn_contp = TSContCreate(ts_lua_http_cont_handler, NULL);
+  TSContDataSet(txn_contp, http_ctx);
+  http_ctx->main_contp = txn_contp;
+
   l = http_ctx->lua;
 
   switch (event) {
@@ -266,190 +296,172 @@ globalHookHandler(TSCont contp, TSEvent event, void *edata)
   }
 
   if (lua_pcall(l, 0, 1, 0) != 0) {
-    fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+    TSError("lua_pcall failed: %s", lua_tostring(l, -1));
   }
 
   ret = lua_tointeger(l, -1);
   lua_pop(l, 1);
 
-  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-  return ret;
+  if(http_ctx->has_hook) {
+    // add a hook to release resources for context
+    TSDebug(TS_LUA_DEBUG_TAG, "[%s] has txn hook -> adding txn close hook handler to release resources", __FUNCTION__);
+    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp);
+  } else {
+    TSDebug(TS_LUA_DEBUG_TAG, "[%s] no txn hook -> release resources now", __FUNCTION__);
+    ts_lua_destroy_http_ctx(http_ctx);
+    TSContDestroy(txn_contp);
+  }
+
+  TSMutexUnlock(main_ctx->mutexp);
+
+  if(ret) {
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
+  } else {
+    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+  }
+
+  return 0;
 }
 
-static int
-transactionStartHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata)
+void
+TSPluginInit(int argc, const char *argv[])
 {
-  TSHttpTxn txnp = (TSHttpTxn) edata;
+  int ret = 0;
+  ts_lua_g_main_ctx_array = TSmalloc(sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT);
+  memset(ts_lua_g_main_ctx_array, 0, sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT);
 
-  uint64_t req_id;
-  TSCont txn_contp;
-  TSCont global_contp;
+  ret = ts_lua_create_vm(ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT);
 
-  ts_lua_main_ctx *main_ctx;
-  ts_lua_http_ctx *http_ctx;
+  if (ret) {
+    ts_lua_destroy_vm(ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT);
+    TSfree(ts_lua_g_main_ctx_array);
+    return;
+  }
 
-  ts_lua_instance_conf *conf = (ts_lua_instance_conf *) TSContDataGet(contp);
+  if (argc < 2) {
+    TSError("[%s] lua script file required !!", __FUNCTION__);
+    return;
+  }
 
-  req_id = __sync_fetch_and_add(&ts_lua_g_http_next_id, 1);
+  if (strlen(argv[1]) >= TS_LUA_MAX_SCRIPT_FNAME_LENGTH - 16) {
+    TSError("[%s] lua script file name too long !!", __FUNCTION__);
+    return;
+  }
 
-  main_ctx = &ts_lua_g_main_ctx_array[req_id % TS_LUA_MAX_STATE_COUNT];
+  ts_lua_instance_conf *conf = TSmalloc(sizeof(ts_lua_instance_conf));
+  if (!conf) {
+    TSError("[%s] TSmalloc failed !!", __FUNCTION__);
+    return;
+  }
+  memset(conf, 0, sizeof(ts_lua_instance_conf));
 
-  TSDebug(TS_LUA_DEBUG_TAG, "[%s] req_id: %" PRId64, __FUNCTION__, req_id);
-  TSMutexLock(main_ctx->mutexp);
+  sprintf(conf->script, "%s", argv[1]);
 
-  http_ctx = ts_lua_create_http_ctx(main_ctx, conf);
-  http_ctx->txnp = txnp;
-  http_ctx->remap = 0;
+  ts_lua_init_instance(conf);
 
-  txn_contp = TSContCreate(ts_lua_http_cont_handler, NULL);
-  TSContDataSet(txn_contp, http_ctx);
-  http_ctx->main_contp = txn_contp;
+  ret = ts_lua_add_module(conf, ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT, argc - 1, (char **) &argv[1]);
 
-  global_contp = TSContCreate(globalHookHandler, NULL);
-  TSContDataSet(global_contp, http_ctx);
+  if (ret != 0) {
+    TSError("[%s] ts_lua_add_module failed", __FUNCTION__);
+    return;
+  }
+
+  TSCont global_contp = TSContCreate(globalHookHandler, NULL);
+  if (!global_contp) {
+    TSError("[%s] could not create transaction start continuation", __FUNCTION__);
+    return;
+  }
+  TSContDataSet(global_contp, conf);
 
   //adding hook based on whether the lua global function exists.
+  ts_lua_main_ctx *main_ctx = &ts_lua_g_main_ctx_array[0];
+  ts_lua_http_ctx *http_ctx = ts_lua_create_http_ctx(main_ctx, conf);
   lua_State *l = http_ctx->lua;
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_REQUEST);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_SEND_REQUEST_HDR_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "send_request_hdr_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_READ_RESPONSE);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_READ_RESPONSE_HDR_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "read_response_hdr_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_SEND_RESPONSE);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_SEND_RESPONSE_HDR_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "send_response_hdr_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "cache_lookup_complete_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_READ_REQUEST);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "read_request_hdr_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_START);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_START_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "txn_start_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_PRE_REMAP);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_PRE_REMAP_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_PRE_REMAP_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "pre_remap_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_POST_REMAP);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_POST_REMAP_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_POST_REMAP_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "post_remap_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_SELECT_ALT);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_SELECT_ALT_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_SELECT_ALT_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "select_alt_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_OS_DNS);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_OS_DNS_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_OS_DNS_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "os_dns_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_READ_CACHE);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_READ_CACHE_HDR_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_READ_CACHE_HDR_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "read_cache_hdr_hook added");
   }
   lua_pop(l, 1);
 
   lua_getglobal(l, TS_LUA_FUNCTION_G_TXN_CLOSE);
   if (lua_type(l, -1) == LUA_TFUNCTION) {
-    TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, global_contp);
+    TSHttpHookAdd(TS_HTTP_TXN_CLOSE_HOOK, global_contp);
     TSDebug(TS_LUA_DEBUG_TAG, "txn_close_hook added");
   }
   lua_pop(l, 1);
 
-  // add a hook to release resources for context
-  TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, txn_contp);
-
-  TSMutexUnlock(main_ctx->mutexp);
-
-  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
-  return 0;
-}
-
-void
-TSPluginInit(int argc, const char *argv[])
-{
-  int ret = 0;
-  ts_lua_g_main_ctx_array = TSmalloc(sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT);
-  memset(ts_lua_g_main_ctx_array, 0, sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT);
-
-  ret = ts_lua_create_vm(ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT);
-
-  if (ret) {
-    ts_lua_destroy_vm(ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT);
-    TSfree(ts_lua_g_main_ctx_array);
-    return;
-  }
-
-  if (argc < 2) {
-    TSError("[%s] lua script file required !!", __FUNCTION__);
-    return;
-  }
-
-  if (strlen(argv[1]) >= TS_LUA_MAX_SCRIPT_FNAME_LENGTH - 16) {
-    TSError("[%s] lua script file name too long !!", __FUNCTION__);
-    return;
-  }
-
-  ts_lua_instance_conf *conf = TSmalloc(sizeof(ts_lua_instance_conf));
-  if (!conf) {
-    TSError("[%s] TSmalloc failed !!", __FUNCTION__);
-    return;
-  }
-
-  sprintf(conf->script, "%s", argv[1]);
-
-  ret = ts_lua_add_module(conf, ts_lua_g_main_ctx_array, TS_LUA_MAX_STATE_COUNT, argc - 1, (char **) &argv[1]);
-
-  if (ret != 0) {
-    TSError("[%s] ts_lua_add_module failed", __FUNCTION__);
-    return;
-  }
-
-  TSCont txn_start_contp = TSContCreate(transactionStartHookHandler, NULL);
-  if (!txn_start_contp) {
-    TSError("[%s] could not create transaction start continuation", __FUNCTION__);
-    return;
-  }
-  TSContDataSet(txn_start_contp, conf);
-  TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, txn_start_contp);
+  ts_lua_destroy_http_ctx(http_ctx);
 
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_common.h
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_common.h b/plugins/experimental/ts_lua/ts_lua_common.h
index 96f07b1..6c245f3 100644
--- a/plugins/experimental/ts_lua/ts_lua_common.h
+++ b/plugins/experimental/ts_lua/ts_lua_common.h
@@ -77,10 +77,6 @@
 
 #define TS_LUA_MAKE_VAR_ITEM(X)                 {X, #X}
 
-#define ee(...)     fprintf(stderr, "Lua *** %s: ", __func__); \
-                            fprintf(stderr, __VA_ARGS__);   \
-                            fprintf(stderr, " @ %s line %d.\n", __FILE__, __LINE__)
-
 /* for http config or cntl var */
 typedef struct
 {
@@ -140,6 +136,7 @@ typedef struct
   int ref;
 
   int remap;
+  int has_hook;
 
 } ts_lua_http_ctx;
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_hook.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_hook.c b/plugins/experimental/ts_lua/ts_lua_hook.c
index 6fb3985..1b27cf1 100644
--- a/plugins/experimental/ts_lua/ts_lua_hook.c
+++ b/plugins/experimental/ts_lua/ts_lua_hook.c
@@ -108,95 +108,169 @@ ts_lua_add_hook(lua_State * L)
   switch (entry) {
 
   case TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_CACHE_LOOKUP_COMPLETE);
+    }
     break;
 
   case TS_LUA_HOOK_SEND_REQUEST_HDR:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_SEND_REQUEST);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_SEND_REQUEST);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_SEND_REQUEST);
+    }
     break;
 
   case TS_LUA_HOOK_READ_RESPONSE_HDR:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_READ_RESPONSE);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_READ_RESPONSE);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_READ_RESPONSE);
+    }
     break;
 
   case TS_LUA_HOOK_SEND_RESPONSE_HDR:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_SEND_RESPONSE);
+    }
     break;
 
   case TS_LUA_HOOK_READ_REQUEST_HDR:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_READ_REQUEST);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_READ_REQUEST);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_READ_REQUEST);
+    }
     break;
 
   case TS_LUA_HOOK_TXN_START:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_TXN_START_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_TXN_START);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_TXN_START_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_TXN_START);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_TXN_START);
+    }
     break;
 
   case TS_LUA_HOOK_PRE_REMAP:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_PRE_REMAP_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_PRE_REMAP);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_PRE_REMAP_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_PRE_REMAP);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_PRE_REMAP);
+    }
     break;
 
   case TS_LUA_HOOK_POST_REMAP:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_POST_REMAP_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_POST_REMAP);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_POST_REMAP_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_POST_REMAP);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_POST_REMAP);
+    }    
     break;
 
   case TS_LUA_HOOK_OS_DNS:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_OS_DNS_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_OS_DNS);
+    if (http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_OS_DNS_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_OS_DNS);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_OS_DNS);
+    }
     break;
 
   case TS_LUA_HOOK_SELECT_ALT:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SELECT_ALT_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_SELECT_ALT);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SELECT_ALT_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_SELECT_ALT);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_SELECT_ALT);
+    }
     break;
 
   case TS_LUA_HOOK_READ_CACHE_HDR:
-    TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_CACHE_HDR_HOOK, http_ctx->main_contp);
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_READ_CACHE);
+    if(http_ctx) {
+      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_CACHE_HDR_HOOK, http_ctx->main_contp);
+      http_ctx->has_hook = 1;
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_READ_CACHE);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_READ_CACHE);
+    }
     break;
 
   case TS_LUA_HOOK_TXN_CLOSE:
-    // we don't need to add a hook because we already have added one by default
-    lua_pushvalue(L, 2);
-    lua_setglobal(L, TS_LUA_FUNCTION_TXN_CLOSE);
+    if(http_ctx) {
+      // we don't need to add a hook because we already have added one by default
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_TXN_CLOSE);
+    } else {
+      lua_pushvalue(L, 2);
+      lua_setglobal(L, TS_LUA_FUNCTION_G_TXN_CLOSE);
+    }
     break;
 
   case TS_LUA_REQUEST_TRANSFORM:
   case TS_LUA_RESPONSE_TRANSFORM:
-    transform_ctx = (ts_lua_transform_ctx *) TSmalloc(sizeof(ts_lua_transform_ctx));
-    memset(transform_ctx, 0, sizeof(ts_lua_transform_ctx));
-    transform_ctx->hctx = http_ctx;
-
-    connp = TSTransformCreate(ts_lua_transform_entry, http_ctx->txnp);
-    TSContDataSet(connp, transform_ctx);
-
-    if (entry == TS_LUA_REQUEST_TRANSFORM) {
-      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_REQUEST_TRANSFORM_HOOK, connp);
-    } else {
-      TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
+    if(http_ctx) {
+      http_ctx->has_hook = 1;
+      transform_ctx = (ts_lua_transform_ctx *) TSmalloc(sizeof(ts_lua_transform_ctx));
+      memset(transform_ctx, 0, sizeof(ts_lua_transform_ctx));
+      transform_ctx->hctx = http_ctx;
+
+      connp = TSTransformCreate(ts_lua_transform_entry, http_ctx->txnp);
+      TSContDataSet(connp, transform_ctx);
+
+      if (entry == TS_LUA_REQUEST_TRANSFORM) {
+        TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_REQUEST_TRANSFORM_HOOK, connp);
+      } else {
+        TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp);
+      }
+
+      lua_pushlightuserdata(L, transform_ctx);
+      lua_pushvalue(L, 2);
+      lua_rawset(L, LUA_GLOBALSINDEX);
     }
-
-    lua_pushlightuserdata(L, transform_ctx);
-    lua_pushvalue(L, 2);
-    lua_rawset(L, LUA_GLOBALSINDEX);
     break;
 
   default:

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_http.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_http.c b/plugins/experimental/ts_lua/ts_lua_http.c
index 9ceb3e8..0ceb0bb 100644
--- a/plugins/experimental/ts_lua/ts_lua_http.c
+++ b/plugins/experimental/ts_lua/ts_lua_http.c
@@ -55,7 +55,7 @@ static int ts_lua_http_resp_cache_transformed(lua_State * L);
 static int ts_lua_http_resp_cache_untransformed(lua_State * L);
 
 static int ts_lua_http_is_internal_request(lua_State * L);
-
+static int ts_lua_http_skip_remapping_set(lua_State * L);
 
 void
 ts_lua_inject_http_api(lua_State * L)
@@ -113,6 +113,9 @@ ts_lua_inject_http_misc_api(lua_State * L)
 {
   lua_pushcfunction(L, ts_lua_http_is_internal_request);
   lua_setfield(L, -2, "is_internal_request");
+
+  lua_pushcfunction(L, ts_lua_http_skip_remapping_set);
+  lua_setfield(L, -2, "skip_remapping_set");
 }
 
 static void
@@ -262,3 +265,19 @@ ts_lua_http_is_internal_request(lua_State * L)
 
   return 1;
 }
+
+static int
+ts_lua_http_skip_remapping_set(lua_State * L)
+{
+  int action;
+  ts_lua_http_ctx *http_ctx;
+
+  http_ctx = ts_lua_get_http_ctx(L);
+
+  action = luaL_checkinteger(L, 1);
+
+  TSSkipRemappingSet(http_ctx->txnp, action);
+
+  return 0;
+}
+

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_http_intercept.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_http_intercept.c b/plugins/experimental/ts_lua/ts_lua_http_intercept.c
index 21e142a..6693d7c 100644
--- a/plugins/experimental/ts_lua/ts_lua_http_intercept.c
+++ b/plugins/experimental/ts_lua/ts_lua_http_intercept.c
@@ -60,11 +60,12 @@ ts_lua_http_intercept(lua_State * L)
   ts_lua_http_ctx *http_ctx;
 
   http_ctx = ts_lua_get_http_ctx(L);
+  http_ctx->has_hook = 1;
 
   type = lua_type(L, 1);
 
   if (type != LUA_TFUNCTION) {
-    fprintf(stderr, "[%s] param in ts.http.intercept should be a function\n", __FUNCTION__);
+    TSError("[%s] param in ts.http.intercept should be a function", __FUNCTION__);
     return 0;
   }
 
@@ -88,11 +89,12 @@ ts_lua_http_server_intercept(lua_State * L)
   ts_lua_http_ctx *http_ctx;
 
   http_ctx = ts_lua_get_http_ctx(L);
+  http_ctx->has_hook = 1;
 
   type = lua_type(L, 1);
 
   if (type != LUA_TFUNCTION) {
-    fprintf(stderr, "[%s] param in ts.http.server_intercept should be a function\n", __FUNCTION__);
+    TSError("[%s] param in ts.http.server_intercept should be a function", __FUNCTION__);
     return 0;
   }
 
@@ -260,7 +262,7 @@ ts_lua_http_intercept_run_coroutine(ts_lua_http_intercept_ctx * ictx, int n)
     break;
 
   default:                     // error
-    fprintf(stderr, "lua_resume failed: %s\n", lua_tostring(L, -1));
+    TSError("lua_resume failed: %s", lua_tostring(L, -1));
     return -1;
   }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_package.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_package.c b/plugins/experimental/ts_lua/ts_lua_package.c
index 3d77f23..ab5096d 100644
--- a/plugins/experimental/ts_lua/ts_lua_package.c
+++ b/plugins/experimental/ts_lua/ts_lua_package.c
@@ -156,7 +156,7 @@ ts_lua_add_package_path_items(lua_State * L, ts_lua_package_path * pp, int n)
 
   for (i = 0; i < n; i++) {
     if (new_path_len + pp[i].len + 1 >= sizeof(new_path)) {
-      fprintf(stderr, "extended package.path is too long.\n");
+      TSError("extended package.path is too long.");
       return -1;
     }
 
@@ -277,7 +277,7 @@ ts_lua_add_package_cpath_items(lua_State * L, ts_lua_package_path * pp, int n)
 
   for (i = 0; i < n; i++) {
     if (new_path_len + pp[i].len + 1 >= sizeof(new_path)) {
-      fprintf(stderr, "extended package.cpath is too long.\n");
+      TSError("extended package.cpath is too long.");
       return -1;
     }
 

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_transform.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_transform.c b/plugins/experimental/ts_lua/ts_lua_transform.c
index f196ea6..b480c86 100644
--- a/plugins/experimental/ts_lua/ts_lua_transform.c
+++ b/plugins/experimental/ts_lua/ts_lua_transform.c
@@ -131,7 +131,7 @@ ts_lua_transform_handler(TSCont contp, ts_lua_transform_ctx * transform_ctx)
     }
 
     if (lua_pcall(L, 2, 2, 0)) {
-      fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(L, -1));
+      TSError("lua_pcall failed: %s", lua_tostring(L, -1));
     }
 
     ret = lua_tointeger(L, -1); /* 0 is not finished, 1 is finished */

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/14c484b4/plugins/experimental/ts_lua/ts_lua_util.c
----------------------------------------------------------------------
diff --git a/plugins/experimental/ts_lua/ts_lua_util.c b/plugins/experimental/ts_lua/ts_lua_util.c
index 36c5cfa..5304531 100644
--- a/plugins/experimental/ts_lua/ts_lua_util.c
+++ b/plugins/experimental/ts_lua/ts_lua_util.c
@@ -126,21 +126,23 @@ ts_lua_add_module(ts_lua_instance_conf * conf, ts_lua_main_ctx * arr, int n, int
 
     if (conf->content) {
       if (luaL_loadstring(L, conf->content)) {
-        fprintf(stderr, "[%s] luaL_loadstring %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1));
+        TSError("[%s] luaL_loadstring %s failed: %s", __FUNCTION__, conf->script, lua_tostring(L, -1));
         lua_pop(L, 1);
         TSMutexUnlock(arr[i].mutexp);
         return -1;
       }
 
-    } else if (luaL_loadfile(L, conf->script)) {
-      fprintf(stderr, "[%s] luaL_loadfile %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1));
-      lua_pop(L, 1);
-      TSMutexUnlock(arr[i].mutexp);
-      return -1;
+    } else if (conf->script) { 
+      if (luaL_loadfile(L, conf->script)) {
+        TSError("[%s] luaL_loadfile %s failed: %s", __FUNCTION__, conf->script, lua_tostring(L, -1));
+        lua_pop(L, 1);
+        TSMutexUnlock(arr[i].mutexp);
+        return -1;
+      }
     }
 
     if (lua_pcall(L, 0, 0, 0)) {
-      fprintf(stderr, "[%s] lua_pcall %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1));
+      TSError("[%s] lua_pcall %s failed: %s", __FUNCTION__, conf->script, lua_tostring(L, -1));
       lua_pop(L, 1);
       TSMutexUnlock(arr[i].mutexp);
       return -1;
@@ -160,7 +162,7 @@ ts_lua_add_module(ts_lua_instance_conf * conf, ts_lua_main_ctx * arr, int n, int
       }
 
       if (lua_pcall(L, 1, 1, 0)) {
-        fprintf(stderr, "[%s] lua_pcall %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1));
+        TSError("[%s] lua_pcall %s failed: %s", __FUNCTION__, conf->script, lua_tostring(L, -1));
         lua_pop(L, 1);
         TSMutexUnlock(arr[i].mutexp);
         return -1;
@@ -178,7 +180,6 @@ ts_lua_add_module(ts_lua_instance_conf * conf, ts_lua_main_ctx * arr, int n, int
       lua_pop(L, 1);            /* pop nil */
     }
 
-
     lua_pushlightuserdata(L, conf);
     lua_pushvalue(L, LUA_GLOBALSINDEX);
     lua_rawset(L, LUA_REGISTRYINDEX);   /* L[REG][conf] = L[GLOBAL] */
@@ -214,7 +215,7 @@ ts_lua_del_module(ts_lua_instance_conf * conf, ts_lua_main_ctx * arr, int n)
     if (lua_type(L, -1) == LUA_TFUNCTION) {
 
       if (lua_pcall(L, 0, 0, 0)) {
-        fprintf(stderr, "[%s] lua_pcall %s failed: %s\n", __FUNCTION__, conf->script, lua_tostring(L, -1));
+        TSError("[%s] lua_pcall %s failed: %s", __FUNCTION__, conf->script, lua_tostring(L, -1));
       }
 
     } else {
@@ -541,7 +542,7 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
 
     if (lua_type(l, -1) == LUA_TFUNCTION) {
       if (lua_pcall(l, 0, 1, 0)) {
-        fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
       }
 
       ret = lua_tointeger(l, -1);
@@ -555,7 +556,7 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
 
     if (lua_type(l, -1) == LUA_TFUNCTION) {
       if (lua_pcall(l, 0, 1, 0)) {
-        fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
       }
 
       ret = lua_tointeger(l, -1);
@@ -569,7 +570,7 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
 
     if (lua_type(l, -1) == LUA_TFUNCTION) {
       if (lua_pcall(l, 0, 1, 0)) {
-        fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
       }
 
       ret = lua_tointeger(l, -1);
@@ -583,7 +584,7 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
 
     if (lua_type(l, -1) == LUA_TFUNCTION) {
       if (lua_pcall(l, 0, 1, 0)) {
-        fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
       }
 
       ret = lua_tointeger(l, -1);
@@ -597,7 +598,85 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
 
     if (lua_type(l, -1) == LUA_TFUNCTION) {
       if (lua_pcall(l, 0, 1, 0)) {
-        fprintf(stderr, "lua_pcall failed: %s\n", lua_tostring(l, -1));
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_READ_REQUEST_HDR:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_READ_REQUEST);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_TXN_START:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_TXN_START);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_PRE_REMAP:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_PRE_REMAP);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+    
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_OS_DNS:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_OS_DNS);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_SELECT_ALT:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_SELECT_ALT);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
+    break;
+
+  case TS_EVENT_HTTP_READ_CACHE_HDR:
+
+    lua_getglobal(l, TS_LUA_FUNCTION_READ_CACHE);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
       }
 
       ret = lua_tointeger(l, -1);
@@ -606,6 +685,15 @@ ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata)
     break;
 
   case TS_EVENT_HTTP_TXN_CLOSE:
+    lua_getglobal(l, TS_LUA_FUNCTION_TXN_CLOSE);
+    if (lua_type(l, -1) == LUA_TFUNCTION) {
+      if (lua_pcall(l, 0, 1, 0)) {
+        TSError("lua_pcall failed: %s", lua_tostring(l, -1));
+      }
+
+      ret = lua_tointeger(l, -1);
+    }
+
     ts_lua_destroy_http_ctx(http_ctx);
     TSContDestroy(contp);
     break;