为什么我只从 HttpContext 中获取 URL 的一部分?

Why I get only part of the URL from the HttpContext?

我使用代理从远程服务器获取资源。

这是代理 class:

public class Proxy : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        string url = context.Request["url"];
        var request = (HttpWebRequest)WebRequest.Create(url);
        request.UserAgent = context.Request.UserAgent;
        request.ContentType = context.Request.ContentType;
        request.Method = context.Request.HttpMethod;

        request.ProtocolVersion = HttpVersion.Version11;
        request.KeepAlive = false;
        request.Timeout = 100000;
        request.ReadWriteTimeout = 100000;
        using (var response = request.GetResponse())
        {
            context.Response.ContentType = response.ContentType;
            using (var responseStream = response.GetResponseStream())
            {
                if (responseStream == null) return;

                responseStream.CopyTo(context.Response.OutputStream);
                context.Response.OutputStream.Flush();
            }
        }
    }
}

这是我对远程服务的 ajax 调用:

function wfs(layer) {

    let dest_url = "https://www.mysited.com/geodata2055/service/mapagent.fcgi?SERVICE=WFS&MAXFEATURES=500&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=ns216630453:WW_MONITOR";
    let proxy_url = "/localhost/Proxy.ashx?url=";
    let url = proxy_url + dest_url;

    var xhr = new XMLHttpRequest();
    xhr.open('GET', url); // depricated-'/proxy.ashx?url='+

    xhr.onload = function () {
        if (xhr.status === 200) {
            console.log("loader success");
        } else {
            console.log("loader fail");
        }
    },
        xhr.send();
}

当触发 wfs 函数时,代理 class 中的 ProcessRequest 函数被触发并且 url 变量的值为:

https://www.mysited.com/geodata2055/service/mapagent.fcgi?SERVICE=WFS

虽然我希望 url 的值为:

https://www.mysited.com/geodata2055/service/mapagent.fcgi?SERVICE=WFS&MAXFEATURES=500&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=ns216630453:WW_MONITOR

似乎 context.Request["url"] returns 将值削减到第一个 '&'。

知道为什么我只从 context.Request["url"] 得到 url 的一部分吗?

您需要对查询参数进行编码,因为它不包含对查询参数安全的字符:

let url = "/localhost/Proxy.ashx?url=" + encodeURIComponent(dest_url);

为了进一步解释,让我们假设我们是一个 URL 解析器。没有编码,你会看到这个字符串:

/localhost/Proxy.ashx?url=https://www.mysited.com/geodata2055/service/mapagent.fcgi?SERVICE=WFS&MAXFEATURES=500&VERSION=1.0.0&REQUEST=GetFeature&TYPENAME=ns216630453:WW_MONITOR

解析器在访问字符时将执行这些步骤:

URL path:              /localhost/Proxy.ashx 
Query params starting: ?
Param name:            url
Starting param value:  =
(some of these next chars aren't valid, but I'll try my best!)
Param value:        
   https://www.mysited.com/geodata2055/service/mapagent.fcgi?SERVICE=WFS
Starting next param:   &
Param name:            MAXFEATURES
Starting param value:  =
Param value:           500
...etc

所以因为它在扫描您的字符串时遇到 &,它认为 MAXFEATURES 之类的参数是您代理请求的查询参数, 不是 的一部分传递给代理请求的 url 参数。因此,当您的代理代码运行时,它只会看到 &.

之前的内容

编码 URL 参数将得到:

/localhost/Proxy.ashx?url=https%3A%2F%2Fwww.mysited.com%2Fgeodata2055%2Fservice%2Fmapagent.fcgi%3FSERVICE%3DWFS%26MAXFEATURES%3D500%26VERSION%3D1.0.0%26REQUEST%3DGetFeature%26TYPENAME%3Dns216630453%3AWW_MONITOR

有了这个,解析器现在只能看到传递给代理处理程序的 url 参数。当代理处理程序现在解析 url 参数时,它会 解码 它,返回你原来的 dest_url

作为一般经验法则,永远不要只使用字符串连接来构建 URLs; URL 不是由字符串组成的,它们是由 URL 编码的字符串组成的。