/nginx_lua_docker_image_files/ngx_openresty-1.7.7.2/bundle/lua-resty-core-0.1.0/lib/resty/core/request.lua

https://github.com/zq2599/blog_demos · Lua · 351 lines · 334 code · 16 blank · 1 comment · 0 complexity · d42c170caeae76365db2753cf4923831 MD5 · raw file

  1. -- Copyright (C) Yichun Zhang (agentzh)
  2. local ffi = require 'ffi'
  3. local base = require "resty.core.base"
  4. local FFI_BAD_CONTEXT = base.FFI_BAD_CONTEXT
  5. local FFI_DECLINED = base.FFI_DECLINED
  6. local FFI_OK = base.FFI_OK
  7. local new_tab = base.new_tab
  8. local C = ffi.C
  9. local ffi_cast = ffi.cast
  10. local ffi_str = ffi.string
  11. local get_string_buf = base.get_string_buf
  12. local get_size_ptr = base.get_size_ptr
  13. local setmetatable = setmetatable
  14. local gsub = ngx.re.gsub
  15. local lower = string.lower
  16. local rawget = rawget
  17. local ngx = ngx
  18. local getfenv = getfenv
  19. local type = type
  20. local error = error
  21. local tostring = tostring
  22. local tonumber = tonumber
  23. ffi.cdef[[
  24. typedef struct {
  25. ngx_http_lua_ffi_str_t key;
  26. ngx_http_lua_ffi_str_t value;
  27. } ngx_http_lua_ffi_table_elt_t;
  28. int ngx_http_lua_ffi_req_get_headers_count(ngx_http_request_t *r,
  29. int max);
  30. int ngx_http_lua_ffi_req_get_headers(ngx_http_request_t *r,
  31. ngx_http_lua_ffi_table_elt_t *out, int count, int raw);
  32. int ngx_http_lua_ffi_req_get_uri_args_count(ngx_http_request_t *r,
  33. int max);
  34. size_t ngx_http_lua_ffi_req_get_querystring_len(ngx_http_request_t *r);
  35. int ngx_http_lua_ffi_req_get_uri_args(ngx_http_request_t *r,
  36. unsigned char *buf, ngx_http_lua_ffi_table_elt_t *out, int count);
  37. double ngx_http_lua_ffi_req_start_time(ngx_http_request_t *r);
  38. int ngx_http_lua_ffi_req_get_method(ngx_http_request_t *r);
  39. int ngx_http_lua_ffi_req_get_method_name(ngx_http_request_t *r,
  40. char *name, size_t *len);
  41. int ngx_http_lua_ffi_req_set_method(ngx_http_request_t *r, int method);
  42. int ngx_http_lua_ffi_req_header_set_single_value(ngx_http_request_t *r,
  43. const unsigned char *key, size_t key_len, const unsigned char *value,
  44. size_t value_len);
  45. ]]
  46. local table_elt_type = ffi.typeof("ngx_http_lua_ffi_table_elt_t*")
  47. local table_elt_size = ffi.sizeof("ngx_http_lua_ffi_table_elt_t")
  48. local req_headers_mt = {
  49. __index = function (tb, key)
  50. return rawget(tb, (gsub(lower(key), '_', '-', "jo")))
  51. end
  52. }
  53. function ngx.req.get_headers(max_headers, raw)
  54. local r = getfenv(0).__ngx_req
  55. if not r then
  56. return error("no request found")
  57. end
  58. if not max_headers then
  59. max_headers = -1
  60. end
  61. if not raw then
  62. raw = 0
  63. else
  64. raw = 1
  65. end
  66. local n = C.ngx_http_lua_ffi_req_get_headers_count(r, max_headers)
  67. if n == FFI_BAD_CONTEXT then
  68. return error("API disabled in the current context")
  69. end
  70. if n == 0 then
  71. return {}
  72. end
  73. local raw_buf = get_string_buf(n * table_elt_size)
  74. local buf = ffi_cast(table_elt_type, raw_buf)
  75. local rc = C.ngx_http_lua_ffi_req_get_headers(r, buf, n, raw)
  76. if rc == 0 then
  77. local headers = new_tab(0, n)
  78. for i = 0, n - 1 do
  79. local h = buf[i]
  80. local key = h.key
  81. key = ffi_str(key.data, key.len)
  82. local value = h.value
  83. value = ffi_str(value.data, value.len)
  84. local existing = headers[key]
  85. if existing then
  86. if type(existing) == "table" then
  87. existing[#existing + 1] = value
  88. else
  89. headers[key] = {existing, value}
  90. end
  91. else
  92. headers[key] = value
  93. end
  94. end
  95. if raw == 0 then
  96. return setmetatable(headers, req_headers_mt)
  97. end
  98. return headers
  99. end
  100. return nil
  101. end
  102. function ngx.req.get_uri_args(max_args)
  103. local r = getfenv(0).__ngx_req
  104. if not r then
  105. return error("no request found")
  106. end
  107. if not max_args then
  108. max_args = -1
  109. end
  110. local n = C.ngx_http_lua_ffi_req_get_uri_args_count(r, max_args)
  111. if n == FFI_BAD_CONTEXT then
  112. return error("API disabled in the current context")
  113. end
  114. if n == 0 then
  115. return {}
  116. end
  117. local args_len = C.ngx_http_lua_ffi_req_get_querystring_len(r)
  118. local strbuf = get_string_buf(args_len + n * table_elt_size)
  119. local kvbuf = ffi_cast(table_elt_type, strbuf + args_len)
  120. local nargs = C.ngx_http_lua_ffi_req_get_uri_args(r, strbuf, kvbuf, n)
  121. local args = new_tab(0, nargs)
  122. for i = 0, nargs - 1 do
  123. local arg = kvbuf[i]
  124. local key = arg.key
  125. key = ffi_str(key.data, key.len)
  126. local value = arg.value
  127. local len = value.len
  128. if len == -1 then
  129. value = true
  130. else
  131. value = ffi_str(value.data, len)
  132. end
  133. local existing = args[key]
  134. if existing then
  135. if type(existing) == "table" then
  136. existing[#existing + 1] = value
  137. else
  138. args[key] = {existing, value}
  139. end
  140. else
  141. args[key] = value
  142. end
  143. end
  144. return args
  145. end
  146. function ngx.req.start_time()
  147. local r = getfenv(0).__ngx_req
  148. if not r then
  149. return error("no request found")
  150. end
  151. return tonumber(C.ngx_http_lua_ffi_req_start_time(r))
  152. end
  153. do
  154. local methods = {
  155. [0x0002] = "GET",
  156. [0x0004] = "HEAD",
  157. [0x0008] = "POST",
  158. [0x0010] = "PUT",
  159. [0x0020] = "DELETE",
  160. [0x0040] = "MKCOL",
  161. [0x0080] = "COPY",
  162. [0x0100] = "MOVE",
  163. [0x0200] = "OPTIONS",
  164. [0x0400] = "PROPFIND",
  165. [0x0800] = "PROPPATCH",
  166. [0x1000] = "LOCK",
  167. [0x2000] = "UNLOCK",
  168. [0x4000] = "PATCH",
  169. [0x8000] = "TRACE",
  170. }
  171. function ngx.req.get_method()
  172. local r = getfenv(0).__ngx_req
  173. if not r then
  174. return error("no request found")
  175. end
  176. do
  177. local id = C.ngx_http_lua_ffi_req_get_method(r)
  178. if id == FFI_BAD_CONTEXT then
  179. return error("API disabled in the current context")
  180. end
  181. local method = methods[id]
  182. if method then
  183. return method
  184. end
  185. end
  186. local buf = get_string_buf(32)
  187. local sizep = get_size_ptr()
  188. sizep[0] = 32
  189. local rc = C.ngx_http_lua_ffi_req_get_method_name(r, buf, sizep)
  190. if rc ~= 0 then
  191. return nil
  192. end
  193. return ffi_str(buf, sizep[0])
  194. end
  195. end -- do
  196. function ngx.req.set_method(method)
  197. local r = getfenv(0).__ngx_req
  198. if not r then
  199. return error("no request found")
  200. end
  201. if type(method) ~= "number" then
  202. return error("bad method number")
  203. end
  204. local rc = C.ngx_http_lua_ffi_req_set_method(r, method)
  205. if rc == FFI_OK then
  206. return
  207. end
  208. if rc == FFI_BAD_CONTEXT then
  209. return error("API disabled in the current context")
  210. end
  211. if rc == FFI_DECLINED then
  212. return error("unsupported HTTP method: " .. method)
  213. end
  214. return error("unknown error: " .. rc)
  215. end
  216. do
  217. local orig_func = ngx.req.set_header
  218. function ngx.req.set_header(name, value)
  219. if type(value) == "table" then
  220. return orig_func(name, value)
  221. end
  222. local r = getfenv(0).__ngx_req
  223. if not r then
  224. return error("no request found")
  225. end
  226. if type(name) ~= "string" then
  227. name = tostring(name)
  228. end
  229. local rc
  230. if not value then
  231. rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name,
  232. #name, nil, 0)
  233. else
  234. if type(value) ~= "string" then
  235. value = tostring(value)
  236. end
  237. rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name,
  238. #name, value, #value)
  239. end
  240. if rc == FFI_OK or rc == FFI_DECLINED then
  241. return
  242. end
  243. if rc == FFI_BAD_CONTEXT then
  244. return error("API disabled in the current context")
  245. end
  246. return error("error")
  247. end
  248. end -- do
  249. function ngx.req.clear_header(name, value)
  250. local r = getfenv(0).__ngx_req
  251. if not r then
  252. return error("no request found")
  253. end
  254. if type(name) ~= "string" then
  255. name = tostring(name)
  256. end
  257. local rc = C.ngx_http_lua_ffi_req_header_set_single_value(r, name, #name,
  258. nil, 0)
  259. if rc == FFI_OK or rc == FFI_DECLINED then
  260. return
  261. end
  262. if rc == FFI_BAD_CONTEXT then
  263. return error("API disabled in the current context")
  264. end
  265. return error("error")
  266. end
  267. return {
  268. version = base.version
  269. }