├── .gitignore ├── README.markdown ├── example ├── hdr.lua ├── post_transform.lua ├── sethost.lua ├── test_cache.lua ├── test_cache_large.lua ├── test_cache_lookup.lua ├── test_cache_status.lua ├── test_cached_response.lua ├── test_cached_response_hdr.lua ├── test_cached_response_hdrs.lua ├── test_client_error_response.lua ├── test_client_hdrs.lua ├── test_client_socket.lua ├── test_creq_method.lua ├── test_creq_uri.lua ├── test_creq_uri_args.lua ├── test_dup.lua ├── test_escape.lua ├── test_fetch.lua ├── test_fetch_multi.lua ├── test_fetch_post.lua ├── test_flush.lua ├── test_intercept.lua ├── test_json.lua ├── test_md5.lua ├── test_path.lua ├── test_redirect.lua ├── test_regex.lua ├── test_remap1.lua ├── test_remap2.lua ├── test_ret_403.lua ├── test_server_intercept.lua ├── test_server_request.lua ├── test_sha1.lua ├── test_shdict_keys.lua ├── test_sleep.lua ├── test_transform.lua ├── test_url.lua └── test_xml.lua └── src ├── Makefile ├── lib ├── ts_fetcher.c └── ts_fetcher.h ├── ts_lua.c ├── ts_lua_cache.c ├── ts_lua_cache.h ├── ts_lua_cached_response.c ├── ts_lua_cached_response.h ├── ts_lua_client_request.c ├── ts_lua_client_request.h ├── ts_lua_client_response.c ├── ts_lua_client_response.h ├── ts_lua_common.h ├── ts_lua_constant.c ├── ts_lua_constant.h ├── ts_lua_context.c ├── ts_lua_context.h ├── ts_lua_coroutine.c ├── ts_lua_coroutine.h ├── ts_lua_crypto.c ├── ts_lua_crypto.h ├── ts_lua_fetch.c ├── ts_lua_fetch.h ├── ts_lua_hash_table.c ├── ts_lua_hash_table.h ├── ts_lua_hook.c ├── ts_lua_hook.h ├── ts_lua_http.c ├── ts_lua_http.h ├── ts_lua_http_cntl.c ├── ts_lua_http_cntl.h ├── ts_lua_http_config.c ├── ts_lua_http_config.h ├── ts_lua_http_intercept.c ├── ts_lua_http_intercept.h ├── ts_lua_io.c ├── ts_lua_io.h ├── ts_lua_log.c ├── ts_lua_log.h ├── ts_lua_mgmt.c ├── ts_lua_mgmt.h ├── ts_lua_misc.c ├── ts_lua_misc.h ├── ts_lua_package.c ├── ts_lua_package.h ├── ts_lua_regex.c ├── ts_lua_regex.h ├── ts_lua_remap.c ├── ts_lua_remap.h ├── ts_lua_server_request.c ├── ts_lua_server_request.h ├── ts_lua_server_response.c ├── ts_lua_server_response.h ├── ts_lua_shared_dict.c ├── ts_lua_shared_dict.h ├── ts_lua_string.c ├── ts_lua_string.h ├── ts_lua_transform.c ├── ts_lua_transform.h ├── ts_lua_util.c └── ts_lua_util.h /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.sh 3 | *.so 4 | *.lo 5 | *.swp 6 | 7 | src/test_* 8 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## Name 2 | ts-lua - Embed the Power of Lua into Apache TrafficServer. 3 | 4 | ## Status 5 | This module is under active development and is production ready. 6 | 7 | ## Version 8 | This document describes ts-lua [v0.1.7](https://github.com/portl4t/ts-lua/tags) released on 31 May 2015. It can work with Apache TrafficServer v4.x, v5.x. 9 | 10 | ## Google group 11 | https://groups.google.com/forum/#!forum/ts-lua 12 | 13 | ##Synopsis 14 | **hdr.lua** 15 | ```lua 16 | function send_response() 17 | ts.client_response.header['Rhost'] = ts.ctx['rhost'] 18 | return 0 19 | end 20 | 21 | function do_remap() 22 | local req_host = ts.client_request.header.Host 23 | ts.ctx['rhost'] = string.reverse(req_host) 24 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 25 | return 0 26 | end 27 | ``` 28 | 29 | **sethost.lua** 30 | ```lua 31 | local HOSTNAME = '' 32 | 33 | function __init__(argtb) 34 | if (#argtb) < 1 then 35 | print(argtb[0], 'hostname parameter required!!') 36 | return -1 37 | end 38 | HOSTNAME = argtb[1] 39 | end 40 | 41 | function do_remap() 42 | ts.client_request.header['Host'] = HOSTNAME 43 | return 0 44 | end 45 | ``` 46 | 47 | ## Description 48 | 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: 49 | 50 | >map http://a.foo.com/ http://inner.foo.com/ @plugin=/X/libtslua.so @pparam=/X/hdr.lua 51 | 52 | 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: 53 | 54 | >map http://a.foo.com/ http://b.foo.com/ @plugin=/X/libtslua.so @pparam=/X/sethost.lua @pparam=a.st.com 55 | 56 | 57 | ## Doc 58 | https://github.com/portl4t/ts-lua/wiki/Doc 59 | 60 | ## System Requirements 61 | * linux/freebsd 64bits 62 | * trafficserver 63 | * pcre 64 | * tcl 65 | * openssl 66 | * lua-5.1 67 | 68 | ## Build 69 | **step1**: get ts-lua 70 | 71 | git clone https://github.com/portl4t/ts-lua.git 72 | cd ts-lua/src 73 | 74 | **step2**: modify Makefile to insure INC_PATH and LIB_PATH is right for trafficserver, lua-5.1 and tcl 75 | 76 | make 77 | 78 | **step3**: modify remap.config and restart the trafficserver 79 | 80 | ## ChangeLog 81 | https://github.com/portl4t/ts-lua/wiki/ChangeLog 82 | 83 | ## History 84 | * [v0.1.7](https://github.com/portl4t/ts-lua/releases/tag/v0.1.7), 2015-05-31 85 | * [v0.1.6](https://github.com/portl4t/ts-lua/releases/tag/v0.1.6), 2015-03-13 86 | * [v0.1.5](https://github.com/portl4t/ts-lua/releases/tag/v0.1.5), 2014-12-18 87 | * [v0.1.4](https://github.com/portl4t/ts-lua/releases/tag/v0.1.4), 2014-05-02 88 | 89 | ## See Also 90 | * [ts-fetcher](https://github.com/portl4t/ts-fetcher) http fetcher for ats, implement as plugin with c 91 | 92 | -------------------------------------------------------------------------------- /example/hdr.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Rhost'] = ts.ctx['rhost'] 20 | return 0 21 | end 22 | 23 | 24 | function do_remap() 25 | local req_host = ts.client_request.header.Host 26 | 27 | if req_host == nil then 28 | return 0 29 | end 30 | 31 | ts.ctx['rhost'] = string.reverse(req_host) 32 | 33 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 34 | 35 | return 0 36 | end 37 | 38 | -------------------------------------------------------------------------------- /example/post_transform.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function request_transform(data, eos) 19 | if data ~= nil then 20 | ts.ctx['body'] = ts.ctx['body'] .. data 21 | end 22 | 23 | if eos == 1 then 24 | local hash = ts.sha1(ts.ctx['body']) 25 | print(ts.ctx['body']) 26 | print(hash) 27 | end 28 | 29 | return data, eos 30 | end 31 | 32 | function do_remap() 33 | local method = ts.client_request.get_method() 34 | 35 | if method == 'POST' then 36 | ts.ctx['body'] = '' 37 | ts.hook(TS_LUA_REQUEST_TRANSFORM, request_transform) 38 | end 39 | 40 | return 0 41 | end 42 | -------------------------------------------------------------------------------- /example/sethost.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | local HOSTNAME = '' 19 | 20 | function __init__(argtb) 21 | 22 | if (#argtb) < 1 then 23 | print(argtb[0], 'hostname parameter required!!') 24 | return -1 25 | end 26 | 27 | HOSTNAME = argtb[1] 28 | end 29 | 30 | function do_remap() 31 | local req_host = ts.client_request.header.Host 32 | 33 | if req_host == nil then 34 | return 0 35 | end 36 | 37 | ts.client_request.header['Host'] = HOSTNAME 38 | 39 | return 0 40 | end 41 | 42 | -------------------------------------------------------------------------------- /example/test_cache.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function read_data(c) 20 | local nt = os.time()..' Zheng.\n' 21 | local resp = 'HTTP/1.0 200 OK\r\n' .. 22 | 'Server: ATS/5.2.0\r\n' .. 23 | 'Content-Type: text/plain\r\n' .. 24 | 'Content-Length: ' .. string.format('%d', string.len(nt)) .. '\r\n' .. 25 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 26 | 'Connection: keep-alive\r\n' .. 27 | 'Cache-Control: max-age=7200\r\n' .. 28 | 'Accept-Ranges: bytes\r\n\r\n' .. 29 | nt 30 | 31 | if c == 'r' then 32 | local fd = ts.cache_open('transformer.txt', TS_LUA_CACHE_READ) 33 | if fd.hit then 34 | d = ts.cache_read(fd) 35 | ts.cache_close(fd) 36 | print(d) 37 | 38 | else 39 | print('miss') 40 | end 41 | 42 | elseif c == 'w' then 43 | local rfd = ts.cache_open('transformer.txt', TS_LUA_CACHE_READ) 44 | local hit = rfd.hit 45 | ts.cache_close(rfd) 46 | 47 | if hit ~= true then 48 | local fd = ts.cache_open('transformer.txt', TS_LUA_CACHE_WRITE) 49 | local n = ts.cache_write(fd, 'Optimus Prime.') 50 | print(string.format('write %d bytes', n)) 51 | ts.cache_close(fd) 52 | end 53 | 54 | else 55 | ts.cache_remove('transformer.txt') 56 | print('removed') 57 | end 58 | 59 | ts.say(resp) 60 | end 61 | 62 | function do_remap() 63 | local cc = ts.client_request.header['CC'] 64 | if cc == nil then 65 | return 0 66 | end 67 | 68 | ts.http.intercept(read_data, cc) 69 | return 0 70 | end 71 | -------------------------------------------------------------------------------- /example/test_cache_large.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function read_data(c) 20 | local nt = os.time()..' Zheng.\n' 21 | local resp = 'HTTP/1.0 200 OK\r\n' .. 22 | 'Server: ATS/5.2.0\r\n' .. 23 | 'Content-Type: text/plain\r\n' .. 24 | 'Content-Length: ' .. string.format('%d', string.len(nt)) .. '\r\n' .. 25 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 26 | 'Connection: keep-alive\r\n' .. 27 | 'Cache-Control: max-age=7200\r\n' .. 28 | 'Accept-Ranges: bytes\r\n\r\n' .. 29 | nt 30 | 31 | local rfd = ts.cache_open('http://foo.com/large.pdf', TS_LUA_CACHE_READ, 'uh') 32 | 33 | if rfd.hit then 34 | while ts.cache_eof(rfd) ~= true do 35 | d = ts.cache_read(rfd, 1024*1024*5) 36 | if ts.cache_err(rfd) then 37 | break 38 | end 39 | print(string.len(d)) 40 | end 41 | 42 | ts.cache_close(rfd) 43 | 44 | else 45 | print('miss') 46 | end 47 | 48 | ts.say(resp) 49 | end 50 | 51 | function do_remap() 52 | local cc = ts.client_request.header['CC'] 53 | if cc == nil then 54 | return 0 55 | end 56 | 57 | ts.http.intercept(read_data, cc) 58 | return 0 59 | end 60 | -------------------------------------------------------------------------------- /example/test_cache_lookup.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function cache_lookup() 18 | local cache_status = ts.http.get_cache_lookup_status() 19 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 20 | print('hit') 21 | else 22 | print('not hit') 23 | end 24 | end 25 | 26 | function do_remap() 27 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 28 | return 0 29 | end 30 | 31 | -------------------------------------------------------------------------------- /example/test_cache_status.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function cache_lookup() 18 | local cache_status = ts.http.get_cache_lookup_status() 19 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 20 | print('hit') 21 | ts.http.set_cache_lookup_status(TS_LUA_CACHE_LOOKUP_MISS) 22 | end 23 | end 24 | 25 | function do_remap() 26 | local uri = ts.client_request.get_uri() 27 | if uri == '/slayer.txt' then 28 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 29 | end 30 | return 0 31 | end 32 | 33 | -------------------------------------------------------------------------------- /example/test_cached_response.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function cache_lookup() 18 | local cache_status = ts.http.get_cache_lookup_status() 19 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 20 | code = ts.cached_response.get_status() 21 | print(code) 22 | end 23 | end 24 | 25 | function do_remap() 26 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 27 | return 0 28 | end 29 | 30 | -------------------------------------------------------------------------------- /example/test_cached_response_hdr.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function cache_lookup() 18 | local cache_status = ts.http.get_cache_lookup_status() 19 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 20 | code = ts.cached_response.header['Content-Type'] 21 | print(code) 22 | end 23 | end 24 | 25 | function do_remap() 26 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 27 | return 0 28 | end 29 | 30 | -------------------------------------------------------------------------------- /example/test_cached_response_hdrs.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function cache_lookup() 18 | local cache_status = ts.http.get_cache_lookup_status() 19 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 20 | hdrs = ts.cached_response.get_headers() 21 | for k, v in pairs(hdrs) do 22 | print(k..': '..v) 23 | end 24 | end 25 | end 26 | 27 | function do_remap() 28 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 29 | return 0 30 | end 31 | 32 | -------------------------------------------------------------------------------- /example/test_client_error_response.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | -- ts.client_response.set_error_resp(404, 'bad luck :(\n') 20 | ts.client_response.set_error_resp(200, 'bad luck :(\n') 21 | end 22 | 23 | function cache_lookup() 24 | local cache_status = ts.http.get_cache_lookup_status() 25 | 26 | if cache_status == TS_LUA_CACHE_LOOKUP_HIT_FRESH then 27 | code = ts.cached_response.get_status() 28 | print(code) 29 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 30 | return -1 31 | end 32 | end 33 | 34 | function do_remap() 35 | ts.hook(TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, cache_lookup) 36 | return 0 37 | end 38 | 39 | -------------------------------------------------------------------------------- /example/test_client_hdrs.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | hdrs = ts.client_request.get_headers() 20 | for k, v in pairs(hdrs) do 21 | print(k..': '..v) 22 | end 23 | return 0 24 | end 25 | 26 | -------------------------------------------------------------------------------- /example/test_client_socket.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['CIP'] = ts.ctx['ip'] 20 | ts.client_response.header['CPort'] = ts.ctx['port'] 21 | ts.client_response.header['Now'] = ts.now() 22 | return 0 23 | end 24 | 25 | 26 | function do_remap() 27 | req_host = ts.client_request.header.Host 28 | 29 | if req_host == nil then 30 | return 0 31 | end 32 | 33 | ts.ctx['ip'] = ts.client_request.client_addr.get_ip() 34 | ts.ctx['port'] = ts.client_request.client_addr.get_port() 35 | 36 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 37 | 38 | return 0 39 | end 40 | 41 | -------------------------------------------------------------------------------- /example/test_creq_method.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Method'] = ts.ctx['method'] 20 | end 21 | 22 | 23 | function do_remap() 24 | local method = ts.client_request.get_method() 25 | 26 | if method == nil then 27 | return 0 28 | end 29 | 30 | ts.ctx['method'] = method 31 | 32 | if method ~= 'GET' then 33 | ts.client_request.set_method('GET') 34 | end 35 | 36 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 37 | 38 | return 0 39 | end 40 | 41 | -------------------------------------------------------------------------------- /example/test_creq_uri.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Uri'] = ts.ctx['uri'] 20 | end 21 | 22 | 23 | function do_remap() 24 | local uri = ts.client_request.get_uri() 25 | 26 | if uri == nil then 27 | return 0 28 | end 29 | 30 | ts.ctx['uri'] = uri 31 | 32 | if uri == '/st' then 33 | ts.client_request.set_uri('/echo/123456') 34 | end 35 | 36 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 37 | 38 | return 0 39 | end 40 | 41 | -------------------------------------------------------------------------------- /example/test_creq_uri_args.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Args'] = ts.ctx['args'] 20 | end 21 | 22 | 23 | function do_remap() 24 | local args = ts.client_request.get_uri_args() 25 | 26 | if args ~= nil then 27 | ts.ctx['args'] = args 28 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 29 | return 0 30 | end 31 | 32 | ts.client_request.set_uri_args('hero=am&skill=burning') 33 | 34 | return 0 35 | end 36 | 37 | -------------------------------------------------------------------------------- /example/test_dup.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 20 | return 0 21 | end 22 | 23 | function send_response() 24 | ts.client_response.header['Ng'] = {'a', 'b', 'c'} 25 | -- ts.client_response.header['Ng'] = 'Hello world' 26 | end 27 | 28 | -------------------------------------------------------------------------------- /example/test_escape.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | uri = 'https://github.com/portl4t/ts-lua' 20 | escape = ts.escape_uri(uri) 21 | unescape = ts.unescape_uri(escape) 22 | print(escape) 23 | print(unescape) 24 | return 0 25 | end 26 | 27 | -------------------------------------------------------------------------------- /example/test_fetch.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | if ts.ctx['flen'] ~= nil then 20 | ts.client_response.header['Flen'] = ts.ctx['flen'] 21 | end 22 | end 23 | 24 | function post_remap() 25 | local url = string.format('http://%s/foo.txt', ts.ctx['host']) 26 | local hdr = { 27 | ['Host'] = ts.ctx['host'], 28 | ['User-Agent'] = 'dummy', 29 | } 30 | 31 | local res = ts.fetch(url, {method = 'GET', header=hdr}) 32 | 33 | if res.status == 200 then 34 | ts.ctx['flen'] = string.len(res.body) 35 | print(res.body) 36 | end 37 | end 38 | 39 | 40 | function do_remap() 41 | local inner = ts.http.is_internal_request() 42 | if inner ~= 0 then 43 | return 0 44 | end 45 | 46 | local host = ts.client_request.header['Host'] 47 | ts.ctx['host'] = host 48 | 49 | ts.hook(TS_LUA_HOOK_POST_REMAP, post_remap) 50 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 51 | end 52 | 53 | -------------------------------------------------------------------------------- /example/test_fetch_multi.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function process_combo(host) 20 | local url1 = string.format('http://%s/css/1.css', host) 21 | local url2 = string.format('http://%s/css/2.css', host) 22 | local url3 = string.format('http://%s/css/3.css', host) 23 | 24 | local hdr = { 25 | ['Host'] = host, 26 | ['User-Agent'] = 'blur blur', 27 | } 28 | 29 | local ct = { 30 | header = hdr, 31 | method = 'GET' 32 | } 33 | 34 | local arr = ts.fetch_multi( 35 | { 36 | {url1, ct}, 37 | {url2, ct}, 38 | {url3, ct}, 39 | }) 40 | 41 | local ctype = arr[1].header['Content-Type'] 42 | local body = arr[1].body .. arr[2].body .. arr[3].body 43 | 44 | local resp = 'HTTP/1.1 200 OK\r\n' .. 45 | 'Server: ATS/5.2.0\r\n' .. 46 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 47 | 'Cache-Control: max-age=7200\r\n' .. 48 | 'Accept-Ranges: bytes\r\n' .. 49 | 'Content-Type: ' .. ctype .. '\r\n' .. 50 | 'Content-Length: ' .. string.format('%d', string.len(body)) .. '\r\n\r\n' .. 51 | body 52 | 53 | ts.say(resp) 54 | end 55 | 56 | function do_remap() 57 | local inner = ts.http.is_internal_request() 58 | if inner ~= 0 then 59 | return 0 60 | end 61 | 62 | local h = ts.client_request.header['Host'] 63 | ts.http.intercept(process_combo, h) 64 | end 65 | -------------------------------------------------------------------------------- /example/test_fetch_post.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | local BODY = 'The Last Emperor.' 18 | local BODY_LEN = string.len(BODY) 19 | 20 | function post_remap() 21 | local url = string.format('http://%s/foo.txt', ts.ctx['host']) 22 | local hdr = { 23 | ['Host'] = ts.ctx['host'], 24 | ['User-Agent'] = 'Custom', 25 | ['Content-Length'] = string.format('%d', BODY_LEN), 26 | } 27 | 28 | local ot = { 29 | method = 'POST', 30 | header = hdr, 31 | body = BODY 32 | } 33 | 34 | local res = ts.fetch(url, ot) 35 | print(res.status) 36 | if res.status == 200 then 37 | print(res.body) 38 | end 39 | end 40 | 41 | 42 | function do_remap() 43 | local inner = ts.http.is_internal_request() 44 | if inner ~= 0 then 45 | return 0 46 | end 47 | 48 | local host = ts.client_request.header['Host'] 49 | ts.ctx['host'] = host 50 | 51 | ts.hook(TS_LUA_HOOK_POST_REMAP, post_remap) 52 | end 53 | -------------------------------------------------------------------------------- /example/test_flush.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function send_data() 20 | ss = 'wo ai yu ye hua\n' 21 | local resp = 'HTTP/1.0 200 OK\r\n' .. 22 | 'Server: ATS/3.2.0\r\n' .. 23 | 'Content-Type: text/plain\r\n' .. 24 | 'Content-Length: ' .. string.format('%d', 5*string.len(ss)) .. '\r\n' .. 25 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 26 | 'Connection: keep-alive\r\n' .. 27 | 'Cache-Control: max-age=7200\r\n' .. 28 | 'Accept-Ranges: bytes\r\n\r\n' 29 | ts.say(resp) 30 | for i=1, 5 do 31 | ts.say(ss) 32 | ts.flush() 33 | end 34 | end 35 | 36 | function do_remap() 37 | ts.http.intercept(send_data) 38 | return 0 39 | end 40 | 41 | -------------------------------------------------------------------------------- /example/test_intercept.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function send_data() 20 | local nt = os.time()..' Zheng.\n' 21 | local resp = 'HTTP/1.0 200 OK\r\n' .. 22 | 'Server: ATS/5.2.0\r\n' .. 23 | 'Content-Type: text/plain\r\n' .. 24 | 'Content-Length: ' .. string.format('%d', string.len(nt)) .. '\r\n' .. 25 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 26 | 'Connection: keep-alive\r\n' .. 27 | 'Cache-Control: max-age=7200\r\n' .. 28 | 'Accept-Ranges: bytes\r\n\r\n' .. 29 | nt 30 | ts.say(resp) 31 | end 32 | 33 | function do_remap() 34 | ts.http.intercept(send_data) 35 | return 0 36 | end 37 | -------------------------------------------------------------------------------- /example/test_json.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | package.path = '/usr/local/luarocks-2.1.0/share/lua/5.1/?.lua;?.lua' 19 | package.cpath = '/usr/local/luarocks-2.1.0/lib/lua/5.1/?.so;?.so' 20 | 21 | local json = require("json") 22 | 23 | function send_response() 24 | ts.client_response.header['Json'] = ts.ctx['jstr'] 25 | return 0 26 | end 27 | 28 | 29 | function do_remap() 30 | local tab = {a = "b", "c", 123, d = 456} 31 | ts.ctx['jstr'] = json.encode(tab) 32 | -- ts.debug(json.encode(tab)) 33 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 34 | 35 | return 0 36 | end 37 | 38 | -------------------------------------------------------------------------------- /example/test_md5.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | uri = ts.client_request.get_uri() 20 | print(ts.md5(uri)) 21 | return 0 22 | end 23 | 24 | -------------------------------------------------------------------------------- /example/test_path.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | ts.add_package_path('/home/quehan/programming/lua/pac/?.lua') 18 | ts.add_package_cpath('/home/quehan/programming/lua/module/?.so') 19 | 20 | local nt = require("nt") 21 | local ma = require("ma") 22 | 23 | function do_remap() 24 | print(nt.t9(7979)) 25 | print(ma.ft()) 26 | return 0 27 | end 28 | 29 | -------------------------------------------------------------------------------- /example/test_redirect.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | ts.http.redirect('http://www.taobao.com/') 20 | return TS_LUA_REMAP_DID_REMAP_STOP 21 | end 22 | 23 | -------------------------------------------------------------------------------- /example/test_regex.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | 19 | function do_remap() 20 | 21 | local ret = ts.re.match('Hello World', '<(.*)>(.*)<(.*)>') 22 | 23 | if ret 24 | then 25 | print('match') 26 | -- print(ret[0]) 27 | -- print(ret[1]) 28 | -- print(ret[2]) 29 | end 30 | 31 | return 0 32 | end 33 | 34 | -------------------------------------------------------------------------------- /example/test_remap1.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Singer'] = 'S.H.E.' 20 | return 0 21 | end 22 | 23 | 24 | function do_remap() 25 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 26 | return TS_LUA_REMAP_NO_REMAP_STOP 27 | end 28 | 29 | -------------------------------------------------------------------------------- /example/test_remap2.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Song'] = 'Wo ai yu ye hua.' 20 | return 0 21 | end 22 | 23 | 24 | function do_remap() 25 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 26 | return TS_LUA_REMAP_NO_REMAP 27 | end 28 | 29 | -------------------------------------------------------------------------------- /example/test_ret_403.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Now'] = ts.now() 20 | return 0 21 | end 22 | 23 | 24 | function do_remap() 25 | 26 | uri = ts.client_request.get_uri() 27 | 28 | pos, len = string.find(uri, '/css/') 29 | if pos ~= nil then 30 | ts.http.set_resp(403, "Document access failed :)\n") 31 | return 0 32 | end 33 | 34 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 35 | 36 | return 0 37 | end 38 | 39 | -------------------------------------------------------------------------------- /example/test_server_intercept.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | require 'os' 18 | 19 | function process_combo(host) 20 | local url1 = string.format('http://%s/css/1.css', host) 21 | local url2 = string.format('http://%s/css/2.css', host) 22 | local url3 = string.format('http://%s/css/3.css', host) 23 | 24 | local hdr = { 25 | ['Host'] = host, 26 | ['User-Agent'] = 'blur blur', 27 | } 28 | 29 | local ct = { 30 | header = hdr, 31 | method = 'GET' 32 | } 33 | 34 | local arr = ts.fetch_multi( 35 | { 36 | {url1, ct}, 37 | {url2, ct}, 38 | {url3, ct}, 39 | }) 40 | 41 | local ctype = arr[1].header['Content-Type'] 42 | local body = arr[1].body .. arr[2].body .. arr[3].body 43 | 44 | local resp = 'HTTP/1.1 200 OK\r\n' .. 45 | 'Server: ATS/5.2.0\r\n' .. 46 | 'Last-Modified: ' .. os.date("%a, %d %b %Y %H:%M:%S GMT", os.time()) .. '\r\n' .. 47 | 'Cache-Control: max-age=7200\r\n' .. 48 | 'Accept-Ranges: bytes\r\n' .. 49 | 'Content-Type: ' .. ctype .. '\r\n' .. 50 | 'Content-Length: ' .. string.format('%d', string.len(body)) .. '\r\n\r\n' .. 51 | body 52 | 53 | print('done') 54 | ts.say(resp) 55 | end 56 | 57 | function do_remap() 58 | local inner = ts.http.is_internal_request() 59 | if inner ~= 0 then 60 | return 0 61 | end 62 | 63 | local h = ts.client_request.header['Host'] 64 | ts.http.server_intercept(process_combo, h) 65 | end 66 | -------------------------------------------------------------------------------- /example/test_server_request.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function send_request() 18 | local uri = ts.server_request.get_uri() 19 | print(uri) 20 | end 21 | 22 | function do_remap() 23 | ts.hook(TS_LUA_HOOK_SEND_REQUEST_HDR, send_request) 24 | return 0 25 | end 26 | 27 | -------------------------------------------------------------------------------- /example/test_sha1.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function do_remap() 19 | uri = ts.client_request.get_uri() 20 | print(uri) 21 | print(ts.sha1(uri)) 22 | return 0 23 | end 24 | 25 | -------------------------------------------------------------------------------- /example/test_shdict_keys.lua: -------------------------------------------------------------------------------- 1 | 2 | 3 | local ft = ts.shared.DICT('fruit') 4 | 5 | function do_remap() 6 | ft:set('apple', 5) 7 | ft:set('banana', 9) 8 | ft:set('cherry', 78) 9 | kt = ft:get_keys() 10 | 11 | for k, v in pairs(kt) do 12 | print(k) 13 | print(v) 14 | end 15 | end 16 | 17 | -------------------------------------------------------------------------------- /example/test_sleep.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | function send_response() 19 | ts.client_response.header['Rhost'] = ts.ctx['rhost'] 20 | ts.sleep(1) 21 | 22 | return 0 23 | end 24 | 25 | function read_response() 26 | local rs = ts.server_response.header['Server'] 27 | if rs ~= nil then 28 | ts.server_response.header['Rserver'] = string.reverse(rs) 29 | end 30 | 31 | ts.sleep(1) 32 | 33 | return 0 34 | end 35 | 36 | 37 | function do_remap() 38 | local req_host = ts.client_request.header.Host 39 | 40 | if req_host == nil then 41 | return 0 42 | end 43 | 44 | ts.ctx['rhost'] = string.reverse(req_host) 45 | 46 | ts.hook(TS_LUA_HOOK_READ_RESPONSE_HDR, read_response) 47 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 48 | 49 | return 0 50 | end 51 | 52 | -------------------------------------------------------------------------------- /example/test_transform.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | local APPEND_DATA = 'TAIL\n' 19 | 20 | function append_transform(data, eos) 21 | if ts.ctx['len_set'] == nil then 22 | local sz = ts.http.resp_transform.get_upstream_bytes() 23 | 24 | if sz ~= TS_LUA_INT64_MAX then 25 | ts.http.resp_transform.set_downstream_bytes(sz + string.len(APPEND_DATA)) 26 | end 27 | 28 | ts.ctx['len_set'] = true 29 | end 30 | 31 | if eos == 1 then 32 | return data .. APPEND_DATA, eos 33 | 34 | else 35 | return data, eos 36 | end 37 | end 38 | 39 | 40 | function do_remap() 41 | ts.hook(TS_LUA_RESPONSE_TRANSFORM, append_transform) 42 | 43 | ts.http.resp_cache_transformed(0) 44 | ts.http.resp_cache_untransformed(1) 45 | return 0 46 | end 47 | -------------------------------------------------------------------------------- /example/test_url.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | function send_request() 18 | print(ts.server_request.header['Host']) 19 | end 20 | 21 | function do_remap() 22 | ts.client_request.set_url_host('192.168.231.129') 23 | ts.client_request.set_url_port('9090') 24 | ts.hook(TS_LUA_HOOK_SEND_REQUEST_HDR, send_request) 25 | return TS_LUA_REMAP_DID_REMAP 26 | end 27 | 28 | -------------------------------------------------------------------------------- /example/test_xml.lua: -------------------------------------------------------------------------------- 1 | -- Licensed to the Apache Software Foundation (ASF) under one 2 | -- or more contributor license agreements. See the NOTICE file 3 | -- distributed with this work for additional information 4 | -- regarding copyright ownership. The ASF licenses this file 5 | -- to you under the Apache License, Version 2.0 (the 6 | -- "License"); you may not use this file except in compliance 7 | -- with the License. You may obtain a copy of the License at 8 | -- 9 | -- http://www.apache.org/licenses/LICENSE-2.0 10 | -- 11 | -- Unless required by applicable law or agreed to in writing, software 12 | -- distributed under the License is distributed on an "AS IS" BASIS, 13 | -- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | -- See the License for the specific language governing permissions and 15 | -- limitations under the License. 16 | 17 | 18 | require("LuaXml") 19 | 20 | local xfile = xml.load("/home/quehan/programming/lua/rocks/test.xml") 21 | local item = xfile:find("item") 22 | 23 | function send_response() 24 | ts.client_response.header['Item'] = item.id 25 | return 0 26 | end 27 | 28 | 29 | function do_remap() 30 | ts.hook(TS_LUA_HOOK_SEND_RESPONSE_HDR, send_response) 31 | return 0 32 | end 33 | 34 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: .c .o .lo 2 | 3 | COMPILE = $(CC) -Wall -Wno-deprecated-declarations -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -g 4 | INC_PATH = -Imodules -I/home/quehan/opt/master/include 5 | LIB_PATH = -L/usr/local/lib -lssl -llua-5.1 -lpcre -ltcl 6 | 7 | TS_LUA_SHARED_OBJS = \ 8 | ts_lua.lo \ 9 | ts_lua_string.lo \ 10 | ts_lua_client_request.lo \ 11 | ts_lua_client_response.lo \ 12 | ts_lua_server_request.lo \ 13 | ts_lua_server_response.lo \ 14 | ts_lua_cached_response.lo \ 15 | ts_lua_util.lo \ 16 | ts_lua_remap.lo \ 17 | ts_lua_hook.lo \ 18 | ts_lua_context.lo \ 19 | ts_lua_misc.lo \ 20 | ts_lua_http.lo \ 21 | ts_lua_transform.lo \ 22 | ts_lua_log.lo \ 23 | ts_lua_http_intercept.lo \ 24 | ts_lua_regex.lo \ 25 | ts_lua_http_config.lo \ 26 | ts_lua_crypto.lo \ 27 | ts_lua_hash_table.lo \ 28 | ts_lua_mgmt.lo \ 29 | ts_lua_http_cntl.lo \ 30 | ts_lua_shared_dict.lo \ 31 | ts_lua_package.lo \ 32 | ts_lua_constant.lo \ 33 | ts_lua_coroutine.lo \ 34 | ts_lua_fetch.lo \ 35 | ts_lua_io.lo \ 36 | ts_lua_cache.lo 37 | 38 | TS_LUA_LIB_SHARED_OBJS = \ 39 | lib/ts_fetcher.lo 40 | 41 | ALL_OBJS = $(TS_LUA_SHARED_OBJS) $(TS_LUA_LIB_SHARED_OBJS) 42 | 43 | ALL_PRGS = 44 | ALL_LIBS = libtslua.so 45 | 46 | all: $(ALL_OBJS) $(ALL_PRGS) $(ALL_LIBS) 47 | 48 | libtslua.so: 49 | $(COMPILE) -o $@ $< -shared $(TS_LUA_SHARED_OBJS) $(TS_LUA_LIB_SHARED_OBJS) $(LIB_PATH) 50 | .c: 51 | $(COMPILE) -o $@ $< $(TS_LUA_SHARED_OBJS) $(LIB_PATH) $(INC_PATH) 52 | .c.o: 53 | $(COMPILE) -c -o $@ $< $(INC_PATH) 54 | .c.lo: 55 | $(COMPILE) -c -fPIC -o $@ $< $(INC_PATH) 56 | install: 57 | /bin/cp -f $(ALL_LIBS) /usr/lib64/trafficserver/plugins/ 58 | clean: 59 | rm -f $(ALL_OBJS) $(ALL_PRGS) $(ALL_LIBS) 60 | 61 | -------------------------------------------------------------------------------- /src/lib/ts_fetcher.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _TS_FETCHER_H 3 | #define _TS_FETCHER_H 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define TS_EVENT_FETCH_HEADER_DONE 63000 16 | #define TS_EVENT_FETCH_BODY_READY 63001 17 | #define TS_EVENT_FETCH_BODY_COMPLETE 63002 18 | #define TS_EVENT_FETCH_ERROR 63003 19 | #define TS_EVENT_FETCH_BODY_QUIET 63004 20 | 21 | #define TS_FLAG_FETCH_FORCE_DECHUNK (1<<0) 22 | #define TS_FLAG_FETCH_IGNORE_HEADER_DONE (1<<1) 23 | #define TS_FLAG_FETCH_IGNORE_BODY_READY (1<<2) 24 | #define TS_FLAG_FETCH_USE_NEW_LOCK (1<<3) 25 | 26 | #define TS_MARK_FETCH_RESP_LOW_WATER (4*1024) // we should reenable read_vio when resp_buffer data less than this 27 | #define TS_MARK_FETCH_BODY_LOW_WATER (4*1024) // we should move data from resp_buffer to body_buffer when body_buffer data less than this 28 | #define TS_MARK_FETCH_BODY_HIGH_WATER (16*1024) // we should not move data from resp_buffer to body_buffer more than this 29 | 30 | 31 | typedef enum { 32 | TS_FETCH_HTTP_METHOD_DUMMY, 33 | TS_FETCH_HTTP_METHOD_GET, 34 | TS_FETCH_HTTP_METHOD_POST, 35 | TS_FETCH_HTTP_METHOD_CONNECT, 36 | TS_FETCH_HTTP_METHOD_DELETE, 37 | TS_FETCH_HTTP_METHOD_HEAD, 38 | TS_FETCH_HTTP_METHOD_PURGE, 39 | TS_FETCH_HTTP_METHOD_PUT, 40 | TS_FETCH_HTTP_METHOD_LAST 41 | } http_method; 42 | 43 | typedef enum { 44 | BODY_READY = 0, 45 | BODY_COMPLETE, 46 | BODY_ERROR, 47 | } http_body_state; 48 | 49 | enum ChunkedState 50 | { 51 | CHUNK_WAIT_LENGTH, 52 | CHUNK_WAIT_RETURN, 53 | CHUNK_WAIT_DATA, 54 | CHUNK_WAIT_RETURN_END, 55 | CHUNK_DATA_DONE 56 | }; 57 | 58 | 59 | typedef struct { 60 | int state; 61 | 62 | int frag_total; 63 | int frag_len; 64 | char frag_buf[16]; 65 | unsigned char frag_pos; 66 | 67 | unsigned done:1; 68 | unsigned cr:1; 69 | unsigned dechunk_enabled:1; 70 | } chunked_info; 71 | 72 | typedef struct { 73 | TSVConn http_vc; 74 | TSVIO read_vio; 75 | TSVIO write_vio; 76 | 77 | http_method method; 78 | 79 | TSHttpParser http_parser; // http response parser 80 | 81 | TSMBuffer hdr_bufp; // HTTPHdr, parse result of response header 82 | TSMLoc hdr_loc; // HTTPHdr->m_http 83 | 84 | TSIOBuffer hdr_buffer; // buffer to store the response header, migration from resp_buffer 85 | TSIOBufferReader hdr_reader; 86 | 87 | TSIOBuffer resp_buffer; // buffer to store the raw response 88 | TSIOBufferReader resp_reader; 89 | 90 | TSIOBuffer body_buffer; // buffer to store the response body, migration from resp_buffer 91 | TSIOBufferReader body_reader; 92 | 93 | TSIOBuffer flow_buffer; // buffer to control flow for response body 94 | TSIOBufferReader flow_reader; 95 | 96 | TSIOBuffer req_buffer; // buffer to store the request 97 | TSIOBufferReader req_reader; 98 | 99 | TSCont contp; 100 | TSMutex mutexp; 101 | 102 | TSCont fetch_contp; 103 | TSAction action; 104 | 105 | struct sockaddr aip; 106 | 107 | int64_t resp_cl; // content-length of resp 108 | int64_t resp_already; // verify content-length 109 | 110 | int64_t post_cl; 111 | int64_t post_already; 112 | 113 | void *ctx; 114 | int status_code; 115 | int flags; 116 | int ref; 117 | 118 | chunked_info cinfo; 119 | unsigned header_done:1; 120 | unsigned body_done:1; 121 | unsigned deleted:1; 122 | unsigned chunked:1; 123 | unsigned error:1; 124 | unsigned launched:1; 125 | unsigned stopped:1; 126 | // unsigned init_with_str:1; 127 | } http_fetcher; 128 | 129 | 130 | http_fetcher * ts_http_fetcher_create(TSCont contp, struct sockaddr *addr, int flags); 131 | void ts_http_fetcher_destroy(http_fetcher *fch); 132 | 133 | void ts_http_fetcher_init(http_fetcher *fch, const char *method, int method_len, const char *uri, int uri_len); 134 | void ts_http_fetcher_init_common(http_fetcher *fch, int method, const char *uri, int uri_len); 135 | void ts_http_fetcher_add_header(http_fetcher *fch, const char *name, int name_len, const char *value, int value_len); 136 | void ts_http_fetcher_append_data(http_fetcher *fch, const char *data, int len); 137 | void ts_http_fetcher_copy_data(http_fetcher *fch, TSIOBufferReader readerp, int64_t length, int64_t offset); 138 | void ts_http_fetcher_launch(http_fetcher *fch); 139 | void ts_http_fetcher_set_high_water(http_fetcher *fch, int64_t max); 140 | void ts_http_fetcher_consume_resp_body(http_fetcher *fch, int64_t len); 141 | 142 | void ts_http_fetcher_set_ctx(http_fetcher *fch, void *ctx); 143 | void * ts_http_fetcher_get_ctx(http_fetcher *fch); 144 | 145 | #ifdef __cplusplus 146 | } 147 | #endif 148 | 149 | #endif 150 | -------------------------------------------------------------------------------- /src/ts_lua.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include 21 | #include 22 | #include 23 | #include "ts_lua_util.h" 24 | 25 | #define TS_LUA_MAX_STATE_COUNT 128 26 | 27 | static uint64_t ts_lua_http_next_id = 0; 28 | static ts_lua_main_ctx *ts_lua_main_ctx_array = NULL; 29 | 30 | TSReturnCode 31 | TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size) 32 | { 33 | int ret; 34 | 35 | if (!api_info || api_info->size < sizeof(TSRemapInterface)) { 36 | strncpy(errbuf, "[TSRemapInit] - Incorrect size of TSRemapInterface structure", errbuf_size - 1); 37 | return TS_ERROR; 38 | } 39 | 40 | if (ts_lua_main_ctx_array != NULL) 41 | return TS_SUCCESS; 42 | 43 | ts_lua_main_ctx_array = TSmalloc(sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT); 44 | memset(ts_lua_main_ctx_array, 0, sizeof(ts_lua_main_ctx) * TS_LUA_MAX_STATE_COUNT); 45 | 46 | ret = ts_lua_create_vm(ts_lua_main_ctx_array, TS_LUA_MAX_STATE_COUNT); 47 | 48 | if (ret) { 49 | ee("TSRemapInit failed, ts_lua version: %s", TS_LUA_RELEASE_VERSION); 50 | 51 | ts_lua_destroy_vm(ts_lua_main_ctx_array, TS_LUA_MAX_STATE_COUNT); 52 | TSfree(ts_lua_main_ctx_array); 53 | return TS_ERROR; 54 | } 55 | 56 | return TS_SUCCESS; 57 | } 58 | 59 | TSReturnCode 60 | TSRemapNewInstance(int argc, char* argv[], void** ih, char* errbuf, int errbuf_size) 61 | { 62 | int fn; 63 | int ret; 64 | 65 | if (argc < 3) { 66 | strncpy(errbuf, "[TSRemapNewInstance] - lua script file or string is required !!", errbuf_size - 1); 67 | return TS_ERROR; 68 | } 69 | 70 | fn = 1; 71 | 72 | if (argv[2][0] != '/') { 73 | fn = 0; 74 | 75 | } else if (strlen(argv[2]) >= TS_LUA_MAX_SCRIPT_FNAME_LENGTH - 16) { 76 | return TS_ERROR; 77 | } 78 | 79 | ts_lua_instance_conf *conf = TSmalloc(sizeof(ts_lua_instance_conf)); 80 | 81 | if (!conf) { 82 | fprintf(stderr, "[%s] TSmalloc failed !!\n", __FUNCTION__); 83 | return TS_ERROR; 84 | } 85 | 86 | memset(conf, 0, sizeof(ts_lua_instance_conf)); 87 | 88 | if (fn) { 89 | sprintf(conf->script, "%s", argv[2]); 90 | 91 | } else { 92 | conf->content = argv[2]; 93 | } 94 | 95 | ts_lua_init_instance(conf); 96 | 97 | ret = ts_lua_add_module(conf, ts_lua_main_ctx_array, TS_LUA_MAX_STATE_COUNT, argc-2, &argv[2]); 98 | 99 | if (ret != 0) { 100 | fprintf(stderr, "[%s] ts_lua_add_module failed\n", __FUNCTION__); 101 | return TS_ERROR; 102 | } 103 | 104 | *ih = conf; 105 | 106 | return TS_SUCCESS; 107 | } 108 | 109 | void 110 | TSRemapDeleteInstance(void* ih) 111 | { 112 | ts_lua_del_module((ts_lua_instance_conf*)ih, ts_lua_main_ctx_array, TS_LUA_MAX_STATE_COUNT); 113 | ts_lua_del_instance(ih); 114 | TSfree(ih); 115 | return; 116 | } 117 | 118 | TSRemapStatus 119 | TSRemapDoRemap(void* ih, TSHttpTxn rh, TSRemapRequestInfo *rri) 120 | { 121 | int ret; 122 | uint64_t req_id; 123 | TSCont contp; 124 | lua_State *L; 125 | ts_lua_main_ctx *main_ctx; 126 | ts_lua_http_ctx *http_ctx; 127 | ts_lua_cont_info *ci; 128 | ts_lua_instance_conf *instance_conf; 129 | 130 | instance_conf = (ts_lua_instance_conf*)ih; 131 | req_id = __sync_fetch_and_add(&ts_lua_http_next_id, 1); 132 | 133 | main_ctx = &ts_lua_main_ctx_array[req_id%TS_LUA_MAX_STATE_COUNT]; 134 | 135 | TSMutexLock(main_ctx->mutexp); 136 | 137 | http_ctx = ts_lua_create_http_ctx(main_ctx, instance_conf); 138 | 139 | http_ctx->txnp = rh; 140 | http_ctx->client_request_bufp = rri->requestBufp; 141 | http_ctx->client_request_hdrp = rri->requestHdrp; 142 | http_ctx->client_request_url = rri->requestUrl; 143 | http_ctx->rri = rri; 144 | 145 | ci = &http_ctx->cinfo; 146 | L = ci->routine.lua; 147 | 148 | contp = TSContCreate(ts_lua_http_cont_handler, NULL); 149 | TSContDataSet(contp, http_ctx); 150 | 151 | ci->contp = contp; 152 | ci->mutex = TSContMutexGet((TSCont)rh); 153 | 154 | // push do_remap function on the stack, and no async operation should exist here. 155 | lua_getglobal(L, TS_LUA_FUNCTION_REMAP); 156 | 157 | if (lua_pcall(L, 0, 1, 0) != 0) { 158 | ee("lua_pcall failed: %s", lua_tostring(L, -1)); 159 | ret = TSREMAP_NO_REMAP; 160 | 161 | } else { 162 | ret = lua_tointeger(L, -1); 163 | } 164 | 165 | lua_pop(L, 1); // pop the result 166 | 167 | if (http_ctx->hooks > 0) { 168 | TSMutexUnlock(main_ctx->mutexp); 169 | TSHttpTxnHookAdd(rh, TS_HTTP_TXN_CLOSE_HOOK, contp); 170 | 171 | } else { 172 | ts_lua_destroy_http_ctx(http_ctx); 173 | TSMutexUnlock(main_ctx->mutexp); 174 | } 175 | 176 | return ret; 177 | } 178 | -------------------------------------------------------------------------------- /src/ts_lua_cache.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | #ifndef _TS_LUA_CACHE_H 20 | #define _TS_LUA_CACHE_H 21 | 22 | #include "ts_lua_common.h" 23 | 24 | struct cache_info; 25 | typedef int (*cache_fn)(ts_lua_cont_info *ci, struct cache_info *info, TSEvent event, void *data); 26 | 27 | typedef struct cache_info { 28 | TSCont contp; // should be destroyed only in cleanup 29 | 30 | TSCacheKey cache_key; 31 | TSVConn cache_vc; 32 | TSAction cache_action; 33 | ts_lua_io_handle ioh; 34 | ts_lua_io_handle reserved; 35 | 36 | int64_t already; 37 | int64_t need; 38 | int64_t sz; 39 | int64_t seek; // Todo: for do_io_pread 40 | cache_fn current_handler; 41 | int optype; 42 | 43 | int hit:1; 44 | int eof:1; 45 | int err:1; 46 | int wait:1; 47 | } ts_lua_cache_info; 48 | 49 | void ts_lua_inject_cache_api(lua_State *L); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /src/ts_lua_cached_response.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | 23 | #define TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx) \ 24 | do { \ 25 | TSMBuffer bufp; \ 26 | TSMLoc hdrp; \ 27 | if (!http_ctx->cached_response_hdrp) { \ 28 | if (TSHttpTxnCachedRespGet(http_ctx->txnp, \ 29 | &bufp, \ 30 | &hdrp) != TS_SUCCESS) { \ 31 | return 0; \ 32 | } \ 33 | http_ctx->cached_response_bufp = TSMBufferCreate(); \ 34 | http_ctx->cached_response_hdrp = TSHttpHdrCreate(http_ctx->cached_response_bufp); \ 35 | TSHttpHdrCopy(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, bufp, hdrp); \ 36 | TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdrp); \ 37 | } \ 38 | } while(0) 39 | 40 | 41 | static void ts_lua_inject_cached_response_misc_api(lua_State *L); 42 | static void ts_lua_inject_cached_response_header_api(lua_State *L); 43 | static void ts_lua_inject_cached_response_headers_api(lua_State *L); 44 | 45 | static int ts_lua_cached_response_header_get(lua_State *L); 46 | static int ts_lua_cached_response_header_set(lua_State *L); 47 | static int ts_lua_cached_response_get_headers(lua_State *L); 48 | 49 | static int ts_lua_cached_response_get_status(lua_State *L); 50 | static int ts_lua_cached_response_get_version(lua_State *L); 51 | 52 | 53 | void 54 | ts_lua_inject_cached_response_api(lua_State *L) 55 | { 56 | lua_newtable(L); 57 | 58 | ts_lua_inject_cached_response_header_api(L); 59 | ts_lua_inject_cached_response_headers_api(L); 60 | ts_lua_inject_cached_response_misc_api(L); 61 | 62 | lua_setfield(L, -2, "cached_response"); 63 | } 64 | 65 | static void 66 | ts_lua_inject_cached_response_header_api(lua_State *L) 67 | { 68 | lua_newtable(L); /* .header */ 69 | 70 | lua_createtable(L, 0, 2); 71 | 72 | lua_pushcfunction(L, ts_lua_cached_response_header_get); 73 | lua_setfield(L, -2, "__index"); 74 | lua_pushcfunction(L, ts_lua_cached_response_header_set); 75 | lua_setfield(L, -2, "__newindex"); 76 | 77 | lua_setmetatable(L, -2); 78 | 79 | lua_setfield(L, -2, "header"); 80 | 81 | return; 82 | } 83 | 84 | static void 85 | ts_lua_inject_cached_response_headers_api(lua_State *L) 86 | { 87 | lua_pushcfunction(L, ts_lua_cached_response_get_headers); 88 | lua_setfield(L, -2, "get_headers"); 89 | } 90 | 91 | static void 92 | ts_lua_inject_cached_response_misc_api(lua_State *L) 93 | { 94 | lua_pushcfunction(L, ts_lua_cached_response_get_status); 95 | lua_setfield(L, -2, "get_status"); 96 | 97 | lua_pushcfunction(L, ts_lua_cached_response_get_version); 98 | lua_setfield(L, -2, "get_version"); 99 | } 100 | 101 | static int 102 | ts_lua_cached_response_get_status(lua_State *L) 103 | { 104 | int status; 105 | ts_lua_http_ctx *http_ctx; 106 | 107 | http_ctx = ts_lua_get_http_ctx(L); 108 | 109 | TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); 110 | 111 | status = TSHttpHdrStatusGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp); 112 | 113 | lua_pushinteger(L, status); 114 | 115 | return 1; 116 | } 117 | 118 | static int 119 | ts_lua_cached_response_get_version(lua_State *L) 120 | { 121 | int version; 122 | char buf[32]; 123 | int n; 124 | 125 | ts_lua_http_ctx *http_ctx; 126 | 127 | http_ctx = ts_lua_get_http_ctx(L); 128 | 129 | TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); 130 | 131 | version = TSHttpHdrVersionGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp); 132 | 133 | n = snprintf(buf, sizeof(buf)-1, "%d.%d", TS_HTTP_MAJOR(version), TS_HTTP_MINOR(version)); 134 | lua_pushlstring(L, buf, n); 135 | 136 | return 1; 137 | } 138 | 139 | static int 140 | ts_lua_cached_response_header_get(lua_State *L) 141 | { 142 | const char *key; 143 | const char *val; 144 | int val_len; 145 | size_t key_len; 146 | 147 | TSMLoc field_loc; 148 | ts_lua_http_ctx *http_ctx; 149 | 150 | http_ctx = ts_lua_get_http_ctx(L); 151 | 152 | /* we skip the first argument that is the table */ 153 | key = luaL_checklstring(L, 2, &key_len); 154 | 155 | TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); 156 | 157 | if (key && key_len) { 158 | field_loc = TSMimeHdrFieldFind(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, key, key_len); 159 | 160 | if (field_loc) { 161 | val = TSMimeHdrFieldValueStringGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc, -1, &val_len); 162 | lua_pushlstring(L, val, val_len); 163 | TSHandleMLocRelease(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc); 164 | 165 | } else { 166 | lua_pushnil(L); 167 | } 168 | 169 | } else { 170 | lua_pushnil(L); 171 | } 172 | 173 | return 1; 174 | } 175 | 176 | static int 177 | ts_lua_cached_response_header_set(lua_State *L) 178 | { 179 | return 0; 180 | } 181 | 182 | static int 183 | ts_lua_cached_response_get_headers(lua_State *L) 184 | { 185 | const char *name; 186 | const char *value; 187 | int name_len; 188 | int value_len; 189 | TSMLoc field_loc; 190 | TSMLoc next_field_loc; 191 | 192 | ts_lua_http_ctx *http_ctx; 193 | 194 | http_ctx = ts_lua_get_http_ctx(L); 195 | 196 | TS_LUA_CHECK_CACHED_RESPONSE_HDR(http_ctx); 197 | 198 | lua_newtable(L); 199 | 200 | field_loc = TSMimeHdrFieldGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, 0); 201 | 202 | while (field_loc) { 203 | 204 | name = TSMimeHdrFieldNameGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc, &name_len); 205 | if (name && name_len) { 206 | 207 | value = TSMimeHdrFieldValueStringGet(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc, -1, &value_len); 208 | lua_pushlstring(L, name, name_len); 209 | lua_pushlstring(L, value, value_len); 210 | lua_rawset(L, -3); 211 | } 212 | 213 | next_field_loc = TSMimeHdrFieldNext(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc); 214 | TSHandleMLocRelease(http_ctx->cached_response_bufp, http_ctx->cached_response_hdrp, field_loc); 215 | field_loc = next_field_loc; 216 | } 217 | 218 | return 1; 219 | } 220 | 221 | -------------------------------------------------------------------------------- /src/ts_lua_cached_response.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CACHED_RESPONSE_H 21 | #define _TS_LUA_CACHED_RESPONSE_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_cached_response_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_client_request.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CLIENT_REQUEST_H 21 | #define _TS_LUA_CLIENT_REQUEST_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_client_request_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_client_response.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CLIENT_RESPONSE_H 21 | #define _TS_LUA_CLIENT_RESPONSE_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_client_response_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_COMMON_H 21 | #define _TS_LUA_COMMON_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | #include 31 | #include 32 | 33 | #include 34 | #include 35 | #include 36 | #include "ts_lua_coroutine.h" 37 | 38 | #define TS_LUA_RELEASE_VERSION "v0.1.6" 39 | 40 | #define TS_LUA_FUNCTION_REMAP "do_remap" 41 | #define TS_LUA_FUNCTION_POST_REMAP "do_post_remap" 42 | #define TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE "do_cache_lookup_complete" 43 | #define TS_LUA_FUNCTION_SEND_REQUEST "do_send_request" 44 | #define TS_LUA_FUNCTION_READ_RESPONSE "do_read_response" 45 | #define TS_LUA_FUNCTION_SEND_RESPONSE "do_send_response" 46 | 47 | #define TS_LUA_EVENT_COROUTINE_CONT 20000 48 | 49 | #define TS_LUA_DEBUG_TAG "ts_lua" 50 | 51 | #define TS_LUA_MAX_SCRIPT_FNAME_LENGTH 1024 52 | #define TS_LUA_MAX_CONFIG_VARS_COUNT 256 53 | #define TS_LUA_MAX_SHARED_DICT_NAME_LENGTH 128 54 | #define TS_LUA_MAX_SHARED_DICT_COUNT 32 55 | #define TS_LUA_MAX_URL_LENGTH 2048 56 | #define TS_LUA_MAX_OVEC_SIZE (3 * 32) 57 | #define TS_LUA_MAX_RESIDENT_PCRE 64 58 | 59 | #define TS_LUA_MAKE_VAR_ITEM(X) {X, #X} 60 | 61 | #define ee(...) fprintf(stderr, "Lua *** %s: ", __func__); \ 62 | fprintf(stderr, __VA_ARGS__); \ 63 | fprintf(stderr, " @%s:%d\n", __FILE__, __LINE__) 64 | 65 | 66 | /* for http config or cntl var */ 67 | typedef struct { 68 | int64_t nvar; 69 | char *svar; 70 | } ts_lua_var64_item; 71 | 72 | typedef struct { 73 | int nvar; 74 | char *svar; 75 | } ts_lua_var_item; 76 | 77 | /* for dict */ 78 | typedef struct { 79 | Tcl_HashTable t; 80 | TSMutex mutexp; 81 | } ts_lua_hash_map; 82 | 83 | typedef struct { 84 | uint16_t ksize; // sizeof(long) or strlen(key) 85 | uint16_t vsize; // 0 or strlen(val) 86 | 87 | union 88 | { 89 | int64_t n; 90 | char *s; 91 | } v; 92 | 93 | char vtype; 94 | } ts_lua_shared_dict_item; 95 | 96 | typedef struct { 97 | char name[TS_LUA_MAX_SHARED_DICT_NAME_LENGTH]; 98 | ts_lua_hash_map map; 99 | int64_t quota; 100 | int64_t used; 101 | int flags; 102 | int initialized:1; 103 | } ts_lua_shared_dict; 104 | 105 | /* plugin instance conf */ 106 | typedef struct { 107 | char *content; 108 | char script[TS_LUA_MAX_SCRIPT_FNAME_LENGTH]; 109 | void *conf_vars[TS_LUA_MAX_CONFIG_VARS_COUNT]; 110 | 111 | ts_lua_hash_map regex_map; 112 | ts_lua_shared_dict shdict[TS_LUA_MAX_SHARED_DICT_COUNT]; 113 | int shdict_n; 114 | 115 | int _first: 1; // create current instance for 1st ts_lua_main_ctx 116 | int _last: 1; // create current instance for the last ts_lua_main_ctx 117 | 118 | } ts_lua_instance_conf; 119 | 120 | /* lua state for http request */ 121 | typedef struct { 122 | ts_lua_cont_info cinfo; 123 | 124 | TSHttpTxn txnp; 125 | TSMBuffer client_request_bufp; 126 | TSMLoc client_request_hdrp; 127 | TSMLoc client_request_url; 128 | 129 | TSMBuffer server_request_bufp; 130 | TSMLoc server_request_hdrp; 131 | TSMLoc server_request_url; 132 | 133 | TSMBuffer server_response_bufp; 134 | TSMLoc server_response_hdrp; 135 | 136 | TSMBuffer client_response_bufp; 137 | TSMLoc client_response_hdrp; 138 | 139 | TSMBuffer cached_response_bufp; 140 | TSMLoc cached_response_hdrp; 141 | 142 | TSRemapRequestInfo *rri; 143 | ts_lua_instance_conf *instance_conf; 144 | uint32_t hooks; 145 | 146 | } ts_lua_http_ctx; 147 | 148 | 149 | typedef struct { 150 | TSVIO vio; 151 | TSIOBuffer buffer; 152 | TSIOBufferReader reader; 153 | } ts_lua_io_handle; 154 | 155 | typedef struct { 156 | ts_lua_cont_info cinfo; 157 | 158 | ts_lua_io_handle output; 159 | ts_lua_io_handle reserved; 160 | 161 | ts_lua_http_ctx *hctx; 162 | int64_t upstream_bytes; 163 | int64_t downstream_bytes; 164 | int64_t total; 165 | } ts_lua_http_transform_ctx; 166 | 167 | typedef struct { 168 | ts_lua_cont_info cinfo; 169 | 170 | ts_lua_io_handle input; 171 | ts_lua_io_handle output; 172 | 173 | TSVConn net_vc; 174 | ts_lua_http_ctx *hctx; 175 | 176 | int64_t to_flush; 177 | int reuse:1; 178 | int recv_complete:1; 179 | int send_complete:1; 180 | int all_ready:1; 181 | } ts_lua_http_intercept_ctx; 182 | 183 | 184 | #define TS_LUA_RELEASE_IO_HANDLE(ih) do { \ 185 | if (ih->reader) { \ 186 | TSIOBufferReaderFree(ih->reader); \ 187 | ih->reader = NULL; \ 188 | } \ 189 | if (ih->buffer) { \ 190 | TSIOBufferDestroy(ih->buffer); \ 191 | ih->buffer = NULL; \ 192 | } \ 193 | } while (0) 194 | 195 | #endif 196 | -------------------------------------------------------------------------------- /src/ts_lua_constant.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_constant.h" 21 | 22 | 23 | typedef enum { 24 | TS_LUA_INT64_MAX = INT64_MAX, 25 | TS_LUA_INT64_MIN = INT64_MIN, 26 | TS_LUA_INT32_MAX = INT32_MAX, 27 | TS_LUA_INT32_MIN = INT32_MIN, 28 | TS_LUA_UINT32_MAX = UINT32_MAX, 29 | } TSLuaConstantNumbers; 30 | 31 | 32 | ts_lua_var64_item ts_lua_number_vars[] = { 33 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_INT64_MAX), 34 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_INT64_MIN), 35 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_INT32_MAX), 36 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_INT32_MIN), 37 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_UINT32_MAX) 38 | }; 39 | 40 | 41 | static void ts_lua_inject_number_variables(lua_State *L); 42 | 43 | 44 | void 45 | ts_lua_inject_constant_api(lua_State *L) 46 | { 47 | ts_lua_inject_number_variables(L); 48 | } 49 | 50 | static void 51 | ts_lua_inject_number_variables(lua_State *L) 52 | { 53 | int i; 54 | 55 | for (i = 0; i < sizeof(ts_lua_number_vars) / sizeof(ts_lua_var64_item); i++) { 56 | lua_pushinteger(L, ts_lua_number_vars[i].nvar); 57 | lua_setglobal(L, ts_lua_number_vars[i].svar); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/ts_lua_constant.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CONSTANT_H 21 | #define _TS_LUA_CONSTANT_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_constant_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_context.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | static char ts_http_context_key; 23 | 24 | static int ts_lua_context_get(lua_State *L); 25 | static int ts_lua_context_set(lua_State *L); 26 | 27 | 28 | void 29 | ts_lua_inject_context_api(lua_State *L) 30 | { 31 | lua_newtable(L); /* .ctx */ 32 | 33 | lua_createtable(L, 0, 2); /* metatable for context */ 34 | 35 | lua_pushcfunction(L, ts_lua_context_get); 36 | lua_setfield(L, -2, "__index"); 37 | lua_pushcfunction(L, ts_lua_context_set); 38 | lua_setfield(L, -2, "__newindex"); 39 | 40 | lua_setmetatable(L, -2); 41 | 42 | lua_setfield(L, -2, "ctx"); 43 | } 44 | 45 | void 46 | ts_lua_create_context_table(lua_State *L) 47 | { 48 | lua_pushlightuserdata(L, &ts_http_context_key); 49 | lua_newtable(L); 50 | lua_rawset(L, LUA_GLOBALSINDEX); 51 | } 52 | 53 | 54 | static int 55 | ts_lua_context_get(lua_State *L) 56 | { 57 | const char *key; 58 | size_t key_len; 59 | 60 | key = luaL_checklstring(L, 2, &key_len); 61 | 62 | if (key && key_len) { 63 | lua_pushlightuserdata(L, &ts_http_context_key); 64 | lua_rawget(L, LUA_GLOBALSINDEX); // get the context table 65 | 66 | lua_pushlstring(L, key, key_len); 67 | lua_rawget(L, -2); 68 | 69 | } else { 70 | lua_pushnil(L); 71 | } 72 | 73 | return 1; 74 | } 75 | 76 | static int 77 | ts_lua_context_set(lua_State *L) 78 | { 79 | const char *key; 80 | size_t key_len; 81 | 82 | key = luaL_checklstring(L, 2, &key_len); 83 | 84 | lua_pushlightuserdata(L, &ts_http_context_key); 85 | lua_rawget(L, LUA_GLOBALSINDEX); // get the context table -3 86 | 87 | lua_pushlstring(L, key, key_len); // push key -2 88 | lua_pushvalue(L, 3); // push value -1 89 | 90 | lua_rawset(L, -3); 91 | lua_pop(L, 1); // pop the context table 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /src/ts_lua_context.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CONTEXT_H 21 | #define _TS_LUA_CONTEXT_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_context_api(lua_State *L); 26 | void ts_lua_create_context_table(lua_State *L); 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /src/ts_lua_coroutine.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | #include "ts_lua_coroutine.h" 20 | 21 | static inline void ts_lua_async_push_item(ts_lua_async_item **head, ts_lua_async_item *node); 22 | static inline void ts_lua_async_destroy_item(ts_lua_async_item *node); 23 | static inline void ts_lua_async_destroy_chain(ts_lua_async_item **head); 24 | 25 | 26 | inline ts_lua_async_item * 27 | ts_lua_async_create_item(TSCont cont, async_clean func, void *d, ts_lua_cont_info *ci) 28 | { 29 | ts_lua_async_item *ai; 30 | 31 | ai = (ts_lua_async_item*)TSmalloc(sizeof(ts_lua_async_item)); 32 | if (ai == NULL) 33 | return NULL; 34 | 35 | ai->cinfo = ci; 36 | 37 | ai->cleanup = func; 38 | ai->data = d; 39 | ai->contp = cont; 40 | ai->deleted = 0; 41 | 42 | ts_lua_async_push_item(&ci->async_chain, ai); 43 | 44 | return ai; 45 | } 46 | 47 | static inline void 48 | ts_lua_async_push_item(ts_lua_async_item **head, ts_lua_async_item *node) 49 | { 50 | node->next = *head; 51 | *head = node; 52 | } 53 | 54 | inline void 55 | ts_lua_async_destroy_item(ts_lua_async_item *node) 56 | { 57 | if (node->cleanup && !node->deleted) { 58 | node->cleanup(node); 59 | } 60 | 61 | TSfree(node); 62 | } 63 | 64 | inline void 65 | ts_lua_async_destroy_chain(ts_lua_async_item **head) 66 | { 67 | ts_lua_async_item *node, *next; 68 | 69 | node = *head; 70 | 71 | while (node) { 72 | next = node->next; 73 | ts_lua_async_destroy_item(node); 74 | node = next; 75 | } 76 | } 77 | 78 | inline void 79 | ts_lua_release_cont_info(ts_lua_cont_info *ci) 80 | { 81 | ts_lua_main_ctx *mctx; 82 | ts_lua_coroutine *crt; 83 | 84 | crt = &ci->routine; 85 | mctx = crt->mctx; 86 | 87 | ts_lua_async_destroy_chain(&ci->async_chain); 88 | 89 | if (ci->contp) { 90 | TSContDestroy(ci->contp); 91 | } 92 | 93 | if (crt->lua) { 94 | TSMutexLock(mctx->mutexp); 95 | luaL_unref(crt->lua, LUA_REGISTRYINDEX, crt->ref); 96 | TSMutexUnlock(mctx->mutexp); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/ts_lua_coroutine.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | #ifndef _TS_LUA_COROUTINE_H 20 | #define _TS_LUA_COROUTINE_H 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | 29 | struct async_item; 30 | typedef int (*async_clean)(struct async_item *item); 31 | 32 | /* main context*/ 33 | typedef struct { 34 | lua_State *lua; // basic lua vm, injected 35 | TSMutex mutexp; // mutex for lua vm 36 | int gref; // reference for lua vm self, in reg table 37 | } ts_lua_main_ctx; 38 | 39 | /* coroutine */ 40 | typedef struct { 41 | ts_lua_main_ctx *mctx; 42 | lua_State *lua; // derived lua_thread 43 | int ref; // reference for lua_thread, in REG Table 44 | } ts_lua_coroutine; 45 | 46 | /* continuation info */ 47 | typedef struct { 48 | ts_lua_coroutine routine; 49 | TSCont contp; // continuation for the routine 50 | TSMutex mutex; // mutex for continuation 51 | struct async_item *async_chain; // async_item list 52 | } ts_lua_cont_info; 53 | 54 | 55 | /* asynchronous item */ 56 | typedef struct async_item { 57 | struct async_item *next; 58 | ts_lua_cont_info *cinfo; 59 | 60 | TSCont contp; // continuation for the async operation 61 | void *data; // private data 62 | 63 | async_clean cleanup; // cleanup function 64 | int deleted:1; 65 | } ts_lua_async_item; 66 | 67 | 68 | ts_lua_async_item * ts_lua_async_create_item(TSCont cont, async_clean func, void *d, ts_lua_cont_info *ci); 69 | void ts_lua_release_cont_info(ts_lua_cont_info *ci); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /src/ts_lua_crypto.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | #include 20 | #include 21 | #include "ts_lua_string.h" 22 | #include "ts_lua_util.h" 23 | 24 | 25 | #define TS_LUA_MD5_DIGEST_LENGTH 16 26 | #define TS_LUA_SHA_DIGEST_LENGTH 20 27 | 28 | static int ts_lua_md5(lua_State *L); 29 | static int ts_lua_md5_bin(lua_State *L); 30 | 31 | static int ts_lua_sha1(lua_State *L); 32 | static int ts_lua_sha1_bin(lua_State *L); 33 | 34 | static int ts_lua_base64_encode(lua_State *L); 35 | static int ts_lua_base64_decode(lua_State *L); 36 | 37 | static int ts_lua_escape_uri(lua_State *L); 38 | static int ts_lua_unescape_uri(lua_State *L); 39 | 40 | 41 | void 42 | ts_lua_inject_crypto_api(lua_State *L) 43 | { 44 | /* ts.md5() */ 45 | lua_pushcfunction(L, ts_lua_md5); 46 | lua_setfield(L, -2, "md5"); 47 | 48 | /* ts.md5_bin(...) */ 49 | lua_pushcfunction(L, ts_lua_md5_bin); 50 | lua_setfield(L, -2, "md5_bin"); 51 | 52 | /* ts.sha1_bin(...) */ 53 | lua_pushcfunction(L, ts_lua_sha1); 54 | lua_setfield(L, -2, "sha1"); 55 | 56 | /* ts.sha1_bin(...) */ 57 | lua_pushcfunction(L, ts_lua_sha1_bin); 58 | lua_setfield(L, -2, "sha1_bin"); 59 | 60 | /* ts.base64_encode(...) */ 61 | lua_pushcfunction(L, ts_lua_base64_encode); 62 | lua_setfield(L, -2, "base64_encode"); 63 | 64 | /* ts.base64_decode(...) */ 65 | lua_pushcfunction(L, ts_lua_base64_decode); 66 | lua_setfield(L, -2, "base64_decode"); 67 | 68 | /* ts.escape_uri(...) */ 69 | lua_pushcfunction(L, ts_lua_escape_uri); 70 | lua_setfield(L, -2, "escape_uri"); 71 | 72 | /* ts.unescape_uri(...) */ 73 | lua_pushcfunction(L, ts_lua_unescape_uri); 74 | lua_setfield(L, -2, "unescape_uri"); 75 | } 76 | 77 | static int 78 | ts_lua_md5(lua_State *L) 79 | { 80 | u_char *src; 81 | size_t slen; 82 | 83 | MD5_CTX md5_ctx; 84 | u_char md5_buf[TS_LUA_MD5_DIGEST_LENGTH]; 85 | u_char hex_buf[2 * sizeof(md5_buf)]; 86 | 87 | if (lua_gettop(L) != 1) { 88 | return luaL_error(L, "expecting one argument"); 89 | } 90 | 91 | if (lua_isnil(L, 1)) { 92 | src = (u_char *) ""; 93 | slen = 0; 94 | 95 | } else { 96 | src = (u_char *) luaL_checklstring(L, 1, &slen); 97 | } 98 | 99 | MD5_Init(&md5_ctx); 100 | MD5_Update(&md5_ctx, src, slen); 101 | MD5_Final(md5_buf, &md5_ctx); 102 | 103 | ts_lua_hex_dump(hex_buf, md5_buf, sizeof(md5_buf)); 104 | 105 | lua_pushlstring(L, (char *) hex_buf, sizeof(hex_buf)); 106 | 107 | return 1; 108 | } 109 | 110 | static int 111 | ts_lua_md5_bin(lua_State *L) 112 | { 113 | u_char *src; 114 | size_t slen; 115 | 116 | MD5_CTX md5_ctx; 117 | u_char md5_buf[TS_LUA_MD5_DIGEST_LENGTH]; 118 | 119 | if (lua_gettop(L) != 1) { 120 | return luaL_error(L, "expecting one argument"); 121 | } 122 | 123 | if (lua_isnil(L, 1)) { 124 | src = (u_char *) ""; 125 | slen = 0; 126 | 127 | } else { 128 | src = (u_char *) luaL_checklstring(L, 1, &slen); 129 | } 130 | 131 | MD5_Init(&md5_ctx); 132 | MD5_Update(&md5_ctx, src, slen); 133 | MD5_Final(md5_buf, &md5_ctx); 134 | 135 | lua_pushlstring(L, (char *) md5_buf, sizeof(md5_buf)); 136 | 137 | return 1; 138 | } 139 | 140 | static int 141 | ts_lua_sha1(lua_State *L) 142 | { 143 | u_char *src; 144 | size_t slen; 145 | 146 | SHA_CTX sha; 147 | u_char sha_buf[TS_LUA_SHA_DIGEST_LENGTH]; 148 | u_char hex_buf[2 * sizeof(sha_buf)]; 149 | 150 | if (lua_gettop(L) != 1) { 151 | return luaL_error(L, "expecting one argument"); 152 | } 153 | 154 | if (lua_isnil(L, 1)) { 155 | src = (u_char *)""; 156 | slen = 0; 157 | 158 | } else { 159 | src = (u_char *)luaL_checklstring(L, 1, &slen); 160 | } 161 | 162 | SHA1_Init(&sha); 163 | SHA1_Update(&sha, src, slen); 164 | SHA1_Final(sha_buf, &sha); 165 | 166 | ts_lua_hex_dump(hex_buf, sha_buf, sizeof(sha_buf)); 167 | lua_pushlstring(L, (char *)hex_buf, sizeof(hex_buf)); 168 | 169 | return 1; 170 | } 171 | 172 | static int 173 | ts_lua_sha1_bin(lua_State *L) 174 | { 175 | u_char *src; 176 | size_t slen; 177 | 178 | SHA_CTX sha; 179 | u_char sha_buf[TS_LUA_SHA_DIGEST_LENGTH]; 180 | 181 | if (lua_gettop(L) != 1) { 182 | return luaL_error(L, "expecting one argument"); 183 | } 184 | 185 | if (lua_isnil(L, 1)) { 186 | src = (u_char *)""; 187 | slen = 0; 188 | 189 | } else { 190 | src = (u_char *)luaL_checklstring(L, 1, &slen); 191 | } 192 | 193 | SHA1_Init(&sha); 194 | SHA1_Update(&sha, src, slen); 195 | SHA1_Final(sha_buf, &sha); 196 | 197 | lua_pushlstring(L, (char *)sha_buf, sizeof(sha_buf)); 198 | 199 | return 1; 200 | } 201 | 202 | static int 203 | ts_lua_base64_encode(lua_State *L) 204 | { 205 | u_char *src; 206 | u_char *dst; 207 | size_t slen; 208 | size_t dlen; 209 | 210 | if (lua_gettop(L) != 1) { 211 | return luaL_error(L, "expecting one argument"); 212 | } 213 | 214 | if (lua_isnil(L, 1)) { 215 | src = (u_char *)""; 216 | slen = 0; 217 | 218 | } else { 219 | src = (u_char*)luaL_checklstring(L, 1, &slen); 220 | } 221 | 222 | dlen = ts_lua_base64_encoded_length(slen); 223 | 224 | dst = lua_newuserdata(L, dlen); 225 | 226 | ts_lua_encode_base64(dst, &dlen, src, slen); 227 | 228 | lua_pushlstring(L, (char*)dst, dlen); 229 | 230 | return 1; 231 | } 232 | 233 | static int 234 | ts_lua_base64_decode(lua_State *L) 235 | { 236 | u_char *src; 237 | u_char *dst; 238 | size_t slen; 239 | size_t dlen; 240 | 241 | if (lua_gettop(L) != 1) { 242 | return luaL_error(L, "expecting one argument"); 243 | } 244 | 245 | if (lua_isnil(L, 1)) { 246 | src = (u_char *)""; 247 | slen = 0; 248 | 249 | } else { 250 | src = (u_char*)luaL_checklstring(L, 1, &slen); 251 | } 252 | 253 | dlen = ts_lua_base64_decoded_length(slen); 254 | 255 | dst = lua_newuserdata(L, dlen); 256 | 257 | if (ts_lua_decode_base64(dst, &dlen, src, slen) == 0) { 258 | lua_pushlstring(L, (char*)dst, dlen); 259 | 260 | } else { 261 | lua_pushnil(L); 262 | } 263 | 264 | return 1; 265 | } 266 | 267 | static int 268 | ts_lua_escape_uri(lua_State *L) 269 | { 270 | size_t len, dlen; 271 | u_char *src, *dst; 272 | uintptr_t escape; 273 | 274 | if (lua_gettop(L) != 1) { 275 | return luaL_error(L, "expecting one argument for ts.escape_uri(...)"); 276 | } 277 | 278 | if (lua_isnil(L, 1)) { 279 | lua_pushliteral(L, ""); 280 | return 1; 281 | } 282 | 283 | src = (u_char*)luaL_checklstring(L, 1, &len); 284 | 285 | if (len == 0) 286 | return 1; 287 | 288 | escape = 2 * ts_lua_escape_internal(NULL, src, len, TS_ESCAPE_URI); 289 | 290 | if (escape) { 291 | dlen = escape + len; 292 | dst = lua_newuserdata(L, dlen); 293 | ts_lua_escape_internal(dst, src, len, TS_ESCAPE_URI); 294 | lua_pushlstring(L, (char *) dst, dlen); 295 | } 296 | 297 | return 1; 298 | } 299 | 300 | static int 301 | ts_lua_unescape_uri(lua_State *L) 302 | { 303 | size_t len, dlen; 304 | u_char *p; 305 | u_char *src, *dst; 306 | 307 | if (lua_gettop(L) != 1) { 308 | return luaL_error(L, "expecting one argument for ts.unescape_uri(...)"); 309 | } 310 | 311 | if (lua_isnil(L, 1)) { 312 | lua_pushliteral(L, ""); 313 | return 1; 314 | } 315 | 316 | src = (u_char *) luaL_checklstring(L, 1, &len); 317 | 318 | /* the unescaped string can only be smaller */ 319 | dlen = len; 320 | 321 | p = lua_newuserdata(L, dlen); 322 | 323 | dst = p; 324 | 325 | ts_lua_unescape_internal(&dst, &src, len, TS_UNESCAPE_URI_COMPONENT); 326 | 327 | lua_pushlstring(L, (char *) p, dst - p); 328 | 329 | return 1; 330 | } 331 | 332 | -------------------------------------------------------------------------------- /src/ts_lua_crypto.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_CRYPTO_H 21 | #define _TS_LUA_CRYPTO_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_crypto_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_fetch.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | #ifndef _TS_LUA_FETCH_H 20 | #define _TS_LUA_FETCH_H 21 | 22 | #include "ts_lua_common.h" 23 | #include "lib/ts_fetcher.h" 24 | 25 | struct fetch_multi_info; 26 | 27 | typedef struct { 28 | TSCont contp; 29 | struct fetch_multi_info *fmi; 30 | 31 | TSIOBuffer buffer; 32 | TSIOBufferReader reader; 33 | http_fetcher *fch; 34 | 35 | int over:1; 36 | int failed:1; 37 | } ts_lua_fetch_info; 38 | 39 | typedef struct fetch_multi_info { 40 | TSCont contp; // should be destroyed only in cleanup 41 | int multi; // invoke from ts.fetch_multi 42 | int total; 43 | int done; 44 | ts_lua_fetch_info fiv[0]; 45 | } ts_lua_fetch_multi_info; 46 | 47 | void ts_lua_inject_fetch_api(lua_State *L); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/ts_lua_hash_table.c: -------------------------------------------------------------------------------- 1 | 2 | #include "ts_lua_hash_table.h" 3 | 4 | 5 | static Tcl_HashEntry * 6 | ts_lua_hash_table_iterator_first(Tcl_HashTable *ht_ptr, Tcl_HashSearch * state_ptr) 7 | { 8 | Tcl_HashTable *tcl_ht_ptr; 9 | Tcl_HashSearch *tcl_search_state_ptr; 10 | Tcl_HashEntry *tcl_he_ptr; 11 | Tcl_HashEntry *he_ptr; 12 | 13 | tcl_ht_ptr = (Tcl_HashTable *) ht_ptr; 14 | tcl_search_state_ptr = (Tcl_HashSearch *) state_ptr; 15 | 16 | tcl_he_ptr = Tcl_FirstHashEntry(tcl_ht_ptr, tcl_search_state_ptr); 17 | he_ptr = tcl_he_ptr; 18 | 19 | return he_ptr; 20 | } 21 | 22 | static Tcl_HashEntry * 23 | ts_lua_hash_table_iterator_next(Tcl_HashTable *ht_ptr, Tcl_HashSearch * state_ptr) 24 | { 25 | Tcl_HashSearch *tcl_search_state_ptr; 26 | Tcl_HashEntry *tcl_he_ptr; 27 | Tcl_HashEntry *he_ptr; 28 | 29 | tcl_search_state_ptr = (Tcl_HashSearch *) state_ptr; 30 | 31 | tcl_he_ptr = Tcl_NextHashEntry(tcl_search_state_ptr); 32 | he_ptr = (Tcl_HashEntry*) tcl_he_ptr; 33 | 34 | return he_ptr; 35 | } 36 | 37 | char * 38 | ts_lua_hash_table_entry_key(Tcl_HashTable * ht_ptr, Tcl_HashEntry * entry_ptr) 39 | { 40 | char *tcl_key; 41 | 42 | tcl_key = (char*) Tcl_GetHashKey((Tcl_HashTable *) ht_ptr, (Tcl_HashEntry *) entry_ptr); 43 | return tcl_key; 44 | } 45 | 46 | ClientData 47 | ts_lua_hash_table_entry_value(Tcl_HashTable *ht_ptr, Tcl_HashEntry *entry_ptr) 48 | { 49 | ClientData tcl_value; 50 | 51 | tcl_value = Tcl_GetHashValue((Tcl_HashEntry *) entry_ptr); 52 | return tcl_value; 53 | } 54 | 55 | void 56 | ts_lua_hash_table_iterate(Tcl_HashTable *ht_ptr, TclHashEntryFunction func, void *data) 57 | { 58 | int retcode; 59 | Tcl_HashEntry *e; 60 | Tcl_HashSearch state; 61 | 62 | for (e = ts_lua_hash_table_iterator_first(ht_ptr, &state); e != NULL; e = ts_lua_hash_table_iterator_next(ht_ptr, &state)) { 63 | retcode = (*func) (ht_ptr, e, data); 64 | if (retcode != 0) 65 | break; 66 | } 67 | } 68 | 69 | int 70 | ts_lua_hash_table_lookup(Tcl_HashTable *ht_ptr, const char* key, ClientData *value_ptr) 71 | { 72 | Tcl_HashEntry *he_ptr; 73 | ClientData value; 74 | 75 | he_ptr = ts_lua_hash_table_lookup_entry(ht_ptr, key); 76 | if (he_ptr == NULL) 77 | return 0; 78 | 79 | value = ts_lua_hash_table_entry_value(ht_ptr, he_ptr); 80 | *value_ptr = value; 81 | return 1; 82 | } 83 | 84 | Tcl_HashEntry * 85 | ts_lua_hash_table_lookup_entry(Tcl_HashTable *ht_ptr, const char *key) 86 | { 87 | Tcl_HashTable *tcl_ht_ptr; 88 | Tcl_HashEntry *tcl_he_ptr; 89 | Tcl_HashEntry *he_ptr; 90 | 91 | tcl_ht_ptr = (Tcl_HashTable *) ht_ptr; 92 | tcl_he_ptr = Tcl_FindHashEntry(tcl_ht_ptr, key); 93 | he_ptr = tcl_he_ptr; 94 | 95 | return he_ptr; 96 | } 97 | 98 | -------------------------------------------------------------------------------- /src/ts_lua_hash_table.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _TS_LUA_HASH_TABLE_H 3 | #define _TS_LUA_HASH_TABLE_H 4 | 5 | #include "ts_lua_common.h" 6 | 7 | typedef int (*TclHashEntryFunction) (Tcl_HashTable *ht_ptr, Tcl_HashEntry *entry_ptr, void *data); 8 | 9 | void ts_lua_hash_table_iterate(Tcl_HashTable *ht, TclHashEntryFunction func, void *data); 10 | ClientData ts_lua_hash_table_entry_value(Tcl_HashTable *ht_ptr, Tcl_HashEntry *entry_ptr); 11 | 12 | char *ts_lua_hash_table_entry_key(Tcl_HashTable * ht_ptr, Tcl_HashEntry * entry_ptr); 13 | Tcl_HashEntry *ts_lua_hash_table_lookup_entry(Tcl_HashTable *ht_ptr, const char *key); 14 | 15 | int ts_lua_hash_table_lookup(Tcl_HashTable *ht_ptr, const char* key, ClientData *value_ptr); 16 | 17 | #endif 18 | 19 | -------------------------------------------------------------------------------- /src/ts_lua_hook.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_hook.h" 21 | #include "ts_lua_transform.h" 22 | #include "ts_lua_util.h" 23 | 24 | 25 | typedef enum { 26 | TS_LUA_HOOK_DUMMY = 0, 27 | TS_LUA_HOOK_POST_REMAP, 28 | TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE, 29 | TS_LUA_HOOK_SEND_REQUEST_HDR, 30 | TS_LUA_HOOK_READ_RESPONSE_HDR, 31 | TS_LUA_HOOK_SEND_RESPONSE_HDR, 32 | TS_LUA_REQUEST_TRANSFORM, 33 | TS_LUA_RESPONSE_TRANSFORM, 34 | TS_LUA_HOOK_LAST 35 | } TSLuaHookID; 36 | 37 | 38 | char * ts_lua_hook_id_string[] = { 39 | "TS_LUA_HOOK_DUMMY", 40 | "TS_LUA_HOOK_POST_REMAP", 41 | "TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE", 42 | "TS_LUA_HOOK_SEND_REQUEST_HDR", 43 | "TS_LUA_HOOK_READ_RESPONSE_HDR", 44 | "TS_LUA_HOOK_SEND_RESPONSE_HDR", 45 | "TS_LUA_REQUEST_TRANSFORM", 46 | "TS_LUA_RESPONSE_TRANSFORM", 47 | "TS_LUA_HOOK_LAST" 48 | }; 49 | 50 | 51 | static int ts_lua_add_hook(lua_State *L); 52 | static void ts_lua_inject_hook_variables(lua_State *L); 53 | 54 | 55 | void 56 | ts_lua_inject_hook_api(lua_State *L) 57 | { 58 | lua_pushcfunction(L, ts_lua_add_hook); 59 | lua_setfield(L, -2, "hook"); 60 | 61 | ts_lua_inject_hook_variables(L); 62 | } 63 | 64 | static void 65 | ts_lua_inject_hook_variables(lua_State *L) 66 | { 67 | int i; 68 | 69 | for (i = 0; i < sizeof(ts_lua_hook_id_string)/sizeof(char*); i++) { 70 | lua_pushinteger(L, i); 71 | lua_setglobal(L, ts_lua_hook_id_string[i]); 72 | } 73 | } 74 | 75 | static int 76 | ts_lua_add_hook(lua_State *L) 77 | { 78 | int type; 79 | int entry; 80 | TSVConn connp; 81 | ts_lua_http_ctx *http_ctx; 82 | ts_lua_cont_info *ci; 83 | 84 | http_ctx = ts_lua_get_http_ctx(L); 85 | ci = &http_ctx->cinfo; 86 | 87 | entry = lua_tointeger(L, 1); // get hook id 88 | 89 | type = lua_type(L, 2); 90 | if (type != LUA_TFUNCTION) 91 | return 0; 92 | 93 | switch (entry) { 94 | 95 | case TS_LUA_HOOK_POST_REMAP: 96 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_POST_REMAP_HOOK, ci->contp); 97 | lua_pushvalue(L, 2); 98 | lua_setglobal(L, TS_LUA_FUNCTION_POST_REMAP); 99 | http_ctx->hooks++; 100 | break; 101 | 102 | case TS_LUA_HOOK_CACHE_LOOKUP_COMPLETE: 103 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, ci->contp); 104 | lua_pushvalue(L, 2); 105 | lua_setglobal(L, TS_LUA_FUNCTION_CACHE_LOOKUP_COMPLETE); 106 | http_ctx->hooks++; 107 | break; 108 | 109 | case TS_LUA_HOOK_SEND_REQUEST_HDR: 110 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, ci->contp); 111 | lua_pushvalue(L, 2); 112 | lua_setglobal(L, TS_LUA_FUNCTION_SEND_REQUEST); 113 | http_ctx->hooks++; 114 | break; 115 | 116 | case TS_LUA_HOOK_READ_RESPONSE_HDR: 117 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, ci->contp); 118 | lua_pushvalue(L, 2); 119 | lua_setglobal(L, TS_LUA_FUNCTION_READ_RESPONSE); 120 | http_ctx->hooks++; 121 | break; 122 | 123 | case TS_LUA_HOOK_SEND_RESPONSE_HDR: 124 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, ci->contp); 125 | lua_pushvalue(L, 2); 126 | lua_setglobal(L, TS_LUA_FUNCTION_SEND_RESPONSE); 127 | http_ctx->hooks++; 128 | break; 129 | 130 | case TS_LUA_REQUEST_TRANSFORM: 131 | case TS_LUA_RESPONSE_TRANSFORM: 132 | connp = TSTransformCreate(ts_lua_transform_entry, http_ctx->txnp); 133 | ts_lua_create_http_transform_ctx(http_ctx, connp); 134 | 135 | if (entry == TS_LUA_REQUEST_TRANSFORM) { 136 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_REQUEST_TRANSFORM_HOOK, connp); 137 | 138 | } else { 139 | TSHttpTxnHookAdd(http_ctx->txnp, TS_HTTP_RESPONSE_TRANSFORM_HOOK, connp); 140 | } 141 | 142 | http_ctx->hooks++; 143 | break; 144 | 145 | default: 146 | break; 147 | } 148 | 149 | return 0; 150 | } 151 | -------------------------------------------------------------------------------- /src/ts_lua_hook.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_HOOK_H 21 | #define _TS_LUA_HOOK_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_hook_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_http.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | #include "ts_lua_http_intercept.h" 22 | #include "ts_lua_http_config.h" 23 | #include "ts_lua_http_cntl.h" 24 | 25 | typedef enum { 26 | TS_LUA_CACHE_LOOKUP_MISS, 27 | TS_LUA_CACHE_LOOKUP_HIT_STALE, 28 | TS_LUA_CACHE_LOOKUP_HIT_FRESH, 29 | TS_LUA_CACHE_LOOKUP_SKIPPED 30 | } TSLuaCacheLookupResult; 31 | 32 | char * ts_lua_cache_lookup_result_string[] = { 33 | "TS_LUA_CACHE_LOOKUP_MISS", 34 | "TS_LUA_CACHE_LOOKUP_HIT_STALE", 35 | "TS_LUA_CACHE_LOOKUP_HIT_FRESH", 36 | "TS_LUA_CACHE_LOOKUP_SKIPPED" 37 | }; 38 | 39 | static void ts_lua_inject_http_retset_api(lua_State *L); 40 | static void ts_lua_inject_http_cache_api(lua_State *L); 41 | static void ts_lua_inject_http_transform_api(lua_State *L); 42 | static void ts_lua_inject_http_misc_api(lua_State *L); 43 | 44 | static int ts_lua_http_set_retstatus(lua_State *L); 45 | static int ts_lua_http_set_retbody(lua_State *L); 46 | static int ts_lua_http_set_resp(lua_State *L); 47 | static int ts_lua_http_redirect(lua_State *L); 48 | 49 | static int ts_lua_http_get_cache_lookup_status(lua_State *L); 50 | static int ts_lua_http_set_cache_lookup_status(lua_State *L); 51 | static int ts_lua_http_set_cache_url(lua_State *L); 52 | 53 | static void ts_lua_inject_cache_lookup_result_variables(lua_State *L); 54 | 55 | static int ts_lua_http_resp_cache_transformed(lua_State *L); 56 | static int ts_lua_http_resp_cache_untransformed(lua_State *L); 57 | 58 | static int ts_lua_http_is_internal_request(lua_State *L); 59 | 60 | static void ts_lua_inject_http_resp_transform_api(lua_State *L); 61 | static int ts_lua_http_resp_transform_get_upstream_bytes(lua_State *L); 62 | static int ts_lua_http_resp_transform_set_downstream_bytes(lua_State *L); 63 | 64 | 65 | void 66 | ts_lua_inject_http_api(lua_State *L) 67 | { 68 | lua_newtable(L); 69 | 70 | ts_lua_inject_http_retset_api(L); 71 | ts_lua_inject_http_cache_api(L); 72 | ts_lua_inject_http_transform_api(L); 73 | ts_lua_inject_http_intercept_api(L); 74 | ts_lua_inject_http_config_api(L); 75 | ts_lua_inject_http_cntl_api(L); 76 | ts_lua_inject_http_misc_api(L); 77 | 78 | lua_setfield(L, -2, "http"); 79 | } 80 | 81 | static void 82 | ts_lua_inject_http_retset_api(lua_State *L) 83 | { 84 | lua_pushcfunction(L, ts_lua_http_set_retstatus); 85 | lua_setfield(L, -2, "set_retstatus"); 86 | 87 | lua_pushcfunction(L, ts_lua_http_set_retbody); 88 | lua_setfield(L, -2, "set_retbody"); 89 | 90 | lua_pushcfunction(L, ts_lua_http_set_resp); 91 | lua_setfield(L, -2, "set_resp"); 92 | 93 | lua_pushcfunction(L, ts_lua_http_redirect); 94 | lua_setfield(L, -2, "redirect"); 95 | } 96 | 97 | static void 98 | ts_lua_inject_http_cache_api(lua_State *L) 99 | { 100 | lua_pushcfunction(L, ts_lua_http_get_cache_lookup_status); 101 | lua_setfield(L, -2, "get_cache_lookup_status"); 102 | 103 | lua_pushcfunction(L, ts_lua_http_set_cache_lookup_status); 104 | lua_setfield(L, -2, "set_cache_lookup_status"); 105 | 106 | lua_pushcfunction(L, ts_lua_http_set_cache_url); 107 | lua_setfield(L, -2, "set_cache_url"); 108 | 109 | ts_lua_inject_cache_lookup_result_variables(L); 110 | } 111 | 112 | static void 113 | ts_lua_inject_http_transform_api(lua_State *L) 114 | { 115 | lua_pushcfunction(L, ts_lua_http_resp_cache_transformed); 116 | lua_setfield(L, -2, "resp_cache_transformed"); 117 | 118 | lua_pushcfunction(L, ts_lua_http_resp_cache_untransformed); 119 | lua_setfield(L, -2, "resp_cache_untransformed"); 120 | 121 | /* ts.http.resp_transform api */ 122 | lua_newtable(L); 123 | ts_lua_inject_http_resp_transform_api(L); 124 | lua_setfield(L, -2, "resp_transform"); 125 | } 126 | 127 | static void 128 | ts_lua_inject_http_resp_transform_api(lua_State *L) 129 | { 130 | lua_pushcfunction(L, ts_lua_http_resp_transform_get_upstream_bytes); 131 | lua_setfield(L, -2, "get_upstream_bytes"); 132 | 133 | lua_pushcfunction(L, ts_lua_http_resp_transform_set_downstream_bytes); 134 | lua_setfield(L, -2, "set_downstream_bytes"); 135 | } 136 | 137 | static void 138 | ts_lua_inject_http_misc_api(lua_State *L) 139 | { 140 | lua_pushcfunction(L, ts_lua_http_is_internal_request); 141 | lua_setfield(L, -2, "is_internal_request"); 142 | } 143 | 144 | static void 145 | ts_lua_inject_cache_lookup_result_variables(lua_State *L) 146 | { 147 | int i; 148 | 149 | for (i = 0; i < sizeof(ts_lua_cache_lookup_result_string)/sizeof(char*); i++) { 150 | lua_pushinteger(L, i); 151 | lua_setglobal(L, ts_lua_cache_lookup_result_string[i]); 152 | } 153 | } 154 | 155 | static int 156 | ts_lua_http_set_retstatus(lua_State *L) 157 | { 158 | int status; 159 | ts_lua_http_ctx *http_ctx; 160 | 161 | http_ctx = ts_lua_get_http_ctx(L); 162 | 163 | status = luaL_checkinteger(L, 1); 164 | TSHttpTxnSetHttpRetStatus(http_ctx->txnp, status); 165 | return 0; 166 | } 167 | 168 | static int 169 | ts_lua_http_set_retbody(lua_State *L) 170 | { 171 | const char *body; 172 | size_t body_len; 173 | ts_lua_http_ctx *http_ctx; 174 | 175 | http_ctx = ts_lua_get_http_ctx(L); 176 | 177 | body = luaL_checklstring(L, 1, &body_len); 178 | TSHttpTxnErrorBodySet(http_ctx->txnp, TSstrdup(body), body_len, NULL); // Defaults to text/html 179 | return 0; 180 | } 181 | 182 | static int 183 | ts_lua_http_set_resp(lua_State *L) 184 | { 185 | int n, status; 186 | const char *body; 187 | size_t body_len; 188 | ts_lua_http_ctx *http_ctx; 189 | 190 | http_ctx = ts_lua_get_http_ctx(L); 191 | 192 | n = lua_gettop(L); 193 | 194 | status = luaL_checkinteger(L, 1); 195 | TSHttpTxnSetHttpRetStatus(http_ctx->txnp, status); 196 | 197 | if (n == 2) { 198 | body = luaL_checklstring(L, 2, &body_len); 199 | TSHttpTxnErrorBodySet(http_ctx->txnp, TSstrdup(body), body_len, NULL); // Defaults to text/html 200 | } 201 | 202 | return 0; 203 | } 204 | 205 | static int 206 | ts_lua_http_redirect(lua_State *L) 207 | { 208 | int n, status; 209 | const char *start, *end; 210 | const char *url; 211 | size_t url_len; 212 | ts_lua_http_ctx *http_ctx; 213 | 214 | http_ctx = ts_lua_get_http_ctx(L); 215 | 216 | n = lua_gettop(L); 217 | 218 | if (n < 1) { 219 | return luaL_error(L, "ts.http.redirect expects at least one argument"); 220 | } 221 | 222 | url = luaL_checklstring(L, 1, &url_len); 223 | 224 | start = url; 225 | end = url + url_len; 226 | 227 | if (TSUrlParse(http_ctx->client_request_bufp, http_ctx->client_request_url, 228 | &start, end) == TS_PARSE_ERROR) { 229 | 230 | fprintf(stderr, "TSUrlParse failed, url: %s\n", url); 231 | return 0; 232 | } 233 | 234 | http_ctx->rri->redirect = 1; 235 | 236 | if (n >= 2) { 237 | status = luaL_checkinteger(L, 2); 238 | if (status > 0) { 239 | TSHttpTxnSetHttpRetStatus(http_ctx->txnp, status); 240 | } 241 | } 242 | 243 | return 0; 244 | } 245 | 246 | static int 247 | ts_lua_http_get_cache_lookup_status(lua_State *L) 248 | { 249 | int status; 250 | ts_lua_http_ctx *http_ctx; 251 | 252 | http_ctx = ts_lua_get_http_ctx(L); 253 | 254 | if (TSHttpTxnCacheLookupStatusGet(http_ctx->txnp, &status) == TS_ERROR) { 255 | lua_pushnil(L); 256 | 257 | } else { 258 | lua_pushnumber(L, status); 259 | } 260 | 261 | return 1; 262 | } 263 | 264 | static int 265 | ts_lua_http_set_cache_lookup_status(lua_State *L) 266 | { 267 | int status; 268 | ts_lua_http_ctx *http_ctx; 269 | 270 | http_ctx = ts_lua_get_http_ctx(L); 271 | 272 | status = luaL_checknumber(L, 1); 273 | 274 | TSHttpTxnCacheLookupStatusSet(http_ctx->txnp, status); 275 | 276 | return 0; 277 | } 278 | 279 | static int 280 | ts_lua_http_set_cache_url(lua_State *L) 281 | { 282 | const char *url; 283 | size_t url_len; 284 | 285 | ts_lua_http_ctx *http_ctx; 286 | 287 | http_ctx = ts_lua_get_http_ctx(L); 288 | 289 | url = luaL_checklstring(L, 1, &url_len); 290 | 291 | if (url && url_len) { 292 | TSCacheUrlSet(http_ctx->txnp, url, url_len); 293 | } 294 | 295 | return 0; 296 | } 297 | 298 | static int 299 | ts_lua_http_resp_cache_transformed(lua_State *L) 300 | { 301 | int action; 302 | ts_lua_http_ctx *http_ctx; 303 | 304 | http_ctx = ts_lua_get_http_ctx(L); 305 | 306 | action = luaL_checkinteger(L, 1); 307 | 308 | TSHttpTxnTransformedRespCache(http_ctx->txnp, action); 309 | 310 | return 0; 311 | } 312 | 313 | static int 314 | ts_lua_http_resp_cache_untransformed(lua_State *L) 315 | { 316 | int action; 317 | ts_lua_http_ctx *http_ctx; 318 | 319 | http_ctx = ts_lua_get_http_ctx(L); 320 | 321 | action = luaL_checkinteger(L, 1); 322 | 323 | TSHttpTxnUntransformedRespCache(http_ctx->txnp, action); 324 | 325 | return 0; 326 | } 327 | 328 | static int 329 | ts_lua_http_is_internal_request(lua_State *L) 330 | { 331 | TSReturnCode ret; 332 | ts_lua_http_ctx *http_ctx; 333 | 334 | http_ctx = ts_lua_get_http_ctx(L); 335 | 336 | ret = TSHttpIsInternalRequest(http_ctx->txnp); 337 | 338 | if (ret == TS_SUCCESS) { 339 | lua_pushnumber(L, 1); 340 | 341 | } else { 342 | lua_pushnumber(L, 0); 343 | } 344 | 345 | return 1; 346 | } 347 | 348 | static int 349 | ts_lua_http_resp_transform_get_upstream_bytes(lua_State *L) 350 | { 351 | ts_lua_http_transform_ctx *transform_ctx; 352 | 353 | transform_ctx = ts_lua_get_http_transform_ctx(L); 354 | 355 | lua_pushnumber(L, transform_ctx->upstream_bytes); 356 | 357 | return 1; 358 | } 359 | 360 | static int 361 | ts_lua_http_resp_transform_set_downstream_bytes(lua_State *L) 362 | { 363 | int64_t n; 364 | ts_lua_http_transform_ctx *transform_ctx; 365 | 366 | transform_ctx = ts_lua_get_http_transform_ctx(L); 367 | 368 | n = luaL_checkinteger(L, 1); 369 | 370 | transform_ctx->downstream_bytes = n; 371 | 372 | return 0; 373 | } 374 | 375 | -------------------------------------------------------------------------------- /src/ts_lua_http.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_HTTP_H 21 | #define _TS_LUA_HTTP_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_http_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_http_cntl.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | typedef enum { 23 | TS_LUA_HTTP_CNTL_GET_LOGGING_MODE = TS_HTTP_CNTL_GET_LOGGING_MODE, 24 | TS_LUA_HTTP_CNTL_SET_LOGGING_MODE = TS_HTTP_CNTL_SET_LOGGING_MODE, 25 | TS_LUA_HTTP_CNTL_GET_INTERCEPT_RETRY_MODE = TS_HTTP_CNTL_GET_INTERCEPT_RETRY_MODE, 26 | TS_LUA_HTTP_CNTL_SET_INTERCEPT_RETRY_MODE = TS_HTTP_CNTL_SET_INTERCEPT_RETRY_MODE 27 | } TSLuaHttpCntlType; 28 | 29 | 30 | ts_lua_var_item ts_lua_http_cntl_type_vars[] = { 31 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_HTTP_CNTL_GET_LOGGING_MODE), 32 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_HTTP_CNTL_SET_LOGGING_MODE), 33 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_HTTP_CNTL_GET_INTERCEPT_RETRY_MODE), 34 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_HTTP_CNTL_SET_INTERCEPT_RETRY_MODE) 35 | }; 36 | 37 | 38 | static void ts_lua_inject_http_cntl_variables(lua_State *L); 39 | 40 | static int ts_lua_http_cntl_set(lua_State *L); 41 | static int ts_lua_http_cntl_get(lua_State *L); 42 | 43 | 44 | void 45 | ts_lua_inject_http_cntl_api(lua_State *L) 46 | { 47 | ts_lua_inject_http_cntl_variables(L); 48 | 49 | lua_pushcfunction(L, ts_lua_http_cntl_set); 50 | lua_setfield(L, -2, "cntl_set"); 51 | 52 | lua_pushcfunction(L, ts_lua_http_cntl_get); 53 | lua_setfield(L, -2, "cntl_get"); 54 | } 55 | 56 | static void 57 | ts_lua_inject_http_cntl_variables(lua_State *L) 58 | { 59 | int i; 60 | 61 | for (i = 0; i < sizeof(ts_lua_http_cntl_type_vars) / sizeof(ts_lua_var_item); i++) { 62 | lua_pushinteger(L, ts_lua_http_cntl_type_vars[i].nvar); 63 | lua_setglobal(L, ts_lua_http_cntl_type_vars[i].svar); 64 | } 65 | } 66 | 67 | static int 68 | ts_lua_http_cntl_set(lua_State *L) 69 | { 70 | int cntl_type; 71 | int value; 72 | ts_lua_http_ctx *http_ctx; 73 | 74 | http_ctx = ts_lua_get_http_ctx(L); 75 | 76 | cntl_type = luaL_checkinteger(L, 1); 77 | value = luaL_checkinteger(L, 2); 78 | 79 | TSHttpTxnCntl(http_ctx->txnp, cntl_type, value ? TS_HTTP_CNTL_ON : TS_HTTP_CNTL_OFF); 80 | 81 | return 0; 82 | } 83 | 84 | static int 85 | ts_lua_http_cntl_get(lua_State *L) 86 | { 87 | int cntl_type; 88 | int64_t value; 89 | ts_lua_http_ctx *http_ctx; 90 | 91 | http_ctx = ts_lua_get_http_ctx(L); 92 | 93 | cntl_type = luaL_checkinteger(L, 1); 94 | 95 | TSHttpTxnCntl(http_ctx->txnp, cntl_type, &value); 96 | 97 | lua_pushnumber(L, value); 98 | 99 | return 1; 100 | } 101 | 102 | -------------------------------------------------------------------------------- /src/ts_lua_http_cntl.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_HTTP_CNTL_H 21 | #define _TS_LUA_HTTP_CNTL_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_http_cntl_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_http_config.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_HTTP_CONFIG_H 21 | #define _TS_LUA_HTTP_CONFIG_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_http_config_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_http_intercept.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_HTTP_INTERCEPT_H 21 | #define _TS_LUA_HTTP_INTERCEPT_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_http_intercept_api(lua_State *L); 26 | void ts_lua_inject_intercept_api(lua_State *L); 27 | 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /src/ts_lua_io.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_io.h" 21 | 22 | int64_t 23 | IOBufferReaderCopy(TSIOBufferReader readerp, void *buf, int64_t length) 24 | { 25 | int64_t avail, need, n; 26 | const char *start; 27 | TSIOBufferBlock blk; 28 | 29 | n = 0; 30 | blk = TSIOBufferReaderStart(readerp); 31 | 32 | while (blk) { 33 | start = TSIOBufferBlockReadStart(blk, readerp, &avail); 34 | need = length < avail ? length : avail; 35 | 36 | if (need > 0) { 37 | memcpy((char*)buf + n, start, need); 38 | length -= need; 39 | n += need; 40 | } 41 | 42 | if (length == 0) 43 | break; 44 | 45 | blk = TSIOBufferBlockNext(blk); 46 | } 47 | 48 | return n; 49 | } 50 | -------------------------------------------------------------------------------- /src/ts_lua_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_IO_H 21 | #define _TS_LUA_IO_H 22 | 23 | #include 24 | #include 25 | 26 | int64_t IOBufferReaderCopy(TSIOBufferReader readerp, void *buf, int64_t length); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/ts_lua_log.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | static TSTextLogObject log; 23 | 24 | static int ts_lua_log_object_creat(lua_State *L); 25 | static int ts_lua_log_object_write(lua_State *L); 26 | static int ts_lua_log_object_destroy(lua_State *L); 27 | 28 | 29 | static void ts_lua_inject_log_object_creat_api(lua_State *L); 30 | static void ts_lua_inject_log_object_write_api(lua_State *L); 31 | static void ts_lua_inject_log_object_destroy_api(lua_State *L); 32 | 33 | void 34 | ts_lua_inject_log_api(lua_State *L) 35 | { 36 | lua_newtable(L); 37 | 38 | ts_lua_inject_log_object_creat_api(L); 39 | ts_lua_inject_log_object_write_api(L); 40 | ts_lua_inject_log_object_destroy_api(L); 41 | 42 | lua_setfield(L, -2, "log"); 43 | } 44 | 45 | static void 46 | ts_lua_inject_log_object_creat_api(lua_State * L) 47 | { 48 | lua_pushcfunction(L, ts_lua_log_object_creat); 49 | lua_setfield(L, -2, "object_creat"); 50 | } 51 | 52 | static int 53 | ts_lua_log_object_creat(lua_State *L) 54 | { 55 | const char *log_name; 56 | size_t name_len; 57 | int log_mode; 58 | TSReturnCode error; 59 | 60 | log_name = luaL_checklstring(L, -2, &name_len); 61 | 62 | if (lua_isnil(L, 3)) { 63 | TSError("no log name!!"); 64 | return -1; 65 | 66 | } else { 67 | log_mode = luaL_checknumber(L, 3); 68 | } 69 | 70 | error = TSTextLogObjectCreate(log_name, log_mode, &log); 71 | 72 | if(!log || error == TS_ERROR) 73 | { 74 | TSError("creat log error <%s>",log_name); 75 | return -1; 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | static void 82 | ts_lua_inject_log_object_write_api(lua_State * L) 83 | { 84 | lua_pushcfunction(L, ts_lua_log_object_write); 85 | lua_setfield(L,-2,"object_write"); 86 | } 87 | 88 | static int 89 | ts_lua_log_object_write(lua_State *L) 90 | { 91 | const char *text; 92 | size_t text_len; 93 | 94 | text = luaL_checklstring(L, 1, &text_len); 95 | 96 | if(log) { 97 | TSTextLogObjectWrite(log, (char*)text, NULL); 98 | 99 | } else { 100 | TSError("[%s] log is not exsited!",__FUNCTION__); 101 | } 102 | 103 | return 0; 104 | } 105 | 106 | static void 107 | ts_lua_inject_log_object_destroy_api(lua_State * L) 108 | { 109 | lua_pushcfunction(L, ts_lua_log_object_destroy); 110 | lua_setfield(L,-2,"object_destroy"); 111 | } 112 | 113 | static int 114 | ts_lua_log_object_destroy(lua_State *L) 115 | { 116 | if(TSTextLogObjectDestroy(log) != TS_SUCCESS) 117 | TSError("[%s] TSTextLogObjectDestroy error!",__FUNCTION__); 118 | 119 | return 0; 120 | } 121 | 122 | -------------------------------------------------------------------------------- /src/ts_lua_log.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_LOG_H 21 | #define _TS_LUA_LOG_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_log_api(lua_State *L); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/ts_lua_mgmt.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | static int ts_lua_mgmt_get_int(lua_State *L); 23 | static int ts_lua_mgmt_get_counter(lua_State *L); 24 | static int ts_lua_mgmt_get_float(lua_State *L); 25 | static int ts_lua_mgmt_get_string(lua_State *L); 26 | 27 | 28 | void 29 | ts_lua_inject_mgmt_api(lua_State *L) 30 | { 31 | lua_newtable(L); 32 | 33 | lua_pushcfunction(L, ts_lua_mgmt_get_int); 34 | lua_setfield(L, -2, "get_int"); 35 | 36 | lua_pushcfunction(L, ts_lua_mgmt_get_counter); 37 | lua_setfield(L, -2, "get_counter"); 38 | 39 | lua_pushcfunction(L, ts_lua_mgmt_get_float); 40 | lua_setfield(L, -2, "get_float"); 41 | 42 | lua_pushcfunction(L, ts_lua_mgmt_get_string); 43 | lua_setfield(L, -2, "get_string"); 44 | 45 | lua_setfield(L, -2, "mgmt"); 46 | } 47 | 48 | static int 49 | ts_lua_mgmt_get_int(lua_State *L) 50 | { 51 | const char *name; 52 | size_t name_len; 53 | TSMgmtInt int_val; 54 | 55 | name = luaL_checklstring(L, 1, &name_len); 56 | 57 | if (TS_SUCCESS == TSMgmtIntGet(name, &int_val)) { 58 | lua_pushinteger(L, int_val); 59 | return 1; 60 | } 61 | 62 | return 0; 63 | } 64 | 65 | static int 66 | ts_lua_mgmt_get_counter(lua_State *L) 67 | { 68 | const char *name; 69 | size_t name_len; 70 | TSMgmtCounter counter_val; 71 | 72 | name = luaL_checklstring(L, 1, &name_len); 73 | 74 | if (TS_SUCCESS == TSMgmtCounterGet(name, &counter_val)) { 75 | lua_pushinteger(L, counter_val); 76 | return 1; 77 | } 78 | 79 | return 0; 80 | } 81 | 82 | static int 83 | ts_lua_mgmt_get_float(lua_State *L) 84 | { 85 | const char *name; 86 | size_t name_len; 87 | TSMgmtFloat float_val; 88 | 89 | name = luaL_checklstring(L, 1, &name_len); 90 | 91 | if (TS_SUCCESS == TSMgmtFloatGet(name, &float_val)) { 92 | lua_pushnumber(L, float_val); 93 | return 1; 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | static int 100 | ts_lua_mgmt_get_string(lua_State *L) 101 | { 102 | const char *name; 103 | size_t name_len; 104 | TSMgmtString str_val; 105 | 106 | name = luaL_checklstring(L, 1, &name_len); 107 | 108 | if (TS_SUCCESS == TSMgmtStringGet(name, &str_val)) { 109 | lua_pushstring(L, str_val); 110 | return 1; 111 | } 112 | 113 | return 0; 114 | } 115 | 116 | -------------------------------------------------------------------------------- /src/ts_lua_mgmt.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_MGMT_H 21 | #define _TS_LUA_MGMT_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_mgmt_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_misc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | 23 | static int ts_lua_get_now_time(lua_State *L); 24 | static int ts_lua_debug(lua_State *L); 25 | static int ts_lua_error(lua_State *L); 26 | static int ts_lua_sleep(lua_State *L); 27 | 28 | static int ts_lua_sleep_cleanup(ts_lua_async_item *ai); 29 | static int ts_lua_sleep_handler(TSCont contp, TSEvent event, void *edata); 30 | 31 | void 32 | ts_lua_inject_misc_api(lua_State *L) 33 | { 34 | /* ts.now() */ 35 | lua_pushcfunction(L, ts_lua_get_now_time); 36 | lua_setfield(L, -2, "now"); 37 | 38 | /* ts.debug(...) */ 39 | lua_pushcfunction(L, ts_lua_debug); 40 | lua_setfield(L, -2, "debug"); 41 | 42 | /* ts.error(...) */ 43 | lua_pushcfunction(L, ts_lua_error); 44 | lua_setfield(L, -2, "error"); 45 | 46 | /* ts.sleep(...) */ 47 | lua_pushcfunction(L, ts_lua_sleep); 48 | lua_setfield(L, -2, "sleep"); 49 | } 50 | 51 | static int 52 | ts_lua_get_now_time(lua_State *L) 53 | { 54 | time_t now; 55 | 56 | now = TShrtime() / 1000000000; 57 | lua_pushnumber(L, now); 58 | return 1; 59 | } 60 | 61 | static int 62 | ts_lua_debug(lua_State *L) 63 | { 64 | const char *msg; 65 | 66 | msg = luaL_checkstring(L, 1); 67 | TSDebug(TS_LUA_DEBUG_TAG, msg, NULL); 68 | return 0; 69 | } 70 | 71 | static int 72 | ts_lua_error(lua_State *L) 73 | { 74 | const char *msg; 75 | 76 | msg = luaL_checkstring(L, 1); 77 | TSError(msg, NULL); 78 | return 0; 79 | } 80 | 81 | 82 | static int 83 | ts_lua_sleep(lua_State *L) 84 | { 85 | int sec; 86 | TSAction action; 87 | TSCont contp; 88 | ts_lua_async_item *ai; 89 | ts_lua_cont_info *ci; 90 | 91 | ci = ts_lua_get_cont_info(L); 92 | if (ci == NULL) 93 | return 0; 94 | 95 | sec = luaL_checknumber(L, 1); 96 | if (sec < 1) { 97 | sec = 1; 98 | } 99 | 100 | contp = TSContCreate(ts_lua_sleep_handler, ci->mutex); 101 | action = TSContSchedule(contp, sec * 1000, TS_THREAD_POOL_DEFAULT); 102 | 103 | ai = ts_lua_async_create_item(contp, ts_lua_sleep_cleanup, (void*)action, ci); 104 | TSContDataSet(contp, ai); 105 | 106 | return lua_yield(L, 0); 107 | } 108 | 109 | static int 110 | ts_lua_sleep_handler(TSCont contp, TSEvent event, void *edata) 111 | { 112 | ts_lua_async_item *ai; 113 | ts_lua_cont_info *ci; 114 | 115 | ai = TSContDataGet(contp); 116 | ci = ai->cinfo; 117 | 118 | ai->data = NULL; 119 | ts_lua_sleep_cleanup(ai); 120 | 121 | TSContCall(ci->contp, TS_LUA_EVENT_COROUTINE_CONT, 0); 122 | 123 | return 0; 124 | } 125 | 126 | static int 127 | ts_lua_sleep_cleanup(ts_lua_async_item *ai) 128 | { 129 | if (ai->data) { 130 | TSActionCancel((TSAction)ai->data); 131 | ai->data = NULL; 132 | } 133 | 134 | TSContDestroy(ai->contp); 135 | ai->deleted = 1; 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /src/ts_lua_misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_MISC_H 21 | #define _TS_LUA_MISC_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_misc_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_package.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | #define TS_LUA_MAX_PACKAGE_PATH_LEN 256 23 | #define TS_LUA_MAX_PACKAGE_NUM 64 24 | 25 | 26 | typedef struct { 27 | size_t len; 28 | char *name; 29 | } ts_lua_package_path; 30 | 31 | 32 | static int g_path_cnt = 0; 33 | static ts_lua_package_path g_path[TS_LUA_MAX_PACKAGE_NUM]; 34 | 35 | static int g_cpath_cnt = 0; 36 | static ts_lua_package_path g_cpath[TS_LUA_MAX_PACKAGE_NUM]; 37 | 38 | 39 | static int ts_lua_add_package_path(lua_State *L); 40 | static int ts_lua_add_package_cpath(lua_State *L); 41 | static int ts_lua_add_package_path_items(lua_State *L, ts_lua_package_path *pp, int n); 42 | static int ts_lua_add_package_cpath_items(lua_State *L, ts_lua_package_path *pp, int n); 43 | 44 | 45 | void 46 | ts_lua_inject_package_api(lua_State *L) 47 | { 48 | /* ts.add_package_path() */ 49 | lua_pushcfunction(L, ts_lua_add_package_path); 50 | lua_setfield(L, -2, "add_package_path"); 51 | 52 | /* ts.add_package_cpath(...) */ 53 | lua_pushcfunction(L, ts_lua_add_package_cpath); 54 | lua_setfield(L, -2, "add_package_cpath"); 55 | } 56 | 57 | static int 58 | ts_lua_add_package_path(lua_State *L) 59 | { 60 | ts_lua_instance_conf *conf; 61 | const char *data; 62 | const char *ptr, *end, *hit; 63 | size_t dlen; 64 | size_t i, n, item_len; 65 | ts_lua_package_path pp[TS_LUA_MAX_PACKAGE_NUM]; 66 | ts_lua_package_path *elt; 67 | 68 | conf = ts_lua_get_instance_conf(L); 69 | if (conf == NULL) { 70 | return luaL_error(L, "cann't get the instance conf."); 71 | } 72 | 73 | data = luaL_checklstring(L, 1, &dlen); 74 | end = data + dlen; 75 | 76 | ptr = data; 77 | n = 0; 78 | 79 | while (ptr < end) { 80 | hit = memchr(ptr, ';', end - ptr); 81 | 82 | if (hit) { 83 | item_len = hit - ptr; 84 | 85 | } else { 86 | item_len = end - ptr; 87 | } 88 | 89 | if (item_len > 0) { 90 | 91 | for (i = 0; i < g_path_cnt; i++) { 92 | if (g_path[i].len == item_len && 93 | memcmp(g_path[i].name, ptr, item_len) == 0) // exist 94 | { 95 | break; 96 | } 97 | } 98 | 99 | if (i >= g_path_cnt) { 100 | 101 | if (n + i >= TS_LUA_MAX_PACKAGE_NUM) 102 | return luaL_error(L, "extended package path number exceeds %d.", TS_LUA_MAX_PACKAGE_NUM); 103 | 104 | pp[n].name = (char*)ptr; 105 | pp[n].len = item_len; 106 | n++; 107 | } 108 | } 109 | 110 | ptr += item_len + 1; // ?? 111 | } 112 | 113 | if (n > 0) { 114 | ts_lua_add_package_path_items(L, pp, n); 115 | 116 | if (conf->_last) { 117 | elt = &g_path[g_path_cnt]; 118 | 119 | for (i = 0; i < n; i++) { 120 | elt->len = pp[i].len; 121 | elt->name = (char*)TSmalloc(pp[i].len); 122 | memcpy(elt->name, pp[i].name, pp[i].len); 123 | elt++; 124 | } 125 | 126 | g_path_cnt += n; 127 | } 128 | } 129 | 130 | return 0; 131 | } 132 | 133 | static int 134 | ts_lua_add_package_path_items(lua_State *L, ts_lua_package_path *pp, int n) 135 | { 136 | int i, base; 137 | const char *old_path; 138 | char new_path[2048]; 139 | size_t old_path_len, new_path_len; 140 | 141 | base = lua_gettop(L); 142 | 143 | lua_getglobal(L, "package"); 144 | 145 | if (!lua_istable(L, -1)) { 146 | return luaL_error(L, "'package' table does not exist."); 147 | } 148 | 149 | lua_getfield(L, -1, "path"); /* get old package.path */ 150 | 151 | old_path = lua_tolstring(L, -1, &old_path_len); 152 | if (old_path[old_path_len - 1] == ';') 153 | old_path_len--; 154 | 155 | new_path_len = snprintf(new_path, sizeof(new_path) - 32, "%.*s", (int)old_path_len, old_path); 156 | 157 | for (i = 0; i < n; i++) { 158 | if (new_path_len + pp[i].len + 1 >= sizeof(new_path)) { 159 | fprintf(stderr, "extended package.path is too long.\n"); 160 | return -1; 161 | } 162 | 163 | new_path[new_path_len++] = ';'; 164 | memcpy(new_path + new_path_len, pp[i].name, pp[i].len); 165 | new_path_len += pp[i].len; 166 | } 167 | 168 | new_path[new_path_len] = 0; 169 | 170 | lua_pushlstring(L, new_path, new_path_len); 171 | lua_setfield(L, -3, "path"); 172 | 173 | lua_settop(L, base); 174 | 175 | return 0; 176 | } 177 | 178 | 179 | static int 180 | ts_lua_add_package_cpath(lua_State *L) 181 | { 182 | ts_lua_instance_conf *conf; 183 | const char *data; 184 | const char *ptr, *end, *hit; 185 | size_t dlen; 186 | size_t i, n, item_len; 187 | ts_lua_package_path pp[TS_LUA_MAX_PACKAGE_NUM]; 188 | ts_lua_package_path *elt; 189 | 190 | conf = ts_lua_get_instance_conf(L); 191 | if (conf == NULL) { 192 | return luaL_error(L, "cann't get the instance conf."); 193 | } 194 | 195 | data = luaL_checklstring(L, 1, &dlen); 196 | end = data + dlen; 197 | 198 | ptr = data; 199 | n = 0; 200 | 201 | while (ptr < end) { 202 | hit = memchr(ptr, ';', end - ptr); 203 | 204 | if (hit) { 205 | item_len = hit - ptr; 206 | 207 | } else { 208 | item_len = end - ptr; 209 | } 210 | 211 | if (item_len > 0) { 212 | 213 | for (i = 0; i < g_cpath_cnt; i++) { 214 | if (g_cpath[i].len == item_len && 215 | memcmp(g_cpath[i].name, ptr, item_len) == 0) // exist 216 | { 217 | break; 218 | } 219 | } 220 | 221 | if (i >= g_cpath_cnt) { 222 | 223 | if (n + i >= TS_LUA_MAX_PACKAGE_NUM) 224 | return luaL_error(L, "extended package cpath number exceeds %d.", TS_LUA_MAX_PACKAGE_NUM); 225 | 226 | pp[n].name = (char*)ptr; 227 | pp[n].len = item_len; 228 | n++; 229 | } 230 | } 231 | 232 | ptr += item_len + 1; // ?? 233 | } 234 | 235 | if (n > 0) { 236 | ts_lua_add_package_cpath_items(L, pp, n); 237 | 238 | if (conf->_last) { 239 | elt = &g_cpath[g_cpath_cnt]; 240 | 241 | for (i = 0; i < n; i++) { 242 | elt->len = pp[i].len; 243 | elt->name = (char*)TSmalloc(pp[i].len); 244 | memcpy(elt->name, pp[i].name, pp[i].len); 245 | elt++; 246 | } 247 | 248 | g_cpath_cnt += n; 249 | } 250 | } 251 | 252 | return 0; 253 | } 254 | 255 | static int 256 | ts_lua_add_package_cpath_items(lua_State *L, ts_lua_package_path *pp, int n) 257 | { 258 | int i, base; 259 | const char *old_path; 260 | char new_path[2048]; 261 | size_t old_path_len, new_path_len; 262 | 263 | base = lua_gettop(L); 264 | 265 | lua_getglobal(L, "package"); 266 | 267 | if (!lua_istable(L, -1)) { 268 | return luaL_error(L, "'package' table does not exist."); 269 | } 270 | 271 | lua_getfield(L, -1, "cpath"); /* get old package.cpath */ 272 | 273 | old_path = lua_tolstring(L, -1, &old_path_len); 274 | if (old_path[old_path_len - 1] == ';') 275 | old_path_len--; 276 | 277 | new_path_len = snprintf(new_path, sizeof(new_path) - 32, "%.*s", (int)old_path_len, old_path); 278 | 279 | for (i = 0; i < n; i++) { 280 | if (new_path_len + pp[i].len + 1 >= sizeof(new_path)) { 281 | fprintf(stderr, "extended package.cpath is too long.\n"); 282 | return -1; 283 | } 284 | 285 | new_path[new_path_len++] = ';'; 286 | memcpy(new_path + new_path_len, pp[i].name, pp[i].len); 287 | new_path_len += pp[i].len; 288 | } 289 | 290 | new_path[new_path_len] = 0; 291 | 292 | lua_pushlstring(L, new_path, new_path_len); 293 | lua_setfield(L, -3, "cpath"); 294 | 295 | lua_settop(L, base); 296 | 297 | return 0; 298 | } 299 | 300 | -------------------------------------------------------------------------------- /src/ts_lua_package.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_PACKAGE_H 21 | #define _TS_LUA_PACKAGE_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_package_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_regex.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include 21 | #include "ts_lua_util.h" 22 | #include "ts_lua_hash_table.h" 23 | 24 | static int ts_lua_regex_match(lua_State *L); 25 | 26 | static int free_pcre_value(Tcl_HashTable *t, Tcl_HashEntry *entry, void *data); 27 | 28 | void 29 | ts_lua_inject_regex_api(lua_State *L) 30 | { 31 | lua_newtable(L); 32 | 33 | lua_pushcfunction(L, ts_lua_regex_match); 34 | lua_setfield(L, -2, "match"); 35 | 36 | lua_setfield(L, -2, "re"); 37 | } 38 | 39 | 40 | static int 41 | ts_lua_regex_match(lua_State *L) 42 | { 43 | int rc, i, n, flags; 44 | const char *src; 45 | const char *sub; 46 | const char *pattern; 47 | const char *opt; 48 | const char *key; 49 | size_t src_len, sub_len, pattern_len, opt_len; 50 | pcre *re; 51 | int ovector[TS_LUA_MAX_OVEC_SIZE]; 52 | char tmp[1024]; 53 | void *pcre_lookup; 54 | char c; 55 | const char *err; 56 | int erroffset; 57 | int isNew, created; 58 | Tcl_HashEntry *hPtr; 59 | ts_lua_http_ctx *http_ctx; 60 | ts_lua_instance_conf *conf; 61 | 62 | http_ctx = ts_lua_get_http_ctx(L); 63 | conf = http_ctx->instance_conf; 64 | 65 | n = lua_gettop(L); 66 | src = luaL_checklstring(L, 1, &src_len); 67 | pattern = luaL_checklstring(L, 2, &pattern_len); 68 | 69 | if (n == 3) { 70 | opt = luaL_checklstring(L, 3, &opt_len); 71 | snprintf(tmp, sizeof(tmp)-8, "%s%s", pattern, opt); 72 | key = tmp; 73 | 74 | } else { 75 | opt = NULL; 76 | key = pattern; 77 | } 78 | 79 | isNew = 0; 80 | created = 0; 81 | 82 | if (ts_lua_hash_table_lookup(&conf->regex_map.t, key, &pcre_lookup)) { 83 | re = pcre_lookup; 84 | 85 | } else { 86 | 87 | i = flags = 0; 88 | 89 | if (opt && opt_len > 0) { 90 | 91 | while (i < opt_len) { 92 | c = *(opt + i); 93 | 94 | switch (c) { 95 | case 'i': 96 | flags |= PCRE_CASELESS; 97 | break; 98 | 99 | case 'a': 100 | flags |= PCRE_ANCHORED; 101 | break; 102 | 103 | case 'm': 104 | flags |= PCRE_MULTILINE; 105 | break; 106 | 107 | case 'u': 108 | flags |= PCRE_UNGREEDY; 109 | break; 110 | 111 | case 's': 112 | flags |= PCRE_DOTALL; 113 | break; 114 | 115 | case 'x': 116 | flags |= PCRE_EXTENDED; 117 | break; 118 | 119 | case 'd': 120 | flags |= PCRE_DOLLAR_ENDONLY; 121 | break; 122 | 123 | default: 124 | break; 125 | } 126 | 127 | i++; 128 | } 129 | } 130 | 131 | re = pcre_compile(pattern, flags, &err, &erroffset, NULL); 132 | created = 1; 133 | 134 | if (re == NULL) { 135 | return luaL_error(L, "PCRE compilation failed at offset %d: %s/n", erroffset, err); 136 | 137 | } else if (conf->regex_map.t.numEntries < TS_LUA_MAX_RESIDENT_PCRE) { 138 | 139 | TSMutexLock(conf->regex_map.mutexp); 140 | hPtr = Tcl_CreateHashEntry(&(conf->regex_map.t), key, &isNew); 141 | if (isNew) { 142 | Tcl_SetHashValue(hPtr, re); 143 | } 144 | 145 | TSMutexUnlock(conf->regex_map.mutexp); 146 | } 147 | } 148 | 149 | rc = pcre_exec(re, NULL, src, src_len, 0, 0, ovector, TS_LUA_MAX_OVEC_SIZE); 150 | 151 | if (rc < 0) { 152 | lua_pushnil(L); 153 | 154 | } else { 155 | lua_newtable(L); 156 | 157 | for (i = 1; i < rc; i++) { 158 | sub = src + ovector[2*i]; 159 | sub_len = ovector[2*i+1] - ovector[2*i]; 160 | lua_pushlstring(L, sub, sub_len); 161 | lua_rawseti(L, -2, i-1); 162 | } 163 | } 164 | 165 | if (created && !isNew) { 166 | pcre_free(re); 167 | } 168 | 169 | return 1; 170 | } 171 | 172 | int 173 | ts_lua_init_regex_map(ts_lua_hash_map *regex_map) 174 | { 175 | Tcl_InitHashTable(&(regex_map->t), TCL_STRING_KEYS); 176 | regex_map->mutexp = TSMutexCreate(); 177 | return 0; 178 | } 179 | 180 | int 181 | ts_lua_del_regex_map(ts_lua_hash_map *regex_map) 182 | { 183 | ts_lua_hash_table_iterate(&(regex_map->t), free_pcre_value, NULL); 184 | Tcl_DeleteHashTable(&(regex_map->t)); 185 | return 0; 186 | } 187 | 188 | static int 189 | free_pcre_value(Tcl_HashTable *t, Tcl_HashEntry *entry, void *data) 190 | { 191 | ClientData val; 192 | 193 | val = ts_lua_hash_table_entry_value(t, entry); 194 | 195 | if (val != NULL) { 196 | pcre_free((pcre*)val); 197 | } 198 | 199 | return 0; 200 | } 201 | 202 | -------------------------------------------------------------------------------- /src/ts_lua_regex.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_REGEX_H 21 | #define _TS_LUA_REGEX_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_regex_api(lua_State *L); 26 | 27 | int ts_lua_init_regex_map(ts_lua_hash_map *regex_map); 28 | int ts_lua_del_regex_map(ts_lua_hash_map *regex_map); 29 | 30 | #endif 31 | 32 | -------------------------------------------------------------------------------- /src/ts_lua_remap.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_remap.h" 21 | 22 | 23 | typedef enum { 24 | TS_LUA_REMAP_NO_REMAP = TSREMAP_NO_REMAP, 25 | TS_LUA_REMAP_DID_REMAP = TSREMAP_DID_REMAP, 26 | TS_LUA_REMAP_NO_REMAP_STOP = TSREMAP_NO_REMAP_STOP, 27 | TS_LUA_REMAP_DID_REMAP_STOP = TSREMAP_DID_REMAP_STOP, 28 | TS_LUA_REMAP_ERROR = TSREMAP_ERROR 29 | } TSLuaRemapStatus; 30 | 31 | 32 | ts_lua_var_item ts_lua_remap_status_vars[] = { 33 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_REMAP_NO_REMAP), 34 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_REMAP_DID_REMAP), 35 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_REMAP_NO_REMAP_STOP), 36 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_REMAP_DID_REMAP_STOP), 37 | TS_LUA_MAKE_VAR_ITEM(TS_LUA_REMAP_ERROR) 38 | }; 39 | 40 | 41 | static void ts_lua_inject_remap_variables(lua_State *L); 42 | 43 | 44 | void 45 | ts_lua_inject_remap_api(lua_State *L) 46 | { 47 | ts_lua_inject_remap_variables(L); 48 | } 49 | 50 | static void 51 | ts_lua_inject_remap_variables(lua_State *L) 52 | { 53 | int i; 54 | 55 | for (i = 0; i < sizeof(ts_lua_remap_status_vars) / sizeof(ts_lua_var_item); i++) { 56 | lua_pushinteger(L, ts_lua_remap_status_vars[i].nvar); 57 | lua_setglobal(L, ts_lua_remap_status_vars[i].svar); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/ts_lua_remap.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_REMAP_H 21 | #define _TS_LUA_REMAP_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_remap_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_server_request.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include 21 | #include "ts_lua_util.h" 22 | 23 | #define TS_LUA_CHECK_SERVER_REQUEST_HDR(http_ctx) \ 24 | do { \ 25 | if (!http_ctx->server_request_hdrp) { \ 26 | if (TSHttpTxnServerReqGet(http_ctx->txnp, \ 27 | &http_ctx->server_request_bufp, \ 28 | &http_ctx->server_request_hdrp) != TS_SUCCESS) { \ 29 | return 0; \ 30 | } \ 31 | } \ 32 | } while(0) 33 | 34 | 35 | #define TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx) \ 36 | do { \ 37 | if (!http_ctx->server_request_url) { \ 38 | TS_LUA_CHECK_SERVER_REQUEST_HDR(http_ctx); \ 39 | if (TSHttpHdrUrlGet(http_ctx->server_request_bufp, \ 40 | http_ctx->server_request_hdrp, \ 41 | &http_ctx->server_request_url) != TS_SUCCESS) { \ 42 | return 0; \ 43 | } \ 44 | } \ 45 | } while(0) 46 | 47 | 48 | 49 | static void ts_lua_inject_server_request_header_api(lua_State *L); 50 | static void ts_lua_inject_server_request_headers_api(lua_State *L); 51 | static void ts_lua_inject_server_request_get_header_size_api(lua_State *L); 52 | static void ts_lua_inject_server_request_get_body_size_api(lua_State *L); 53 | static void ts_lua_inject_server_request_uri_api(lua_State *L); 54 | static void ts_lua_inject_server_request_uri_args_api(lua_State *L); 55 | 56 | static int ts_lua_server_request_header_get(lua_State *L); 57 | static int ts_lua_server_request_header_set(lua_State *L); 58 | static int ts_lua_server_request_get_headers(lua_State *L); 59 | static int ts_lua_server_request_get_header_size(lua_State *L); 60 | static int ts_lua_server_request_get_body_size(lua_State *L); 61 | static int ts_lua_server_request_get_uri(lua_State *L); 62 | static int ts_lua_server_request_set_uri(lua_State *L); 63 | static int ts_lua_server_request_set_uri_args(lua_State *L); 64 | static int ts_lua_server_request_get_uri_args(lua_State *L); 65 | 66 | 67 | void 68 | ts_lua_inject_server_request_api(lua_State *L) 69 | { 70 | lua_newtable(L); 71 | 72 | ts_lua_inject_server_request_header_api(L); 73 | ts_lua_inject_server_request_headers_api(L); 74 | ts_lua_inject_server_request_get_header_size_api(L); 75 | ts_lua_inject_server_request_get_body_size_api(L); 76 | 77 | ts_lua_inject_server_request_uri_api(L); 78 | ts_lua_inject_server_request_uri_args_api(L); 79 | 80 | lua_setfield(L, -2, "server_request"); 81 | } 82 | 83 | 84 | static void 85 | ts_lua_inject_server_request_header_api(lua_State *L) 86 | { 87 | lua_newtable(L); /* .header */ 88 | 89 | lua_createtable(L, 0, 2); /* metatable for .header */ 90 | 91 | lua_pushcfunction(L, ts_lua_server_request_header_get); 92 | lua_setfield(L, -2, "__index"); 93 | lua_pushcfunction(L, ts_lua_server_request_header_set); 94 | lua_setfield(L, -2, "__newindex"); 95 | 96 | lua_setmetatable(L, -2); 97 | 98 | lua_setfield(L, -2, "header"); 99 | } 100 | 101 | static int 102 | ts_lua_server_request_header_get(lua_State *L) 103 | { 104 | const char *key; 105 | const char *val; 106 | int val_len; 107 | size_t key_len; 108 | 109 | TSMLoc field_loc; 110 | ts_lua_http_ctx *http_ctx; 111 | 112 | http_ctx = ts_lua_get_http_ctx(L); 113 | 114 | /* we skip the first argument that is the table */ 115 | key = luaL_checklstring(L, 2, &key_len); 116 | 117 | if (!http_ctx->server_request_hdrp) { 118 | if (TSHttpTxnServerReqGet(http_ctx->txnp, 119 | &http_ctx->server_request_bufp, &http_ctx->server_request_hdrp) != TS_SUCCESS) { 120 | 121 | lua_pushnil(L); 122 | return 1; 123 | } 124 | } 125 | 126 | if (key && key_len) { 127 | 128 | field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len); 129 | if (field_loc) { 130 | val = TSMimeHdrFieldValueStringGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, &val_len); 131 | lua_pushlstring(L, val, val_len); 132 | TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 133 | 134 | } else { 135 | lua_pushnil(L); 136 | } 137 | 138 | } else { 139 | lua_pushnil(L); 140 | } 141 | 142 | return 1; 143 | } 144 | 145 | static int 146 | ts_lua_server_request_header_set(lua_State *L) 147 | { 148 | const char *key; 149 | const char *val; 150 | size_t val_len; 151 | size_t key_len; 152 | int remove; 153 | 154 | TSMLoc field_loc; 155 | 156 | ts_lua_http_ctx *http_ctx; 157 | 158 | http_ctx = ts_lua_get_http_ctx(L); 159 | 160 | remove = 0; 161 | val = NULL; 162 | 163 | /* we skip the first argument that is the table */ 164 | key = luaL_checklstring(L, 2, &key_len); 165 | if (lua_isnil(L, 3)) { 166 | remove = 1; 167 | } else { 168 | val = luaL_checklstring(L, 3, &val_len); 169 | } 170 | 171 | if (!http_ctx->server_request_hdrp) { 172 | if (TSHttpTxnServerReqGet(http_ctx->txnp, 173 | &http_ctx->server_request_bufp, &http_ctx->server_request_hdrp) != TS_SUCCESS) { 174 | return 0; 175 | } 176 | } 177 | 178 | field_loc = TSMimeHdrFieldFind(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, key, key_len); 179 | 180 | if (remove) { 181 | if (field_loc) { 182 | TSMimeHdrFieldDestroy(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 183 | } 184 | 185 | } else if (field_loc) { 186 | TSMimeHdrFieldValueStringSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, val, val_len); 187 | 188 | } else if (TSMimeHdrFieldCreateNamed(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, 189 | key, key_len, &field_loc) != TS_SUCCESS) { 190 | TSError("[%s] TSMimeHdrFieldCreateNamed error", __FUNCTION__); 191 | return 0; 192 | 193 | } else { 194 | TSMimeHdrFieldValueStringSet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, val, val_len); 195 | TSMimeHdrFieldAppend(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 196 | } 197 | 198 | if (field_loc) 199 | TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 200 | 201 | return 0; 202 | } 203 | 204 | static void 205 | ts_lua_inject_server_request_headers_api(lua_State *L) 206 | { 207 | lua_pushcfunction(L, ts_lua_server_request_get_headers); 208 | lua_setfield(L, -2, "get_headers"); 209 | } 210 | 211 | static int 212 | ts_lua_server_request_get_headers(lua_State *L) 213 | { 214 | const char *name; 215 | const char *value; 216 | int name_len; 217 | int value_len; 218 | TSMLoc field_loc; 219 | TSMLoc next_field_loc; 220 | 221 | ts_lua_http_ctx *http_ctx; 222 | 223 | http_ctx = ts_lua_get_http_ctx(L); 224 | 225 | TS_LUA_CHECK_SERVER_REQUEST_HDR(http_ctx); 226 | 227 | lua_newtable(L); 228 | 229 | field_loc = TSMimeHdrFieldGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, 0); 230 | 231 | while (field_loc) { 232 | 233 | name = TSMimeHdrFieldNameGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, &name_len); 234 | if (name && name_len) { 235 | 236 | value = TSMimeHdrFieldValueStringGet(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc, -1, &value_len); 237 | lua_pushlstring(L, name, name_len); 238 | lua_pushlstring(L, value, value_len); 239 | lua_rawset(L, -3); 240 | } 241 | 242 | next_field_loc = TSMimeHdrFieldNext(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 243 | TSHandleMLocRelease(http_ctx->server_request_bufp, http_ctx->server_request_hdrp, field_loc); 244 | field_loc = next_field_loc; 245 | } 246 | 247 | return 1; 248 | } 249 | 250 | static void 251 | ts_lua_inject_server_request_get_header_size_api(lua_State *L) 252 | { 253 | lua_pushcfunction(L, ts_lua_server_request_get_header_size); 254 | lua_setfield(L, -2, "get_header_size"); 255 | } 256 | 257 | static int 258 | ts_lua_server_request_get_header_size(lua_State *L) 259 | { 260 | int header_size; 261 | ts_lua_http_ctx *http_ctx; 262 | 263 | http_ctx = ts_lua_get_http_ctx(L); 264 | 265 | header_size = TSHttpTxnServerReqHdrBytesGet(http_ctx->txnp); 266 | lua_pushnumber(L,header_size); 267 | 268 | return 1; 269 | } 270 | 271 | static void 272 | ts_lua_inject_server_request_get_body_size_api(lua_State *L) 273 | { 274 | lua_pushcfunction(L, ts_lua_server_request_get_body_size); 275 | lua_setfield(L, -2, "get_body_size"); 276 | } 277 | 278 | static int 279 | ts_lua_server_request_get_body_size(lua_State *L) 280 | { 281 | int64_t body_size; 282 | ts_lua_http_ctx *http_ctx; 283 | 284 | http_ctx = ts_lua_get_http_ctx(L); 285 | 286 | body_size = TSHttpTxnServerReqBodyBytesGet(http_ctx->txnp); 287 | lua_pushnumber(L,body_size); 288 | 289 | return 1; 290 | } 291 | 292 | static void 293 | ts_lua_inject_server_request_uri_api(lua_State *L) 294 | { 295 | lua_pushcfunction(L, ts_lua_server_request_set_uri); 296 | lua_setfield(L, -2, "set_uri"); 297 | 298 | lua_pushcfunction(L, ts_lua_server_request_get_uri); 299 | lua_setfield(L, -2, "get_uri"); 300 | } 301 | 302 | static int 303 | ts_lua_server_request_get_uri(lua_State *L) 304 | { 305 | char uri[TS_LUA_MAX_URL_LENGTH]; 306 | const char *path; 307 | int path_len; 308 | int uri_len; 309 | 310 | ts_lua_http_ctx *http_ctx; 311 | 312 | http_ctx = ts_lua_get_http_ctx(L); 313 | 314 | TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); 315 | 316 | path = TSUrlPathGet(http_ctx->server_request_bufp, http_ctx->server_request_url, &path_len); 317 | 318 | uri_len = snprintf(uri, TS_LUA_MAX_URL_LENGTH, "/%.*s", path_len, path); 319 | 320 | lua_pushlstring(L, uri, uri_len); 321 | 322 | return 1; 323 | } 324 | 325 | static int 326 | ts_lua_server_request_set_uri(lua_State *L) 327 | { 328 | const char *path; 329 | size_t path_len; 330 | 331 | ts_lua_http_ctx *http_ctx; 332 | 333 | http_ctx = ts_lua_get_http_ctx(L); 334 | 335 | TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); 336 | 337 | path = luaL_checklstring(L, 1, &path_len); 338 | 339 | if (*path == '/') { 340 | path++; 341 | path_len--; 342 | } 343 | 344 | TSUrlPathSet(http_ctx->server_request_bufp, http_ctx->server_request_url, path, path_len); 345 | 346 | return 0; 347 | } 348 | 349 | static void 350 | ts_lua_inject_server_request_uri_args_api(lua_State *L) 351 | { 352 | lua_pushcfunction(L, ts_lua_server_request_set_uri_args); 353 | lua_setfield(L, -2, "set_uri_args"); 354 | 355 | lua_pushcfunction(L, ts_lua_server_request_get_uri_args); 356 | lua_setfield(L, -2, "get_uri_args"); 357 | } 358 | 359 | static int 360 | ts_lua_server_request_set_uri_args(lua_State *L) 361 | { 362 | const char *param; 363 | size_t param_len; 364 | 365 | ts_lua_http_ctx *http_ctx; 366 | 367 | http_ctx = ts_lua_get_http_ctx(L); 368 | 369 | TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); 370 | 371 | param = luaL_checklstring(L, 1, ¶m_len); 372 | TSUrlHttpQuerySet(http_ctx->server_request_bufp, http_ctx->server_request_url, param, param_len); 373 | 374 | return 0; 375 | } 376 | 377 | static int 378 | ts_lua_server_request_get_uri_args(lua_State *L) 379 | { 380 | const char *param; 381 | int param_len; 382 | 383 | ts_lua_http_ctx *http_ctx; 384 | 385 | http_ctx = ts_lua_get_http_ctx(L); 386 | 387 | TS_LUA_CHECK_SERVER_REQUEST_URL(http_ctx); 388 | 389 | param = TSUrlHttpQueryGet(http_ctx->server_request_bufp, http_ctx->server_request_url, ¶m_len); 390 | 391 | if (param && param_len > 0) { 392 | lua_pushlstring(L, param, param_len); 393 | 394 | } else { 395 | lua_pushnil(L); 396 | } 397 | 398 | return 1; 399 | } 400 | 401 | -------------------------------------------------------------------------------- /src/ts_lua_server_request.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_SERVER_REQUEST_H 21 | #define _TS_LUA_SERVER_REQUEST_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_server_request_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_server_response.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | #define TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx) \ 23 | do { \ 24 | if (!http_ctx->server_response_hdrp) { \ 25 | if (TSHttpTxnServerRespGet(http_ctx->txnp, \ 26 | &http_ctx->server_response_bufp, \ 27 | &http_ctx->server_response_hdrp) != TS_SUCCESS) { \ 28 | return 0; \ 29 | } \ 30 | } \ 31 | } while(0) 32 | 33 | 34 | static void ts_lua_inject_server_response_header_api(lua_State *L); 35 | static void ts_lua_inject_server_response_headers_api(lua_State *L); 36 | static void ts_lua_inject_server_response_misc_api(lua_State *L); 37 | 38 | static int ts_lua_server_response_header_get(lua_State *L); 39 | static int ts_lua_server_response_header_set(lua_State *L); 40 | 41 | static int ts_lua_server_response_get_headers(lua_State *L); 42 | 43 | static int ts_lua_server_response_get_status(lua_State *L); 44 | static int ts_lua_server_response_set_status(lua_State *L); 45 | 46 | static int ts_lua_server_response_get_version(lua_State *L); 47 | static int ts_lua_server_response_set_version(lua_State *L); 48 | 49 | 50 | void 51 | ts_lua_inject_server_response_api(lua_State *L) 52 | { 53 | lua_newtable(L); 54 | 55 | ts_lua_inject_server_response_header_api(L); 56 | ts_lua_inject_server_response_headers_api(L); 57 | ts_lua_inject_server_response_misc_api(L); 58 | 59 | lua_setfield(L, -2, "server_response"); 60 | } 61 | 62 | 63 | static void 64 | ts_lua_inject_server_response_header_api(lua_State *L) 65 | { 66 | lua_newtable(L); /* .header */ 67 | 68 | lua_createtable(L, 0, 2); /* metatable for .header */ 69 | 70 | lua_pushcfunction(L, ts_lua_server_response_header_get); 71 | lua_setfield(L, -2, "__index"); 72 | lua_pushcfunction(L, ts_lua_server_response_header_set); 73 | lua_setfield(L, -2, "__newindex"); 74 | 75 | lua_setmetatable(L, -2); 76 | 77 | lua_setfield(L, -2, "header"); 78 | } 79 | 80 | static void 81 | ts_lua_inject_server_response_headers_api(lua_State *L) 82 | { 83 | lua_pushcfunction(L, ts_lua_server_response_get_headers); 84 | lua_setfield(L, -2, "get_headers"); 85 | } 86 | 87 | static int 88 | ts_lua_server_response_get_headers(lua_State *L) 89 | { 90 | const char *name; 91 | const char *value; 92 | int name_len; 93 | int value_len; 94 | TSMLoc field_loc; 95 | TSMLoc next_field_loc; 96 | 97 | ts_lua_http_ctx *http_ctx; 98 | 99 | http_ctx = ts_lua_get_http_ctx(L); 100 | 101 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 102 | 103 | lua_newtable(L); 104 | 105 | field_loc = TSMimeHdrFieldGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, 0); 106 | 107 | while (field_loc) { 108 | 109 | name = TSMimeHdrFieldNameGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc, &name_len); 110 | if (name && name_len) { 111 | 112 | value = TSMimeHdrFieldValueStringGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc, -1, &value_len); 113 | lua_pushlstring(L, name, name_len); 114 | lua_pushlstring(L, value, value_len); 115 | lua_rawset(L, -3); 116 | } 117 | 118 | next_field_loc = TSMimeHdrFieldNext(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 119 | TSHandleMLocRelease(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 120 | field_loc = next_field_loc; 121 | } 122 | 123 | return 1; 124 | } 125 | 126 | static void 127 | ts_lua_inject_server_response_misc_api(lua_State *L) 128 | { 129 | lua_pushcfunction(L, ts_lua_server_response_get_status); 130 | lua_setfield(L, -2, "get_status"); 131 | lua_pushcfunction(L, ts_lua_server_response_set_status); 132 | lua_setfield(L, -2, "set_status"); 133 | 134 | lua_pushcfunction(L, ts_lua_server_response_get_version); 135 | lua_setfield(L, -2, "get_version"); 136 | lua_pushcfunction(L, ts_lua_server_response_set_version); 137 | lua_setfield(L, -2, "set_version"); 138 | } 139 | 140 | static int 141 | ts_lua_server_response_header_get(lua_State *L) 142 | { 143 | const char *key; 144 | const char *val; 145 | int val_len; 146 | size_t key_len; 147 | 148 | TSMLoc field_loc; 149 | ts_lua_http_ctx *http_ctx; 150 | 151 | http_ctx = ts_lua_get_http_ctx(L); 152 | 153 | /* we skip the first argument that is the table */ 154 | key = luaL_checklstring(L, 2, &key_len); 155 | 156 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 157 | 158 | if (key && key_len) { 159 | 160 | field_loc = TSMimeHdrFieldFind(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, key, key_len); 161 | if (field_loc) { 162 | val = TSMimeHdrFieldValueStringGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc, -1, &val_len); 163 | lua_pushlstring(L, val, val_len); 164 | TSHandleMLocRelease(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 165 | 166 | } else { 167 | lua_pushnil(L); 168 | } 169 | 170 | } else { 171 | lua_pushnil(L); 172 | } 173 | 174 | return 1; 175 | } 176 | 177 | static int 178 | ts_lua_server_response_header_set(lua_State *L) 179 | { 180 | const char *key; 181 | const char *val; 182 | size_t val_len; 183 | size_t key_len; 184 | int remove; 185 | 186 | TSMLoc field_loc; 187 | 188 | ts_lua_http_ctx *http_ctx; 189 | 190 | http_ctx = ts_lua_get_http_ctx(L); 191 | 192 | remove = 0; 193 | val = NULL; 194 | 195 | /* we skip the first argument that is the table */ 196 | key = luaL_checklstring(L, 2, &key_len); 197 | if (lua_isnil(L, 3)) { 198 | remove = 1; 199 | } else { 200 | val = luaL_checklstring(L, 3, &val_len); 201 | } 202 | 203 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 204 | 205 | field_loc = TSMimeHdrFieldFind(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, key, key_len); 206 | 207 | if (remove) { 208 | if (field_loc) { 209 | TSMimeHdrFieldDestroy(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 210 | } 211 | 212 | } else if (field_loc) { 213 | TSMimeHdrFieldValueStringSet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc, -1, val, val_len); 214 | 215 | } else if (TSMimeHdrFieldCreateNamed(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, 216 | key, key_len, &field_loc) != TS_SUCCESS) { 217 | TSError("[%s] TSMimeHdrFieldCreateNamed error", __FUNCTION__); 218 | return 0; 219 | 220 | } else { 221 | TSMimeHdrFieldValueStringSet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc, -1, val, val_len); 222 | TSMimeHdrFieldAppend(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 223 | } 224 | 225 | if (field_loc) 226 | TSHandleMLocRelease(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, field_loc); 227 | 228 | return 0; 229 | } 230 | 231 | static int 232 | ts_lua_server_response_get_status(lua_State *L) 233 | { 234 | int status; 235 | ts_lua_http_ctx *http_ctx; 236 | 237 | http_ctx = ts_lua_get_http_ctx(L); 238 | 239 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 240 | 241 | status = TSHttpHdrStatusGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp); 242 | 243 | lua_pushinteger(L, status); 244 | 245 | return 1; 246 | } 247 | 248 | static int 249 | ts_lua_server_response_set_status(lua_State *L) 250 | { 251 | int status; 252 | const char *reason; 253 | int reason_len; 254 | 255 | ts_lua_http_ctx *http_ctx; 256 | 257 | http_ctx = ts_lua_get_http_ctx(L); 258 | 259 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 260 | 261 | status = luaL_checkint(L, 1); 262 | 263 | reason = TSHttpHdrReasonLookup(status); 264 | reason_len = strlen(reason); 265 | 266 | TSHttpHdrStatusSet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, status); 267 | TSHttpHdrReasonSet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, reason, reason_len); 268 | 269 | return 0; 270 | } 271 | 272 | static int 273 | ts_lua_server_response_get_version(lua_State *L) 274 | { 275 | int version; 276 | char buf[32]; 277 | int n; 278 | 279 | ts_lua_http_ctx *http_ctx; 280 | 281 | http_ctx = ts_lua_get_http_ctx(L); 282 | 283 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 284 | 285 | version = TSHttpHdrVersionGet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp); 286 | 287 | n = snprintf(buf, sizeof(buf)-1, "%d.%d", TS_HTTP_MAJOR(version), TS_HTTP_MINOR(version)); 288 | lua_pushlstring(L, buf, n); 289 | 290 | return 1; 291 | } 292 | 293 | static int 294 | ts_lua_server_response_set_version(lua_State *L) 295 | { 296 | const char *version; 297 | size_t len; 298 | int major, minor; 299 | 300 | ts_lua_http_ctx *http_ctx; 301 | 302 | http_ctx = ts_lua_get_http_ctx(L); 303 | 304 | TS_LUA_CHECK_SERVER_RESPONSE_HDR(http_ctx); 305 | 306 | version = luaL_checklstring(L, 1, &len); 307 | 308 | sscanf(version, "%2u.%2u", &major, &minor); 309 | 310 | TSHttpHdrVersionSet(http_ctx->server_response_bufp, http_ctx->server_response_hdrp, TS_HTTP_VERSION(major, minor)); 311 | 312 | return 0; 313 | } 314 | 315 | -------------------------------------------------------------------------------- /src/ts_lua_server_response.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_SERVER_RESPONSE_H 21 | #define _TS_LUA_SERVER_RESPONSE_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_server_response_api(lua_State *L); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_shared_dict.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_SHARED_DICT_H 21 | #define _TS_LUA_SHARED_DICT_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | void ts_lua_inject_shared_dict_api(lua_State *L); 26 | 27 | int ts_lua_del_shared_dict(ts_lua_shared_dict *shdict); 28 | 29 | #endif 30 | 31 | -------------------------------------------------------------------------------- /src/ts_lua_string.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_STRING_H 21 | #define _TS_LUA_STRING_H 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define TS_ESCAPE_URI 0 29 | #define TS_ESCAPE_ARGS 1 30 | #define TS_ESCAPE_URI_COMPONENT 2 31 | #define TS_ESCAPE_HTML 3 32 | #define TS_ESCAPE_REFRESH 4 33 | #define TS_ESCAPE_MEMCACHED 5 34 | #define TS_ESCAPE_MAIL_AUTH 6 35 | 36 | #define TS_UNESCAPE_URI_COMPONENT 0 37 | #define TS_UNESCAPE_URI 1 38 | #define TS_UNESCAPE_REDIRECT 2 39 | 40 | #define ts_lua_base64_encoded_length(len) (((len + 2) / 3) * 4) 41 | #define ts_lua_base64_decoded_length(len) (((len + 3) / 4) * 3) 42 | 43 | u_char * ts_lua_hex_dump(u_char *dst, u_char *src, size_t len); 44 | 45 | void ts_lua_encode_base64(u_char *dst, size_t *dst_len, u_char *src, size_t src_len); 46 | int ts_lua_decode_base64(u_char *dst, size_t *dst_len, u_char *src, size_t src_len); 47 | 48 | uintptr_t ts_lua_escape_internal(u_char *dst, u_char *src, size_t size, int type); 49 | void ts_lua_unescape_internal(u_char **dst, u_char **src, size_t size, int type); 50 | #endif 51 | 52 | -------------------------------------------------------------------------------- /src/ts_lua_transform.c: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #include "ts_lua_util.h" 21 | 22 | 23 | static int ts_lua_transform_handler(TSCont contp, ts_lua_http_transform_ctx *transform_ctx, TSEvent event, int n); 24 | 25 | 26 | int 27 | ts_lua_transform_entry(TSCont contp, TSEvent ev, void *edata) 28 | { 29 | int n, event; 30 | TSVIO input_vio; 31 | ts_lua_http_transform_ctx *transform_ctx; 32 | 33 | event = (int)ev; 34 | transform_ctx = (ts_lua_http_transform_ctx*)TSContDataGet(contp); 35 | 36 | if (TSVConnClosedGet(contp)) { 37 | ts_lua_destroy_http_transform_ctx(transform_ctx); 38 | return 0; 39 | } 40 | 41 | n = 0; 42 | 43 | switch (event) { 44 | 45 | case TS_EVENT_ERROR: 46 | input_vio = TSVConnWriteVIOGet(contp); 47 | TSContCall(TSVIOContGet(input_vio), TS_EVENT_ERROR, input_vio); 48 | break; 49 | 50 | case TS_EVENT_VCONN_WRITE_COMPLETE: 51 | TSVConnShutdown(TSTransformOutputVConnGet(contp), 0, 1); 52 | break; 53 | 54 | case TS_LUA_EVENT_COROUTINE_CONT: 55 | n = (intptr_t)edata; 56 | 57 | case TS_EVENT_VCONN_WRITE_READY: 58 | default: 59 | ts_lua_transform_handler(contp, transform_ctx, event, n); 60 | break; 61 | } 62 | 63 | return 0; 64 | } 65 | 66 | static int 67 | ts_lua_transform_handler(TSCont contp, ts_lua_http_transform_ctx *transform_ctx, TSEvent event, int n) 68 | { 69 | TSVConn output_conn; 70 | TSVIO input_vio; 71 | TSIOBufferReader input_reader; 72 | TSIOBufferBlock blk; 73 | int64_t toread, towrite, blk_len, upstream_done, input_avail, l; 74 | const char *start; 75 | const char *res; 76 | size_t res_len; 77 | int ret, eos, write_down, rc, top; 78 | ts_lua_coroutine *crt; 79 | ts_lua_cont_info *ci; 80 | 81 | lua_State *L; 82 | TSMutex mtxp; 83 | 84 | ci = &transform_ctx->cinfo; 85 | crt = &ci->routine; 86 | 87 | mtxp = crt->mctx->mutexp; 88 | L = crt->lua; 89 | 90 | output_conn = TSTransformOutputVConnGet(contp); 91 | input_vio = TSVConnWriteVIOGet(contp); 92 | 93 | if (!TSVIOBufferGet(input_vio)) { 94 | if (transform_ctx->output.vio) { 95 | TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total); 96 | TSVIOReenable(transform_ctx->output.vio); 97 | } 98 | 99 | return 0; 100 | } 101 | 102 | input_reader = TSVIOReaderGet(input_vio); 103 | 104 | if (!transform_ctx->output.buffer) { 105 | transform_ctx->output.buffer = TSIOBufferCreate(); 106 | transform_ctx->output.reader = TSIOBufferReaderAlloc(transform_ctx->output.buffer); 107 | 108 | transform_ctx->reserved.buffer = TSIOBufferCreate(); 109 | transform_ctx->reserved.reader = TSIOBufferReaderAlloc(transform_ctx->reserved.buffer); 110 | 111 | transform_ctx->upstream_bytes = TSVIONBytesGet(input_vio); 112 | transform_ctx->downstream_bytes = INT64_MAX; 113 | } 114 | 115 | input_avail = TSIOBufferReaderAvail(input_reader); 116 | upstream_done = TSVIONDoneGet(input_vio); 117 | toread = TSVIONTodoGet(input_vio); 118 | 119 | if (toread <= input_avail) { // upstream finished 120 | eos = 1; 121 | 122 | } else { 123 | eos = 0; 124 | } 125 | 126 | if (input_avail > 0) { 127 | // move to the reserved.buffer 128 | TSIOBufferCopy(transform_ctx->reserved.buffer, input_reader, input_avail, 0); 129 | 130 | // reset input 131 | TSIOBufferReaderConsume(input_reader, input_avail); 132 | TSVIONDoneSet(input_vio, upstream_done + input_avail); 133 | } 134 | 135 | write_down = 0; 136 | towrite = TSIOBufferReaderAvail(transform_ctx->reserved.reader); 137 | 138 | TSMutexLock(mtxp); 139 | ts_lua_set_cont_info(L, ci); 140 | 141 | do { 142 | if (event == TS_LUA_EVENT_COROUTINE_CONT) { 143 | event = 0; 144 | goto launch; 145 | 146 | } else { 147 | n = 2; 148 | } 149 | 150 | if (towrite == 0) 151 | break; 152 | 153 | blk = TSIOBufferReaderStart(transform_ctx->reserved.reader); 154 | start = TSIOBufferBlockReadStart(blk, transform_ctx->reserved.reader, &blk_len); 155 | 156 | lua_pushlightuserdata(L, transform_ctx); 157 | lua_rawget(L, LUA_GLOBALSINDEX); /* push function */ 158 | 159 | if (towrite > blk_len) { 160 | lua_pushlstring(L, start, (size_t)blk_len); 161 | towrite -= blk_len; 162 | TSIOBufferReaderConsume(transform_ctx->reserved.reader, blk_len); 163 | 164 | } else { 165 | lua_pushlstring(L, start, (size_t)towrite); 166 | TSIOBufferReaderConsume(transform_ctx->reserved.reader, towrite); 167 | towrite = 0; 168 | } 169 | 170 | if (!towrite && eos) { 171 | lua_pushinteger(L, 1); /* second param, data finished */ 172 | 173 | } else { 174 | lua_pushinteger(L, 0); /* second param, data not finish */ 175 | } 176 | 177 | launch: 178 | rc = lua_resume(L, n); 179 | top = lua_gettop(L); 180 | 181 | switch (rc) { 182 | case LUA_YIELD: // coroutine yield 183 | TSMutexUnlock(mtxp); 184 | return 0; 185 | 186 | case 0: // coroutine success 187 | if (top == 2) { 188 | ret = lua_tointeger(L, -1); /* 0 is not finished, 1 is finished */ 189 | res = lua_tolstring(L, -2, &res_len); 190 | 191 | } else { // what hells code are you writing ? 192 | ret = 0; 193 | res = NULL; 194 | res_len = 0; 195 | } 196 | 197 | break; 198 | 199 | default: // coroutine failed 200 | ee("lua_resume failed: %s", lua_tostring(L, -1)); 201 | ret = 1; 202 | res = NULL; 203 | res_len = 0; 204 | break; 205 | } 206 | 207 | if (res && res_len > 0) { 208 | if (!transform_ctx->output.vio) { 209 | l = transform_ctx->downstream_bytes; 210 | if (ret) 211 | l = res_len; 212 | 213 | transform_ctx->output.vio = TSVConnWrite(output_conn, contp, transform_ctx->output.reader, l); // HttpSM go on 214 | } 215 | 216 | TSIOBufferWrite(transform_ctx->output.buffer, res, res_len); 217 | transform_ctx->total += res_len; 218 | write_down = 1; 219 | } 220 | 221 | lua_pop(L, top); 222 | 223 | if (ret || (eos && !towrite)) { // EOS 224 | eos = 1; 225 | break; 226 | } 227 | 228 | } while (towrite > 0); 229 | 230 | TSMutexUnlock(mtxp); 231 | 232 | if (eos && !transform_ctx->output.vio) 233 | transform_ctx->output.vio = TSVConnWrite(output_conn, contp, transform_ctx->output.reader, 0); 234 | 235 | if (write_down || eos) 236 | TSVIOReenable(transform_ctx->output.vio); 237 | 238 | if (toread > input_avail) { // upstream not finished. 239 | if (eos) { 240 | TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total); 241 | TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_EOS, input_vio); 242 | 243 | } else { 244 | TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_READY, input_vio); 245 | } 246 | 247 | } else { // upstream is finished. 248 | TSVIONBytesSet(transform_ctx->output.vio, transform_ctx->total); 249 | TSContCall(TSVIOContGet(input_vio), TS_EVENT_VCONN_WRITE_COMPLETE, input_vio); 250 | } 251 | 252 | return 0; 253 | } 254 | -------------------------------------------------------------------------------- /src/ts_lua_transform.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_TRANSFORM_H 21 | #define _TS_LUA_TRANSFORM_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | int ts_lua_transform_entry(TSCont contp, TSEvent event, void *edata); 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /src/ts_lua_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef _TS_LUA_UTIL_H 21 | #define _TS_LUA_UTIL_H 22 | 23 | #include "ts_lua_common.h" 24 | 25 | int ts_lua_create_vm(ts_lua_main_ctx *arr, int n); 26 | void ts_lua_destroy_vm(ts_lua_main_ctx *arr, int n); 27 | 28 | int ts_lua_add_module(ts_lua_instance_conf *conf, ts_lua_main_ctx *arr, int n, int argc, char *argv[]); 29 | int ts_lua_del_module(ts_lua_instance_conf *conf, ts_lua_main_ctx *arr, int n); 30 | 31 | int ts_lua_init_instance(ts_lua_instance_conf *conf); 32 | int ts_lua_del_instance(ts_lua_instance_conf *conf); 33 | 34 | void ts_lua_set_instance_conf(lua_State *L, ts_lua_instance_conf *conf); 35 | ts_lua_instance_conf * ts_lua_get_instance_conf(lua_State *L); 36 | 37 | void ts_lua_set_cont_info(lua_State *L, ts_lua_cont_info *ci); 38 | ts_lua_cont_info * ts_lua_get_cont_info(lua_State *L); 39 | 40 | void ts_lua_set_http_ctx(lua_State *L, ts_lua_http_ctx *ctx); 41 | ts_lua_http_ctx * ts_lua_get_http_ctx(lua_State *L); 42 | 43 | ts_lua_http_ctx * ts_lua_create_http_ctx(ts_lua_main_ctx *mctx, ts_lua_instance_conf *conf); 44 | void ts_lua_destroy_http_ctx(ts_lua_http_ctx* http_ctx); 45 | 46 | ts_lua_http_transform_ctx * ts_lua_create_http_transform_ctx(ts_lua_http_ctx *http_ctx, TSVConn connp); 47 | void ts_lua_destroy_http_transform_ctx(ts_lua_http_transform_ctx *transform_ctx); 48 | void ts_lua_set_http_transform_ctx(lua_State *L, ts_lua_http_transform_ctx *tctx); 49 | ts_lua_http_transform_ctx * ts_lua_get_http_transform_ctx(lua_State *L); 50 | 51 | ts_lua_http_intercept_ctx * ts_lua_create_http_intercept_ctx(lua_State *L, ts_lua_http_ctx *http_ctx, int n); 52 | ts_lua_http_intercept_ctx * ts_lua_get_http_intercept_ctx(lua_State *L); 53 | void ts_lua_destroy_http_intercept_ctx(ts_lua_http_intercept_ctx *ictx); 54 | 55 | int ts_lua_http_cont_handler(TSCont contp, TSEvent event, void *edata); 56 | 57 | #endif 58 | 59 | --------------------------------------------------------------------------------