Example #1
0
    def send_head(self, headersOnly=False):
        headers = {}
        path = self.path.split("?", 1)[0]

        if path == "/vehicle.json":
            global outputList
            global outputListLock
            expired = False
            outputListCopy = None
            with outputListLock:
                outputListCopy = outputList.copy()
            if b"relaytime" not in outputListCopy:
                expired = True  # no data yet
            elif self.server.thread.cacheExpire == 0.0:
                pass
            elif time(
            ) > outputListCopy[b"relaytime"] + self.server.thread.cacheExpire:
                expired = True
            if not expired:
                encoded = simpleDictionaryToJSON(outputListCopy)
            if not expired:
                response = HTTPStatus.OK
                contentType = "application/json"
            else:
                encoded = b"No available up-to-date data"
                response = HTTPStatus.GATEWAY_TIMEOUT
                contentType = "text/plain"
        elif path == "/vehicle.ws":
            self.webSocketClass = WebSocket_vehicle
            info = WebSocket.prepareHeaders(self)
            encoded = info["encoded"]
            response = info["response"]
            contentType = info["contentType"]
            headers = info["headers"]
        else:
            encoded = b"Not found"
            response = HTTPStatus.NOT_FOUND
            contentType = "text/plain"

        f = BytesIO()
        f.write(encoded)
        f.seek(0)
        self.send_response(response)
        if contentType is not None:
            self.send_header("Content-type", contentType)
        if headersOnly:
            self.send_header("Content-Length", "0")
        else:
            self.send_header("Content-Length", str(len(encoded)))
        for header in headers.items():
            self.send_header(header[0], header[1])
        self.send_header("Access-Control-Allow-Origin", "*")
        self.end_headers()
        return f
    def send_head(self, headersOnly=False):
        headers = {}

        currentThread = threading.currentThread()
        currentThread.name = "%s %s" % (self.command, self.path)
        path = self.path.split("?", 1)[0]

        if path == "/frames.ws":
            self.webSocketClass = WebSocket_frames
            info = WebSocket.prepareHeaders(self)
            encoded = info["encoded"]
            response = info["response"]
            contentType = info["contentType"]
            headers = info["headers"]
        elif path == "/threads.txt":
            contentLines = [b"List of known running threads:"]
            currentThread = threading.currentThread()
            for thread in threading.enumerate():
                if thread is currentThread:
                    contentLines.append(
                        ("%5u: This request" % (thread.ident or 0, )).encode(
                            "utf_8", errors="replace"))
                else:
                    threadModuleName = str(thread.run.__func__.__module__)
                    threadClassName = type(thread).__name__
                    threadTargetClassName = None
                    if type(
                            thread
                    ) is threading.Thread:  # is not of a meaningful class
                        try:
                            threadTargetClass = type(thread._target.__self__)
                            threadModuleName = str(
                                threadTargetClass.__module__)
                            threadClassName = str(threadTargetClass.__name__)
                        except:
                            pass
                    contentLines.append(("%5u: %s.%s(%s, %s) [%s]" % (
                        thread.ident or 0,
                        threadModuleName,
                        threadClassName,
                        str(thread._args)[1:-1],
                        str(thread._kwargs)[1:-1],
                        thread.name,
                    )).encode("utf_8", errors="replace"))
            contentLines.append(
                b"\r\nOn Windows the CPU usage can be monitored for each thread using SysInternals Autoruns."
            )
            encoded = b"\r\n".join(contentLines)
            response = HTTPStatus.OK
            contentType = "text/plain"
        elif path[:5] == "/api/":
            contentType = "application/json"
            response = HTTPStatus.OK
            errorString = None
            data = {}
            canBus = self.server.thread.canBus
            try:
                postData = None
                if self.command == "POST":
                    postContentLength = None
                    try:
                        postContentLength = int(
                            self.headers.get("Content-Length"))
                    except TypeError:
                        pass
                    except ValueError:
                        pass
                    if postContentLength is None or postContentLength < 0:
                        raise StatusLengthRequired()
                    if postContentLength > self.maxPostLength:
                        raise StatusPayloadTooLarge()
                    postPayload = self.rfile.read(postContentLength)
                    postContentType = self.headers.get(
                        "Content-Type", "application/x-www-form-urlencoded")
                    if postContentType[:16] == "application/json":
                        try:
                            postData = json_loads(postPayload.decode("utf_8"))
                        except ValueError:
                            pass
                    elif postContentType[:
                                         33] == "application/x-www-form-urlencoded":
                        postData_ = None
                        try:
                            postData_ = parse_qs(postPayload.decode("ascii"),
                                                 keep_blank_values=True,
                                                 strict_parsing=True)
                        except ValueError:
                            pass
                        if postData_ is not None:
                            postData = {}
                            for pair in postData_.items():
                                # dict of lists => dict of {str and lists}
                                if pair[0][-2:] == "[]":
                                    # explicit list
                                    postData[pair[0][:-2]] = pair[1]
                                elif len(pair[1]) == 1:
                                    # single str
                                    postData[pair[0]] = pair[1][0]
                                else:
                                    # implicit list
                                    postData[pair[0]] = pair[1]
                        del postData_
                    if postData is None:
                        raise StatusBadRequest()
                # Note: each POST data can be str or list or int!
                if path == "/api/filter1/installByMask":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    try:
                        mask = self.postFieldToIdentifier(postData["mask"])
                        maskingResult = self.postFieldToIdentifier(
                            postData["maskingResult"])
                    except KeyError:
                        raise StatusBadRequest()
                    canBus.setFilter1Remote(mask, maskingResult)
                elif path == "/api/filter1/installByIds":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    try:
                        whitelist = self.postFieldToIdentifiersSet(
                            postData, "whitelist")
                    except KeyError:
                        raise StatusBadRequest()
                    if whitelist is None:
                        # only vanish whitelist
                        canBus.setFilter1Local(None)
                    else:
                        # set filter as well
                        canBus.setFilter1(whitelist)
                elif path == "/api/filter1/getInstalled":
                    maskInfo = canBus.getFilter1Remote()
                    data["mask"] = maskInfo[0]
                    data["maskingResult"] = maskInfo[1]
                    del maskInfo
                    whitelist = canBus.getFilter1Local()
                    whitelist = (whitelist
                                 is not None) and list(whitelist) or None
                    data["whitelist"] = whitelist
                    del whitelist
                elif path == "/api/filter1/reset":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    canBus.setFilter1(None)
                elif path == "/api/filter2/setExcluded":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    try:
                        blacklist = self.postFieldToIdentifiersSet(
                            postData, "blacklist")
                    except KeyError:
                        raise StatusBadRequest()
                    canBus.setFilter2(blacklist)
                elif path == "/api/filter2/getExcluded":
                    blacklist = canBus.getFilter2()
                    blacklist = (blacklist
                                 is not None) and list(blacklist) or None
                    data["blacklist"] = blacklist
                    del blacklist
                elif path == "/api/filter2/reset":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    canBus.setFilter2(None)
                elif path == "/api/setInactivityTimeout":
                    if postData is None:
                        raise StatusMethodNotAllowed()
                    try:
                        inactivityTimeout = float(postData["timeout"])
                    except TypeError:
                        raise StatusBadRequest()
                    except ValueError:
                        raise StatusBadRequest()
                    if inactivityTimeout <= 0.:
                        raise StatusBadRequest()
                    canBus.inactivityTimeout = inactivityTimeout
                elif path == "/api/getInactivityTimeout":
                    data["timeout"] = canBus.inactivityTimeout
                else:
                    raise StatusNotFound()
            except Status as e:
                response = e.status
                errorString = e.text
            except Exception as e:
                printT(format_exc())
                response = HTTPStatus.INTERNAL_SERVER_ERROR
                errorString = repr(e)
            del canBus
            if response == HTTPStatus.OK:
                data["status"] = 200
            else:
                data = {
                    "status": int(response),
                    "error": errorString,
                }
            encoded = json_dumps(data).encode("utf_8", errors="replace")
        elif path in self.staticFiles:
            diskFileExcept = None
            try:
                diskFile = open(self.staticFiles[path], "rb")
                encoded = diskFile.read()
                diskFile.close()
                response = HTTPStatus.OK
                ext_4 = path[-5:].lower()
                ext_3 = ext_4[-4:]
                ext_2 = ext_4[-3:]
                contentType = "application/octet-stream"
                if ext_3 == ".htm" or ext_4 == ".html":
                    contentType = "text/html; charset=utf-8"
                elif ext_2 == ".js":
                    contentType = "text/javascript"
                elif ext_3 == ".css":
                    contentType = "text/css"
            except FileNotFoundError as e:
                diskFileExcept = e
                response = HTTPStatus.NOT_FOUND
            except PermissionError as e:
                diskFileExcept = e
                response = HTTPStatus.FORBIDDEN
            except Exception as e:
                printT(format_exc())
                diskFileExcept = e
                response = HTTPStatus.INTERNAL_SERVER_ERROR
            if diskFileExcept:
                encoded = repr(diskFileExcept).encode("utf_8", "replace")
                contentType = "text/plain"
        else:
            encoded = b"Not found"
            response = HTTPStatus.NOT_FOUND
            contentType = "text/plain"

        f = BytesIO()
        f.write(encoded)
        f.seek(0)
        self.send_response(response)
        if contentType is not None:
            self.send_header("Content-type", contentType)
        if headersOnly:
            self.send_header("Content-Length", "0")
        else:
            self.send_header("Content-Length", str(len(encoded)))
        for header in headers.items():
            self.send_header(header[0], header[1])
        self.send_header("Access-Control-Allow-Origin", "*")
        self.end_headers()
        return f