2
0

http.lua 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Copyright 2010-2018 Jo-Philipp Wich <jo@mein.io>
  3. -- Licensed to the public under the Apache License 2.0.
  4. local util = require "luci.util"
  5. local coroutine = require "coroutine"
  6. local table = require "table"
  7. local lhttp = require "lucihttp"
  8. local nixio = require "nixio"
  9. local ltn12 = require "luci.ltn12"
  10. local table, ipairs, pairs, type, tostring, tonumber, error =
  11. table, ipairs, pairs, type, tostring, tonumber, error
  12. module "luci.http"
  13. HTTP_MAX_CONTENT = 1024*100 -- 100 kB maximum content size
  14. context = util.threadlocal()
  15. Request = util.class()
  16. function Request.__init__(self, env, sourcein, sinkerr)
  17. self.input = sourcein
  18. self.error = sinkerr
  19. -- File handler nil by default to let .content() work
  20. self.filehandler = nil
  21. -- HTTP-Message table
  22. self.message = {
  23. env = env,
  24. headers = {},
  25. params = urldecode_params(env.QUERY_STRING or ""),
  26. }
  27. self.parsed_input = false
  28. end
  29. function Request.formvalue(self, name, noparse)
  30. if not noparse and not self.parsed_input then
  31. self:_parse_input()
  32. end
  33. if name then
  34. return self.message.params[name]
  35. else
  36. return self.message.params
  37. end
  38. end
  39. function Request.formvaluetable(self, prefix)
  40. local vals = {}
  41. prefix = prefix and prefix .. "." or "."
  42. if not self.parsed_input then
  43. self:_parse_input()
  44. end
  45. local void = self.message.params[nil]
  46. for k, v in pairs(self.message.params) do
  47. if k:find(prefix, 1, true) == 1 then
  48. vals[k:sub(#prefix + 1)] = tostring(v)
  49. end
  50. end
  51. return vals
  52. end
  53. function Request.content(self)
  54. if not self.parsed_input then
  55. self:_parse_input()
  56. end
  57. return self.message.content, self.message.content_length
  58. end
  59. function Request.getcookie(self, name)
  60. return lhttp.header_attribute("cookie; " .. (self:getenv("HTTP_COOKIE") or ""), name)
  61. end
  62. function Request.getenv(self, name)
  63. if name then
  64. return self.message.env[name]
  65. else
  66. return self.message.env
  67. end
  68. end
  69. function Request.setfilehandler(self, callback)
  70. self.filehandler = callback
  71. if not self.parsed_input then
  72. return
  73. end
  74. -- If input has already been parsed then uploads are stored as unlinked
  75. -- temporary files pointed to by open file handles in the parameter
  76. -- value table. Loop all params, and invoke the file callback for any
  77. -- param with an open file handle.
  78. local name, value
  79. for name, value in pairs(self.message.params) do
  80. if type(value) == "table" then
  81. while value.fd do
  82. local data = value.fd:read(1024)
  83. local eof = (not data or data == "")
  84. callback(value, data, eof)
  85. if eof then
  86. value.fd:close()
  87. value.fd = nil
  88. end
  89. end
  90. end
  91. end
  92. end
  93. function Request._parse_input(self)
  94. parse_message_body(
  95. self.input,
  96. self.message,
  97. self.filehandler
  98. )
  99. self.parsed_input = true
  100. end
  101. function close()
  102. if not context.eoh then
  103. context.eoh = true
  104. coroutine.yield(3)
  105. end
  106. if not context.closed then
  107. context.closed = true
  108. coroutine.yield(5)
  109. end
  110. end
  111. function content()
  112. return context.request:content()
  113. end
  114. function formvalue(name, noparse)
  115. return context.request:formvalue(name, noparse)
  116. end
  117. function formvaluetable(prefix)
  118. return context.request:formvaluetable(prefix)
  119. end
  120. function getcookie(name)
  121. return context.request:getcookie(name)
  122. end
  123. -- or the environment table itself.
  124. function getenv(name)
  125. return context.request:getenv(name)
  126. end
  127. function setfilehandler(callback)
  128. return context.request:setfilehandler(callback)
  129. end
  130. function header(key, value)
  131. if not context.headers then
  132. context.headers = {}
  133. end
  134. context.headers[key:lower()] = value
  135. coroutine.yield(2, key, value)
  136. end
  137. function prepare_content(mime)
  138. if not context.headers or not context.headers["content-type"] then
  139. if mime == "application/xhtml+xml" then
  140. if not getenv("HTTP_ACCEPT") or
  141. not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
  142. mime = "text/html; charset=UTF-8"
  143. end
  144. header("Vary", "Accept")
  145. end
  146. header("Content-Type", mime)
  147. end
  148. end
  149. function source()
  150. return context.request.input
  151. end
  152. function status(code, message)
  153. code = code or 200
  154. message = message or "OK"
  155. context.status = code
  156. coroutine.yield(1, code, message)
  157. end
  158. -- This function is as a valid LTN12 sink.
  159. -- If the content chunk is nil this function will automatically invoke close.
  160. function write(content, src_err)
  161. if not content then
  162. if src_err then
  163. error(src_err)
  164. else
  165. close()
  166. end
  167. return true
  168. elseif #content == 0 then
  169. return true
  170. else
  171. if not context.eoh then
  172. if not context.status then
  173. status()
  174. end
  175. if not context.headers or not context.headers["content-type"] then
  176. header("Content-Type", "text/html; charset=utf-8")
  177. end
  178. if not context.headers["cache-control"] then
  179. header("Cache-Control", "no-cache")
  180. header("Expires", "0")
  181. end
  182. if not context.headers["x-frame-options"] then
  183. header("X-Frame-Options", "SAMEORIGIN")
  184. end
  185. if not context.headers["x-xss-protection"] then
  186. header("X-XSS-Protection", "1; mode=block")
  187. end
  188. if not context.headers["x-content-type-options"] then
  189. header("X-Content-Type-Options", "nosniff")
  190. end
  191. context.eoh = true
  192. coroutine.yield(3)
  193. end
  194. coroutine.yield(4, content)
  195. return true
  196. end
  197. end
  198. function splice(fd, size)
  199. coroutine.yield(6, fd, size)
  200. end
  201. function redirect(url)
  202. if url == "" then url = "/" end
  203. status(302, "Found")
  204. header("Location", url)
  205. close()
  206. end
  207. function build_querystring(q)
  208. local s, n, k, v = {}, 1, nil, nil
  209. for k, v in pairs(q) do
  210. s[n+0] = (n == 1) and "?" or "&"
  211. s[n+1] = util.urlencode(k)
  212. s[n+2] = "="
  213. s[n+3] = util.urlencode(v)
  214. n = n + 4
  215. end
  216. return table.concat(s, "")
  217. end
  218. urldecode = util.urldecode
  219. urlencode = util.urlencode
  220. function write_json(x)
  221. util.serialize_json(x, write)
  222. end
  223. -- from given url or string. Returns a table with urldecoded values.
  224. -- Simple parameters are stored as string values associated with the parameter
  225. -- name within the table. Parameters with multiple values are stored as array
  226. -- containing the corresponding values.
  227. function urldecode_params(url, tbl)
  228. local parser, name
  229. local params = tbl or { }
  230. parser = lhttp.urlencoded_parser(function (what, buffer, length)
  231. if what == parser.TUPLE then
  232. name, value = nil, nil
  233. elseif what == parser.NAME then
  234. name = lhttp.urldecode(buffer)
  235. elseif what == parser.VALUE and name then
  236. params[name] = lhttp.urldecode(buffer) or ""
  237. end
  238. return true
  239. end)
  240. if parser then
  241. parser:parse((url or ""):match("[^?]*$"))
  242. parser:parse(nil)
  243. end
  244. return params
  245. end
  246. -- separated by "&". Tables are encoded as parameters with multiple values by
  247. -- repeating the parameter name with each value.
  248. function urlencode_params(tbl)
  249. local k, v
  250. local n, enc = 1, {}
  251. for k, v in pairs(tbl) do
  252. if type(v) == "table" then
  253. local i, v2
  254. for i, v2 in ipairs(v) do
  255. if enc[1] then
  256. enc[n] = "&"
  257. n = n + 1
  258. end
  259. enc[n+0] = lhttp.urlencode(k)
  260. enc[n+1] = "="
  261. enc[n+2] = lhttp.urlencode(v2)
  262. n = n + 3
  263. end
  264. else
  265. if enc[1] then
  266. enc[n] = "&"
  267. n = n + 1
  268. end
  269. enc[n+0] = lhttp.urlencode(k)
  270. enc[n+1] = "="
  271. enc[n+2] = lhttp.urlencode(v)
  272. n = n + 3
  273. end
  274. end
  275. return table.concat(enc, "")
  276. end
  277. -- Content-Type. Stores all extracted data associated with its parameter name
  278. -- in the params table within the given message object. Multiple parameter
  279. -- values are stored as tables, ordinary ones as strings.
  280. -- If an optional file callback function is given then it is fed with the
  281. -- file contents chunk by chunk and only the extracted file name is stored
  282. -- within the params table. The callback function will be called subsequently
  283. -- with three arguments:
  284. -- o Table containing decoded (name, file) and raw (headers) mime header data
  285. -- o String value containing a chunk of the file data
  286. -- o Boolean which indicates whether the current chunk is the last one (eof)
  287. function mimedecode_message_body(src, msg, file_cb)
  288. local parser, header, field
  289. local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil)
  290. parser, err = lhttp.multipart_parser(msg.env.CONTENT_TYPE, function (what, buffer, length)
  291. if what == parser.PART_INIT then
  292. field = { }
  293. elseif what == parser.HEADER_NAME then
  294. header = buffer:lower()
  295. elseif what == parser.HEADER_VALUE and header then
  296. if header:lower() == "content-disposition" and
  297. lhttp.header_attribute(buffer, nil) == "form-data"
  298. then
  299. field.name = lhttp.header_attribute(buffer, "name")
  300. field.file = lhttp.header_attribute(buffer, "filename")
  301. field[1] = field.file
  302. end
  303. if field.headers then
  304. field.headers[header] = buffer
  305. else
  306. field.headers = { [header] = buffer }
  307. end
  308. elseif what == parser.PART_BEGIN then
  309. return not field.file
  310. elseif what == parser.PART_DATA and field.name and length > 0 then
  311. if field.file then
  312. if file_cb then
  313. file_cb(field, buffer, false)
  314. msg.params[field.name] = msg.params[field.name] or field
  315. else
  316. if not field.fd then
  317. field.fd = nixio.mkstemp(field.name)
  318. end
  319. if field.fd then
  320. field.fd:write(buffer)
  321. msg.params[field.name] = msg.params[field.name] or field
  322. end
  323. end
  324. else
  325. field.value = buffer
  326. end
  327. elseif what == parser.PART_END and field.name then
  328. if field.file and msg.params[field.name] then
  329. if file_cb then
  330. file_cb(field, "", true)
  331. elseif field.fd then
  332. field.fd:seek(0, "set")
  333. end
  334. else
  335. local val = msg.params[field.name]
  336. if type(val) == "table" then
  337. val[#val+1] = field.value or ""
  338. elseif val ~= nil then
  339. msg.params[field.name] = { val, field.value or "" }
  340. else
  341. msg.params[field.name] = field.value or ""
  342. end
  343. end
  344. field = nil
  345. elseif what == parser.ERROR then
  346. err = buffer
  347. end
  348. return true
  349. end, HTTP_MAX_CONTENT)
  350. return ltn12.pump.all(src, function (chunk)
  351. len = len + (chunk and #chunk or 0)
  352. if maxlen and len > maxlen + 2 then
  353. return nil, "Message body size exceeds Content-Length"
  354. end
  355. if not parser or not parser:parse(chunk) then
  356. return nil, err
  357. end
  358. return true
  359. end)
  360. end
  361. -- Content-Type. Stores all extracted data associated with its parameter name
  362. -- in the params table within the given message object. Multiple parameter
  363. -- values are stored as tables, ordinary ones as strings.
  364. function urldecode_message_body(src, msg)
  365. local err, name, value, parser
  366. local len, maxlen = 0, tonumber(msg.env.CONTENT_LENGTH or nil)
  367. parser = lhttp.urlencoded_parser(function (what, buffer, length)
  368. if what == parser.TUPLE then
  369. name, value = nil, nil
  370. elseif what == parser.NAME then
  371. name = lhttp.urldecode(buffer, lhttp.DECODE_PLUS)
  372. elseif what == parser.VALUE and name then
  373. local val = msg.params[name]
  374. if type(val) == "table" then
  375. val[#val+1] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or ""
  376. elseif val ~= nil then
  377. msg.params[name] = { val, lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or "" }
  378. else
  379. msg.params[name] = lhttp.urldecode(buffer, lhttp.DECODE_PLUS) or ""
  380. end
  381. elseif what == parser.ERROR then
  382. err = buffer
  383. end
  384. return true
  385. end, HTTP_MAX_CONTENT)
  386. return ltn12.pump.all(src, function (chunk)
  387. len = len + (chunk and #chunk or 0)
  388. if maxlen and len > maxlen + 2 then
  389. return nil, "Message body size exceeds Content-Length"
  390. elseif len > HTTP_MAX_CONTENT then
  391. return nil, "Message body size exceeds maximum allowed length"
  392. end
  393. if not parser or not parser:parse(chunk) then
  394. return nil, err
  395. end
  396. return true
  397. end)
  398. end
  399. -- This function will examine the Content-Type within the given message object
  400. -- to select the appropriate content decoder.
  401. -- Currently the application/x-www-urlencoded and application/form-data
  402. -- mime types are supported. If the encountered content encoding can't be
  403. -- handled then the whole message body will be stored unaltered as "content"
  404. -- property within the given message object.
  405. function parse_message_body(src, msg, filecb)
  406. if msg.env.CONTENT_LENGTH or msg.env.REQUEST_METHOD == "POST" then
  407. local ctype = lhttp.header_attribute(msg.env.CONTENT_TYPE, nil)
  408. -- Is it multipart/mime ?
  409. if ctype == "multipart/form-data" then
  410. return mimedecode_message_body(src, msg, filecb)
  411. -- Is it application/x-www-form-urlencoded ?
  412. elseif ctype == "application/x-www-form-urlencoded" then
  413. return urldecode_message_body(src, msg)
  414. end
  415. -- Unhandled encoding
  416. -- If a file callback is given then feed it chunk by chunk, else
  417. -- store whole buffer in message.content
  418. local sink
  419. -- If we have a file callback then feed it
  420. if type(filecb) == "function" then
  421. local meta = {
  422. name = "raw",
  423. encoding = msg.env.CONTENT_TYPE
  424. }
  425. sink = function( chunk )
  426. if chunk then
  427. return filecb(meta, chunk, false)
  428. else
  429. return filecb(meta, nil, true)
  430. end
  431. end
  432. -- ... else append to .content
  433. else
  434. msg.content = ""
  435. msg.content_length = 0
  436. sink = function( chunk )
  437. if chunk then
  438. if ( msg.content_length + #chunk ) <= HTTP_MAX_CONTENT then
  439. msg.content = msg.content .. chunk
  440. msg.content_length = msg.content_length + #chunk
  441. return true
  442. else
  443. return nil, "POST data exceeds maximum allowed length"
  444. end
  445. end
  446. return true
  447. end
  448. end
  449. -- Pump data...
  450. while true do
  451. local ok, err = ltn12.pump.step( src, sink )
  452. if not ok and err then
  453. return nil, err
  454. elseif not ok then -- eof
  455. return true
  456. end
  457. end
  458. return true
  459. end
  460. return false
  461. end