From cf7065a5670090861b5e4e35aa15e70351a2eed4 Mon Sep 17 00:00:00 2001 From: Klaus-Uwe Mitterer Date: Sat, 28 Oct 2017 17:20:10 +0200 Subject: [PATCH] More refactoring, dedicated class for requests and responses --- main.py | 350 +++++++++++++++++++++++++------------------------------- 1 file changed, 153 insertions(+), 197 deletions(-) diff --git a/main.py b/main.py index 0f0b268..a655ed7 100644 --- a/main.py +++ b/main.py @@ -7,220 +7,176 @@ import workers.val import workers.closest import workers.radar +from classes.request import * +from classes.response import * + HTTP200 = "200 OK" HTTP400 = "400 Bad Request" +HTTP405 = "405 Method Not Allowed" HTTP500 = "500 Internal Server Error" HTML = "text/html" JSON = "application/json" XML = "text/xml" -def doConn(args, cfrm = None, cto = None): +def doConn(req): + try: + getfrm = req.cfrm if "cfrm" in dir(req) and req.cfrm else req.args["from"][0] if "from" in req.args else None + getto = req.cto if "cto" in dir(req) and req.cto else req.args["to"][0] if "to" in req.args else None try: - try: - frm = (cfrm or args["from"][0]).encode("latin-1").decode("utf-8") - to = (cto or args["to"][0]).encode("latin-1").decode("utf-8") - except UnicodeDecodeError: - frm = cfrm or args["from"][0] - to = cto or args["to"][0] + frm = getfrm.encode("latin-1").decode("utf-8") + to = getto.encode("latin-1").decode("utf-8") + except UnicodeDecodeError: + frm = getfrm + to = getto - if not frm or not to: - raise ValueError() + if not frm or not to: + raise ValueError() - except Exception: - content = "

400 Bad Request

\n" - content += "\"from\"and \"to\" values are required for this type of request.\n" - return (HTTP400, HTML, content) + except Exception: + content = "

400 Bad Request

\n" + content += "\"from\"and \"to\" values are required for this type of request." + return Response(HTTP400, HTML, content) - count = args["count"][0] if "count" in args and args["count"] else 6 - date = args["date"][0] if "date" in args and args["date"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%d.%m.%Y") - time = args["time"][0] if "time" in args and args["time"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%H:%M") - mode = True if "mode" in args and args["mode"] and args["mode"][0].lower() == "arr" else False - details = True if "details" in args else False - - try: - count = int(count) - if count < 0 or count > 10: - raise ValueError() - except: - content = "

400 Bad Request

\n" - content += "The \"count\" value must be a value between 0 and 10." - return (HTTP400, HTML, content) - - try: - outtime = datetime.datetime.strptime("%s %s" % (date, time), "%d.%m.%Y %H:%M") - except: - content = "

400 Bad Request

\n" - content += "The \"date\" value must be in DD.MM.YYYY format, the \"time\" value must be in HH:MM format." - return (HTTP400, HTML, content) - - via = list(args["via"]) if "via" in args else None - - if via and len(via) > 3: - content = "

400 Bad Request

\n" - content += "It is not possible to route through more than three \"via\" stations." - return (HTTP400, HTML, content) - - json = "json" in args - - try: - content = workers.conn.worker(frm, to, count, outtime, mode, details, json, via) - except Exception as e: - content = "

500 Internal Server Error

\n" - if "debug" in args: - content += str(e) - return (HTTP500, HTML, content) - - return (HTTP200, JSON if json else XML, content) - -def doVal(args, cfrm): - try: - try: - name = (cfrm or args["name"][0]).encode("latin-1").decode("utf-8") - except UnicodeDecodeError: - name = cfrm or args["name"][0] - - if not name: - raise ValueError() - - except: - content = "

400 Bad Request

\n" - content += "A \"name\" value is required for this type of request." - return HTTP400, HTML, content - - json = "json" in args - - try: - content = workers.val.worker(name, json) - - except Exception as e: - content = "

