2 LuCI - HTTP-Interaction
5 HTTP-Header manipulator and form variable preprocessor
11 Copyright 2008 Steven Barth <steven@midlink.org>
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
17 http://www.apache.org/licenses/LICENSE-2.0
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
27 --- LuCI Web Framework high-level HTTP functions.
28 module("luci.http", package.seeall)
29 local ltn12 = require("luci.ltn12")
30 require("luci.http.protocol")
33 context = luci.util.threadlocal()
35 Request = luci.util.class()
36 function Request.__init__(self, env, sourcein, sinkerr)
42 self.filehandler = function() end
48 params = luci.http.protocol.urldecode_params(env.QUERY_STRING or ""),
51 self.parsed_input = false
54 function Request.formvalue(self, name, noparse)
55 if not noparse and not self.parsed_input then
60 return self.message.params[name]
62 return self.message.params
66 function Request.formvaluetable(self, prefix)
68 prefix = prefix and prefix .. "." or "."
70 if not self.parsed_input then
74 local void = self.message.params[nil]
75 for k, v in pairs(self.message.params) do
76 if k:find(prefix, 1, true) == 1 then
77 vals[k:sub(#prefix + 1)] = tostring(v)
84 function Request.content(self)
85 if not self.parsed_input then
89 return self.message.content, self.message.content_length
92 function Request.getcookie(self, name)
93 local c = string.gsub(";" .. (self:getenv("HTTP_COOKIE") or "") .. ";", "%s*;%s*", ";")
94 local p = ";" .. name .. "=(.-);"
95 local i, j, value = c:find(p)
96 return value and urldecode(value)
99 function Request.getenv(self, name)
101 return self.message.env[name]
103 return self.message.env
107 function Request.setfilehandler(self, callback)
108 self.filehandler = callback
111 function Request._parse_input(self)
112 luci.http.protocol.parse_message_body(
117 self.parsed_input = true
120 --- Close the HTTP-Connection.
122 if not context.eoh then
127 if not context.closed then
128 context.closed = true
133 --- Return the request content if the request was of unknown type.
134 -- @return HTTP request body
135 -- @return HTTP request body length
137 return context.request:content()
140 --- Get a certain HTTP input value or a table of all input values.
141 -- @param name Name of the GET or POST variable to fetch
142 -- @param noparse Don't parse POST data before getting the value
143 -- @return HTTP input value or table of all input value
144 function formvalue(name, noparse)
145 return context.request:formvalue(name, noparse)
148 --- Get a table of all HTTP input values with a certain prefix.
149 -- @param prefix Prefix
150 -- @return Table of all HTTP input values with given prefix
151 function formvaluetable(prefix)
152 return context.request:formvaluetable(prefix)
155 --- Get the value of a certain HTTP-Cookie.
156 -- @param name Cookie Name
157 -- @return String containing cookie data
158 function getcookie(name)
159 return context.request:getcookie(name)
162 --- Get the value of a certain HTTP environment variable
163 -- or the environment table itself.
164 -- @param name Environment variable
165 -- @return HTTP environment value or environment table
166 function getenv(name)
167 return context.request:getenv(name)
170 --- Set a handler function for incoming user file uploads.
171 -- @param callback Handler function
172 function setfilehandler(callback)
173 return context.request:setfilehandler(callback)
176 --- Send a HTTP-Header.
177 -- @param key Header key
178 -- @param value Header value
179 function header(key, value)
180 if not context.headers then
183 context.headers[key:lower()] = value
184 coroutine.yield(2, key, value)
187 --- Set the mime type of following content data.
188 -- @param mime Mimetype of following content
189 function prepare_content(mime)
190 if mime == "application/xhtml+xml" then
191 if not getenv("HTTP_ACCEPT") or
192 not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
193 mime = "text/html; charset=UTF-8"
195 header("Vary", "Accept")
197 header("Content-Type", mime)
200 --- Get the RAW HTTP input source
201 -- @return HTTP LTN12 source
203 return context.request.input
206 --- Set the HTTP status code and status message.
207 -- @param code Status code
208 -- @param message Status message
209 function status(code, message)
211 message = message or "OK"
212 context.status = code
213 coroutine.yield(1, code, message)
216 --- Send a chunk of content data to the client.
217 -- This function is as a valid LTN12 sink.
218 -- If the content chunk is nil this function will automatically invoke close.
219 -- @param content Content chunk
220 -- @param src_err Error object from source (optional)
222 function write(content, src_err)
230 elseif #content == 0 then
233 if not context.eoh then
234 if not context.status then
237 if not context.headers or not context.headers["content-type"] then
238 header("Content-Type", "text/html; charset=utf-8")
240 if not context.headers["cache-control"] then
241 header("Cache-Control", "no-cache")
242 header("Expires", "0")
249 coroutine.yield(4, content)
254 --- Redirects the client to a new URL and closes the connection.
255 -- @param url Target URL
256 function redirect(url)
258 header("Location", url)
262 --- Create a querystring out of a table of key - value pairs.
263 -- @param table Query string source table
264 -- @return Encoded HTTP query string
265 function build_querystring(table)
268 for k, v in pairs(table) do
269 s = s .. urlencode(k) .. "=" .. urlencode(v) .. "&"
275 --- Return the URL-decoded equivalent of a string.
276 -- @param str URL-encoded string
277 -- @param no_plus Don't decode + to " "
278 -- @return URL-decoded string
280 urldecode = luci.http.protocol.urldecode
282 --- Return the URL-encoded equivalent of a string.
283 -- @param str Source string
284 -- @return URL-encoded string
286 urlencode = luci.http.protocol.urlencode