19 import mimetypes
as mime
28 import http.server
as BaseHTTPServer
33 import _webiopi.GPIO
as GPIO
37 WEBIOPI_DOCROOT =
"/usr/share/webiopi/htdocs"
39 class HTTPServer(BaseHTTPServer.HTTPServer, threading.Thread):
41 address_family = socket.AF_INET6
43 def __init__(self, host, port, handler, context, docroot, index, auth=None, realm=None):
45 BaseHTTPServer.HTTPServer.__init__(self, (
"", port), HTTPHandler)
48 BaseHTTPServer.HTTPServer.__init__(self, (
"", port), HTTPHandler)
50 threading.Thread.__init__(self, name=
"HTTPThread")
56 if not self.context.startswith(
"/"):
58 if not self.context.endswith(
"/"):
68 self.
index =
"index.html"
81 sock, addr = self.socket.accept()
89 except Exception
as e:
92 info(
"HTTP Server stopped")
99 logger = logging.getLogger(
"HTTP")
108 return VERSION_STRING
111 if self.server.auth ==
None or len(self.server.auth) == 0:
114 authHeader = self.headers.get(
'Authorization')
115 if authHeader ==
None:
118 if not authHeader.startswith(
"Basic "):
121 auth = authHeader.replace(
"Basic ",
"")
122 if PYTHON_MAJOR >= 3:
123 auth_hash =
encrypt(auth.encode())
127 if auth_hash == self.server.auth:
132 self.send_response(401)
133 self.send_header(
"WWW-Authenticate", self.server.authenticateHeader)
138 self.logger.debug(
'"%s %s %s" - %s %s (Client: %s <%s>)' % (self.
command, self.path, self.request_version, code, self.responses[code][0], self.client_address[0], self.headers[
"User-Agent"]))
143 self.send_error(code, body)
145 self.send_error(code)
147 self.send_response(code)
148 self.send_header(
"Cache-Control",
"no-cache")
150 encodedBody = body.encode();
151 self.send_header(
"Content-Type", contentType);
152 self.send_header(
"Content-Length", len(encodedBody));
154 self.wfile.write(encodedBody)
158 if os.path.exists(filepath):
159 if os.path.isdir(filepath):
160 filepath +=
"/" + self.server.index
161 if os.path.exists(filepath):
169 if self.server.docroot !=
None:
170 path = self.
findFile(self.server.docroot +
"/" + relativePath)
172 path = self.
findFile(
"./" + relativePath)
175 path = self.
findFile(
"./" + relativePath)
177 path = self.
findFile(WEBIOPI_DOCROOT +
"/" + relativePath)
179 if path ==
None and (relativePath.startswith(
"webiopi.")
or relativePath.startswith(
"jquery")):
180 path = self.
findFile(WEBIOPI_DOCROOT +
"/" + relativePath)
185 realPath = os.path.realpath(path)
187 if realPath.endswith(
".py"):
190 if not (realPath.startswith(os.getcwd())
191 or (self.server.docroot
and realPath.startswith(self.server.docroot))
192 or realPath.startswith(WEBIOPI_DOCROOT)):
195 (contentType, encoding) = mime.guess_type(path)
196 f = codecs.open(path, encoding=encoding)
199 self.send_response(200)
200 self.send_header(
"Content-Type", contentType);
201 self.send_header(
"Content-Length", os.path.getsize(realPath))
203 self.wfile.write(data)
207 self.request.settimeout(
None)
211 request = self.path.replace(self.server.context,
"/").split(
'?')
212 relativePath = request[0]
213 if relativePath[0] ==
"/":
214 relativePath = relativePath[1:]
216 if relativePath ==
"webiopi" or relativePath ==
"webiopi/":
217 self.send_response(301)
218 self.send_header(
"Location",
"/")
224 for s
in request[1].split(
'&'):
226 (name, value) = s.split(
'=')
232 if 'compact' in params:
233 compact =
str2bool(params[
'compact'])
236 result = (
None,
None,
None)
238 result = self.server.handler.do_GET(relativePath, compact)
241 length_header =
'content-length'
242 if length_header
in self.headers:
243 length = int(self.headers[length_header])
244 result = self.server.handler.do_POST(relativePath, self.rfile.read(length), compact)
246 result = (405,
None,
None)
248 (code, body, contentType) = result
258 except (GPIO.InvalidDirectionException, GPIO.InvalidChannelException, GPIO.SetupException)
as e:
260 except ValueError
as e:
262 except Exception
as e:
def requestAuthentication