def _runwsgi()

in eden/scm/edenscm/mercurial/hgweb/hgweb_mod.py [0:0]


    def _runwsgi(self, req, repo):
        rctx = requestcontext(self, repo)

        # This state is global across all threads.
        encoding.encoding = rctx.config("web", "encoding")
        rctx.repo.ui.environ = req.env

        if rctx.csp:
            # hgwebdir may have added CSP header. Since we generate our own,
            # replace it.
            req.headers = [h for h in req.headers if h[0] != "Content-Security-Policy"]
            req.headers.append(("Content-Security-Policy", rctx.csp))

        # work with CGI variables to create coherent structure
        # use SCRIPT_NAME, PATH_INFO and QUERY_STRING as well as our REPO_NAME

        req.url = req.env[r"SCRIPT_NAME"]
        if not req.url.endswith("/"):
            req.url += "/"
        if req.env.get("REPO_NAME"):
            req.url += req.env[r"REPO_NAME"] + r"/"

        if r"PATH_INFO" in req.env:
            parts = req.env[r"PATH_INFO"].strip("/").split("/")
            repo_parts = req.env.get(r"REPO_NAME", r"").split(r"/")
            if parts[: len(repo_parts)] == repo_parts:
                parts = parts[len(repo_parts) :]
            query = "/".join(parts)
        else:
            query = req.env[r"QUERY_STRING"].partition(r"&")[0]
            query = query.partition(r";")[0]

        # process this if it's a protocol request
        # protocol bits don't need to create any URLs
        # and the clients always use the old URL structure

        cmd = req.form.get(r"cmd", [r""])[0]
        if protocol.iscmd(cmd):
            try:
                if query:
                    raise ErrorResponse(HTTP_NOT_FOUND)
                if cmd in perms:
                    self.check_perm(rctx, req, perms[cmd])
                return protocol.call(rctx.repo, req, cmd)
            except ErrorResponse as inst:
                # A client that sends unbundle without 100-continue will
                # break if we respond early.
                if (
                    cmd == "unbundle"
                    and (req.env.get("HTTP_EXPECT", "").lower() != "100-continue")
                    or req.env.get("X-HgHttp2", "")
                ):
                    req.drain()
                else:
                    req.headers.append((r"Connection", r"Close"))
                req.respond(inst, protocol.HGTYPE, body="0\n%s\n" % inst)
                return ""

        # translate user-visible url structure to internal structure

        args = query.split("/", 2)
        if r"cmd" not in req.form and args and args[0]:
            cmd = args.pop(0)
            style = cmd.rfind("-")
            if style != -1:
                req.form["style"] = [cmd[:style]]
                cmd = cmd[style + 1 :]

            # avoid accepting e.g. style parameter as command
            if util.safehasattr(webcommands, cmd):
                req.form[r"cmd"] = [cmd]

            if cmd == "static":
                req.form["file"] = ["/".join(args)]
            else:
                if args and args[0]:
                    node = args.pop(0).replace("%2F", "/")
                    req.form["node"] = [node]
                if args:
                    req.form["file"] = args

            ua = req.env.get("HTTP_USER_AGENT", "")
            if cmd == "rev" and "mercurial" in ua:
                req.form["style"] = ["raw"]

            if cmd == "archive":
                fn = req.form["node"][0]
                for type_, spec in pycompat.iteritems(rctx.archivespecs):
                    ext = spec[2]
                    if fn.endswith(ext):
                        req.form["node"] = [fn[: -len(ext)]]
                        req.form["type"] = [type_]

        # process the web interface request

        try:
            tmpl = rctx.templater(req)
            ctype = tmpl("mimetype", encoding=encoding.encoding)
            ctype = templater.stringify(ctype)

            # check read permissions non-static content
            if cmd != "static":
                self.check_perm(rctx, req, None)

            if cmd == "":
                req.form[r"cmd"] = [tmpl.cache["default"]]
                cmd = req.form[r"cmd"][0]

            # Don't enable caching if using a CSP nonce because then it wouldn't
            # be a nonce.
            if rctx.configbool("web", "cache") and not rctx.nonce:
                caching(self, req)  # sets ETag header or raises NOT_MODIFIED
            if cmd not in webcommands.__all__:
                msg = "no such method: %s" % cmd
                raise ErrorResponse(HTTP_BAD_REQUEST, msg)
            elif cmd == "file" and r"raw" in req.form.get(r"style", []):
                rctx.ctype = ctype
                content = webcommands.rawfile(rctx, req, tmpl)
            else:
                content = getattr(webcommands, cmd)(rctx, req, tmpl)
                req.respond(HTTP_OK, ctype)

            return content

        except (error.LookupError, error.RepoLookupError) as err:
            req.respond(HTTP_NOT_FOUND, ctype)
            msg = str(err)
            if util.safehasattr(err, "name") and not isinstance(
                err, error.ManifestLookupError
            ):
                msg = "revision not found: %s" % err.name
            return tmpl("error", error=msg)
        except (error.RepoError, error.RevlogError) as inst:
            req.respond(HTTP_SERVER_ERROR, ctype)
            return tmpl("error", error=str(inst))
        except ErrorResponse as inst:
            req.respond(inst, ctype)
            if inst.code == HTTP_NOT_MODIFIED:
                # Not allowed to return a body on a 304
                return [""]
            return tmpl("error", error=str(inst))