500 Internal Server Error

\n" - if "debug" in args: - content += str(e).encode() - return HTTP500, HTML, content - - return HTTP200, JSON if json else XML, content - -def doNearby(args): - try: - lat = float(args["lat"][0].replace(",", ".")) - lon = float(args["lon"][0].replace(",", ".")) - - if (not lat and not lat == float(0)) or (not lon and not lon == float(0)): - raise ValueError() - - except: - content = "

400 Bad Request

\n" - content += "\"lat\" and \"lon\" values are required for this type of request." - return HTTP400, HTML, content - - distance = args["distance"][0] if "distance" in args and args["distance"] else 1000 - - try: - distance = int(distance) - if distance < 0 or distance > 10000: - raise ValueError() - except: - content = "

400 Bad Request

\n" - content += "\"distance\" must be a value between 0 and 10000." - return HTTP400, HTML, content - - json = "json" in args - - try: - content = workers.closest.worker(lat, lon, distance, json) - - except Exception as e: - content = "

500 Internal Server Error

" - if "debug" in args: - content += repr(e) - return HTTP500, HTML, content - - return HTTP200, JSON if json else XML, content - -def doRadar(args): - trains = args["train"] if "train" in args else None - json = "json" in args - - try: - content = workers.radar.worker(trains, json) - except Exception as e: - content = "

500 Internal Server Error

\n" - if "debug" in args: - content += repr(e) - return HTTP500, HTML, content - - return HTTP200, JSON if json else XML, content - -def application(env, re): - if env["REQUEST_METHOD"] == "POST": - args = cgi.parse_qs(env['wsgi.input'].readline().decode(), True) - elif env["REQUEST_METHOD"] == "GET": - args = cgi.parse_qs(env['QUERY_STRING'], True) - else: - re("405 Method Not Allowed", []) - return - - conn = False - val = False - cfrm = None - cto = None - - split = env["PATH_INFO"].split("/") - split = [i.strip() for i in split] - - while "" in split: - split.remove("") - - if len(split) > 2: - re("400 Bad Request", []) - yield "

400 Bad Request

".encode() - yield "Only one (validate) or two (conn) arguments may be passed as path.".encode() - return - - if len(split) > 0: - if len(split) == 1: - val = True - else: - conn = True - cto = split[1].encode("latin-1").decode("utf-8") - - cfrm = split[0].encode("latin-1").decode("utf-8") + count = req.args["count"][0] if "count" in req.args and req.args["count"] else 6 + date = req.args["date"][0] if "date" in req.args and req.args["date"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%d.%m.%Y") + time = req.args["time"][0] if "time" in req.args and req.args["time"] else datetime.datetime.strftime(datetime.datetime.now(pytz.timezone("Europe/Vienna")),"%H:%M") + mode = True if "mode" in req.args and req.args["mode"] and req.args["mode"][0].lower() == "arr" else False + details = True if "details" in req.args else False try: - rtype = "conn" if conn else "val" if val else args["type"][0] + count = int(count) + if count < 0 or count > 10: + raise ValueError() except: - re("400 Bad Request", []) - yield "

400 Bad Request

".encode() - yield "A request type must be provided.".encode() - return + content = "

400 Bad Request

\n" + content += "The \"count\" value must be a value between 0 and 10." + return Response(HTTP400, HTML, content) - if rtype.lower() in ["conn", "connection"]: - status, ctype, content = doConn(args, cfrm, cto) - re(status, [("Content-Type", ctype)]) - yield content.encode() - return + try: + outtime = datetime.datetime.strptime("%s %s" % (date, time), "%d.%m.%Y %H:%M") + except: + content = "

400 Bad Request

