Builds a scope and request body into a WSGI environ object.
(scope: Scope, body: bytes)
| 24 | |
| 25 | |
| 26 | def build_environ(scope: Scope, body: bytes) -> dict[str, Any]: |
| 27 | """ |
| 28 | Builds a scope and request body into a WSGI environ object. |
| 29 | """ |
| 30 | |
| 31 | script_name = scope.get("root_path", "").encode("utf8").decode("latin1") |
| 32 | path_info = scope["path"].encode("utf8").decode("latin1") |
| 33 | if path_info.startswith(script_name): |
| 34 | path_info = path_info[len(script_name) :] |
| 35 | |
| 36 | environ = { |
| 37 | "REQUEST_METHOD": scope["method"], |
| 38 | "SCRIPT_NAME": script_name, |
| 39 | "PATH_INFO": path_info, |
| 40 | "QUERY_STRING": scope["query_string"].decode("ascii"), |
| 41 | "SERVER_PROTOCOL": f"HTTP/{scope['http_version']}", |
| 42 | "wsgi.version": (1, 0), |
| 43 | "wsgi.url_scheme": scope.get("scheme", "http"), |
| 44 | "wsgi.input": io.BytesIO(body), |
| 45 | "wsgi.errors": sys.stdout, |
| 46 | "wsgi.multithread": True, |
| 47 | "wsgi.multiprocess": True, |
| 48 | "wsgi.run_once": False, |
| 49 | } |
| 50 | |
| 51 | # Get server name and port - required in WSGI, not in ASGI |
| 52 | server = scope.get("server") or ("localhost", 80) |
| 53 | environ["SERVER_NAME"] = server[0] |
| 54 | environ["SERVER_PORT"] = server[1] |
| 55 | |
| 56 | # Get client IP address |
| 57 | if scope.get("client"): |
| 58 | environ["REMOTE_ADDR"] = scope["client"][0] |
| 59 | |
| 60 | # Go through headers and make them into environ entries |
| 61 | for name, value in scope.get("headers", []): |
| 62 | name = name.decode("latin1") |
| 63 | if name == "content-length": |
| 64 | corrected_name = "CONTENT_LENGTH" |
| 65 | elif name == "content-type": |
| 66 | corrected_name = "CONTENT_TYPE" |
| 67 | else: |
| 68 | corrected_name = f"HTTP_{name}".upper().replace("-", "_") |
| 69 | # HTTPbis say only ASCII chars are allowed in headers, but we latin1 just in |
| 70 | # case |
| 71 | value = value.decode("latin1") |
| 72 | if corrected_name in environ: |
| 73 | value = environ[corrected_name] + "," + value |
| 74 | environ[corrected_name] = value |
| 75 | return environ |
| 76 | |
| 77 | |
| 78 | class WSGIMiddleware: |