【问题标题】:Changing the scheme of System.Uri更改 System.Uri 的方案
【发布时间】:2013-07-31 20:43:00
【问题描述】:

我正在寻找使用System.UriBuilder 更改给定System.Uri 实例方案的规范方法,而无需进行糟糕的字符串操作和魔术常量。说我有

var uri = new Uri("http://localhost/hello")

我需要将其更改为“https”。我的问题是有限的 UriBuilder ctors 和 Uri.Port 默认为 80(我们应该将其更改为 443?硬编码?)。代码必须尊重所有 Uri 属性,例如可能的基本身份验证凭据、查询字符串等。

【问题讨论】:

    标签: c# .net url uri


    【解决方案1】:

    结束了这个:

    var uriBuilder = new UriBuilder(requestUrl)
    {
        Scheme = Uri.UriSchemeHttps,
        Port = -1 // default port for scheme
    };
    

    【讨论】:

    • 请注意 - 由于某种原因,方案名称字段不适用于 PCL 项目(请参阅 here)。
    • 仅出于完整性考虑:这不适用于具有非默认端口的 URI(例如,http://localhost:12345/hello 将更改为 https://localhost/hello)。
    • 在我正在编写的操作过滤器中,我通过立即使用解决了这个问题:if (filterContext.RequestContext.HttpContext.Request.IsLocal && filterContext.HttpContext.Request.Url.Host.Contains("localhost")) uriBuilder.Port = <my assigned https port>; 我更愿意动态拉取分配的端口,但我不确定这是否可能。另外,在我的情况下,我永远不会使用 localhost 从服务器浏览网站,所以如果你有这个要求,你可能希望以不同的方式处理它。
    【解决方案2】:

    UserControl's answer 工作正常,除非您必须确保在 URI 中保留非默认端口。

    例如,http://localhost:12345/hello 应该变为 https://localhost:12345/hello 而不是 https://localhost/hello

    以下是如何轻松做到这一点:

    public static string ForceHttps(string requestUrl)
    {
        var uri = new UriBuilder(requestUrl);
    
        var hadDefaultPort = uri.Uri.IsDefaultPort;
        uri.Scheme = Uri.UriSchemeHttps;
        uri.Port = hadDefaultPort ? -1 : uri.Port;
    
        return uri.ToString();
    }
    

    请注意,我们必须在设置uri.Scheme之前阅读uri.Uri.IsDefaultPort

    这是一个工作示例:https://dotnetfiddle.net/pDrF7s

    【讨论】:

      【解决方案3】:

      如果您想使用自定义端口号,我更喜欢将所需的 https 端口号传递给 ForceHttps 方法,否则省略 https 端口或使用 -1 来使用标准端口号(隐式)。我真的不关心 url 上已经存在的端口,因为 http 和 https 永远不能在同一服务器上使用相同的端口。

      如果 url 已经是 https,它将保持不变,保留任何端口。

      private static string ForceHttps(string requestUrl, int? httpsPort = null)
      {
          var uri = new UriBuilder(requestUrl);
          // Handle https: let the httpsPort value override existing port if specified
          if (uri.Uri.Scheme.Equals(Uri.UriSchemeHttps)) {
              if (httpsPort.HasValue)
                  uri.Port = httpsPort.Value;
              return uri.Uri.AbsoluteUri;
          }
      
          // Handle http: override the scheme and use either the specified https port or the default https port
          uri.Scheme = Uri.UriSchemeHttps;
          uri.Port = httpsPort.HasValue ? httpsPort.Value : -1;
      
          return uri.Uri.AbsoluteUri;
      }
      

      用法:

      ForceHttps("http://www.google.com/"); // https://www.google.com/
      ForceHttps("http://www.google.com/", 225); // https://www.google.com:225/
      ForceHttps("http://www.google.com/", 443); // https://www.google.com:443/
      ForceHttps("https://www.google.com/"); // https://www.google.com/
      ForceHttps("https://www.google.com:443/"); // https://www.google.com:443/
      ForceHttps("https://www.google.com:443/", -1); // https://www.google.com/
      ForceHttps("http://www.google.com:80/"); // https://www.google.com/
      ForceHttps("http://www.google.com:3000/", 8080); // https://www.google.com:8080/
      

      【讨论】:

        【解决方案4】:

        晚安书呆子骄傲的答案的另一个迭代,作为扩展:

        public static Uri RewriteHttps(this Uri originalUri)
        {
            return new UriBuilder(originalUri)
            {
                Scheme = Uri.UriSchemeHttps,
                Port = originalUri.IsDefaultPort ? -1 : originalUri.Port // -1 => default port for scheme
            }.Uri;
        }
        

        【讨论】:

          猜你喜欢
          • 2011-09-02
          • 1970-01-01
          • 2012-07-06
          • 2021-05-06
          • 2017-10-30
          • 2012-08-30
          • 2017-12-05
          • 1970-01-01
          • 2017-07-13
          相关资源
          最近更新 更多