# 路由器 下面是一个 HTTP 状态代码的定义: **2xx:成功**: * 200 正常,请求已完成。 * 201 正常,紧接POST命令。 * 202 正常,已接受用于处理,但处理尚未完成。 * 203 正常,部分信息—返回的信息只是一部分。 * 204 正常,无响应—已接收请求,但不存在要回送的信息。 **3xx:重定向**: * 301 已移动,请求的数据具有新的位置且更改是永久的。 * 302 已找到,请求的数据临时具有不同 URI。 * 303 请参阅其它,可在另一 URI 下找到对请求的响应,且应使用 GET 方法检索此响应。 * 304 未修改,未按预期修改文档。 * 305 使用代理,必须通过位置字段中提供的代理来访问请求的资源。 * 306 未使用,不再使用,保留此代码以便将来使用。 **4xx:客户机中出现的错误**: * 400 错误请求,请求中有语法问题,或不能满足请求。 * 401 未授权,未授权客户机访问数据。 * 402 需要付款,表示计费系统已有效。 * 403 禁止,即使有授权也不需要访问。 * 404 找不到,服务器找不到给定的资源;文档不存在。 * 407 代理认证请求,客户机首先必须使用代理认证自身。 * 415 介质类型不受支持,服务器拒绝服务请求,因为不支持请求实体的格式。 **5xx:服务器中出现的错误**: * 500 内部错误,因为意外情况,服务器不能完成请求。 * 501 未执行,服务器不支持请求的工具。 * 502 错误网关,服务器接收到来自上游服务器的无效响应。 * 503 无法获得服务,由于临时过载或维护,服务器无法处理请求。 编写一个路由服务,支持注入路由配置,正确处理请求参数 ```python # -*- coding: UTF-8 -*- from error_code import ErrorCode import json import logging import traceback logger = logging.getLogger(__name__) class Router: def __init__(self, routes) -> None: self.routes = routes def dispatch(self, http_request_str): # TODO(You): 请实现路由逻辑,返回符合语义的HTTP状态码 if __name__ == '__main__': # 注册路由 router = Router({ '/': lambda req: print(f'goto home:{str(req)}') }) # 分发路由 router.dispatch(json.dumps({ 'path': '/', 'data': ["Hello", "World!"] })) ``` 以下路由的逻辑代码都一样,请选出**HTTP状态码符合语义**的选项。 ## template ```python from error_code import ErrorCode import json import logging import traceback logger = logging.getLogger(__name__) class Router: def __init__(self, routes) -> None: self.routes = routes def dispatch(self, http_request_str): ''' 实现一个路由器 http_request_str: 请求数据字符串,包含 {path:"",data:""}格式的JSON字符串 ''' assert http_request_str is not None assert type(http_request_str) == type('') req_path = None req = None try: http_request = json.loads(http_request_str) req_path = http_request.get('path') req = http_request.get('data') except Exception as e: logger.error(f"parse data exception:{str(e)}") return {'err': ErrorCode.INVALID_PARAMETERS}, 200 if req_path is None or self.routes.get(req_path) is None: return {'err': ErrorCode.NOT_FOUND}, 404 try: handler = self.routes.get(req_path) return handler(req), 200 except Exception as e: logger.error(f"route to '{req_path}' exception:{str(e)}") logger.error(traceback.format_exc()) return {'err': ErrorCode.FAILED}, 500 if __name__ == '__main__': server = Router({ '/': lambda req: print(f'goto home:{str(req)}') }) server.dispatch(json.dumps({ 'path': '/', 'data': ["Hello", "World!"] })) ``` ## 答案 ```python class Router: def dispatch(self, http_request_str): req_path = None req = None try: http_request = json.loads(http_request_str) req_path = http_request.get('path') req = http_request.get('data') except Exception as e: logger.error(f"parse data exception:{str(e)}") return {'err': ErrorCode.INVALID_PARAMETERS}, 400 if req_path is None or self.routes.get(req_path) is None: return {'err': ErrorCode.NOT_FOUND}, 404 try: handler = self.routes.get(req_path) return handler(req), 200 except Exception as e: logger.error(f"route to '{req_path}' exception:{str(e)}") logger.error(traceback.format_exc()) return {'err': ErrorCode.FAILED}, 500 ``` ## 选项 ### A ```python class Router: def dispatch(self, http_request_str): req_path = None req = None try: http_request = json.loads(http_request_str) req_path = http_request.get('path') req = http_request.get('data') except Exception as e: logger.error(f"parse data exception:{str(e)}") return {'err': ErrorCode.INVALID_PARAMETERS}, 200 if req_path is None or self.routes.get(req_path) is None: return {'err': ErrorCode.NOT_FOUND}, 200 try: handler = self.routes.get(req_path) return handler(req), 200 except Exception as e: logger.error(f"route to '{req_path}' exception:{str(e)}") logger.error(traceback.format_exc()) return {'err': ErrorCode.FAILED}, 200 ``` ### B ```python class Router: def dispatch(self, http_request_str): req_path = None req = None try: http_request = json.loads(http_request_str) req_path = http_request.get('path') req = http_request.get('data') except Exception as e: logger.error(f"parse data exception:{str(e)}") return {'err': ErrorCode.INVALID_PARAMETERS}, 301 if req_path is None or self.routes.get(req_path) is None: return {'err': ErrorCode.NOT_FOUND}, 404 try: handler = self.routes.get(req_path) return handler(req), 200 except Exception as e: logger.error(f"route to '{req_path}' exception:{str(e)}") logger.error(traceback.format_exc()) return {'err': ErrorCode.FAILED}, 500 ``` ### C ```python class Router: def dispatch(self, http_request_str): req_path = None req = None try: http_request = json.loads(http_request_str) req_path = http_request.get('path') req = http_request.get('data') except Exception as e: logger.error(f"parse data exception:{str(e)}") return {'err': ErrorCode.INVALID_PARAMETERS}, 200 if req_path is None or self.routes.get(req_path) is None: return {'err': ErrorCode.NOT_FOUND}, 200 try: handler = self.routes.get(req_path) return handler(req), 200 except Exception as e: logger.error(f"route to '{req_path}' exception:{str(e)}") logger.error(traceback.format_exc()) return {'err': ErrorCode.FAILED}, 500 ```