\n" + content += "The \"date\" value must be in DD.MM.YYYY format, the \"time\" value must be in HH:MM format." + return Response(HTTP400, HTML, content) - elif rtype.lower() in ["val", "validate"]: - status, ctype, content = doVal(args, cfrm) - re(status, [("Content-Type", ctype)]) - yield content.encode() - return + via = list(req.args["via"]) if "via" in req.args else None - elif rtype.lower() in ["closest", "close", "near", "nearby"]: - status, ctype, content = doNearby(args) - re(status, [("Content-Type", ctype)]) - yield content.encode() - return + if via and len(via) > 3: + content = "

400 Bad Request

\n" + content += "It is not possible to route through more than three \"via\" stations." + return Response(HTTP400, HTML, content) - elif rtype.lower() in ["radar", "live"]: - status, ctype, content = doRadar(args) - re(status, [("Content-Type", ctype)]) - yield content.encode() - return + try: + content = workers.conn.worker(frm, to, count, outtime, mode, details, req.json, via) + except Exception as e: + content = "

500 Internal Server Error

\n" + if "debug" in req.args: + content += str(e) + return Response(HTTP500, HTML, content) + + return Response(HTTP200, JSON if req.json else XML, content) + +def doVal(req): + try: + try: + name = (req.cfrm or req.args["name"][0]).encode("latin-1").decode("utf-8") + except UnicodeDecodeError: + name = req.cfrm or req.args["name"][0] + + if not name: + raise ValueError() + + except Exception: + content = "

400 Bad Request

\n" + content += "A \"name\" value is required for this type of request." + return Response(HTTP400, HTML, content) + + try: + content = workers.val.worker(name, req.json) + + except Exception as e: + content = "

500 Internal Server Error

\n" + if "debug" in req.args: + content += str(e).encode() + return Response(HTTP500, HTML, content) + + return Response(HTTP200, JSON if req.json else XML, content) + +def doNearby(req): + try: + lat = float(req.args["lat"][0].replace(",", ".")) + lon = float(req.args["lon"][0].replace(",", ".")) + + if (not lat and not lat == float(0)) or (not lon and not lon == float(0)): + raise ValueError() + + except: + content = "

400 Bad Request

\n" + content += "\"lat\" and \"lon\" values are required for this type of request." + return Response(HTTP400, HTML, content) + + distance = req.args["distance"][0] if "distance" in req.args and req.args["distance"] else 1000 + + try: + distance = int(distance) + if distance < 0 or distance > 10000: + raise ValueError() + except: + content = "

400 Bad Request

\n" + content += "\"distance\" must be a value between 0 and 10000." + return Response(HTTP400, HTML, content) + + try: + content = workers.closest.worker(lat, lon, distance, req.json) + + except Exception as e: + content = "

500 Internal Server Error

" + if "debug" in req.args: + content += repr(e) + return Response(HTTP500, HTML, content) + + return Response(HTTP200, JSON if req.json else XML, content) + +def doRadar(req): + trains = req.args["train"] if "train" in req.args else None + + try: + content = workers.radar.worker(trains, req.json) + except Exception as e: + content = "

500 Internal Server Error

\n" + if "debug" in req.args: + content += repr(e) + return Response(HTTP500, HTML, content) + + return Response(HTTP200, JSON if req.json else XML, content) + +def doNot(req): + content = "

400 Bad Request

" + content += "The request type you submitted is invalid." + return Response(HTTP400, HTML, content) + +def application(env, re): + try: + req = Request(env) + + if req.rtype in ["conn", "connection"]: + res = doConn(req) + elif req.rtype in ["val", "validate"]: + res = doVal(req) + elif req.rtype in ["closest", "close", "near", "nearby"]: + res = doNearby(req) + elif req.rtype in ["radar", "live"]: + res = doRadar(req) + else: + res = doNot(req) + + except IllegalMethodException as e: + res = Response(HTTP405, HTML, str(e)) + except InvalidArgumentException as e: + res = Response(HTTP400, HTML, str(e)) + + re(res.status, [("Content-Type", res.ctype)]) + yield res.content.encode() + return - else: - re("400 Bad Request", []) - yield "

400 Bad Request

".encode() - yield "The request type you submitted is invalid.".encode() - return