关于.net:HttpServerUtility.UrlTokenEncode替换netstandard

HttpServerUtility.UrlTokenEncode replacement for netstandard

我正在把一个针对net472的项目移植到netstandard上。我最后一个依赖于System.Web的是HttpServerUtility.UrlTokenEncode(Byte[])

我找到了Microsoft.AspNetCore.WebUtilities,其中包含Base64UrlTextEncoderWebEncoders,但这些不能与UrlTokenEncodeDecode互换,因为它在末尾附加/预期了=填充字符的数量,例如:

1
2
3
4
5
6
var data = Encoding.UTF8.GetBytes("SO");
Convert.ToBase64String(data);              // U08=
HttpServerUtility.UrlTokenEncode(data);    // U081 - this is what's expected and
                                           // the only thing UrlTokenDecode can handle
Base64UrlTextEncoder.Encode(data);         // U08
WebEncoders.Base64UrlEncode(data);         // U08

据我所知,没有其他差异(我用随机字符串运行测试),但它也引入了一些我在该项目中不真正需要的其他依赖项(Microsoft.net.http.headersµsoft.extensions.primitives)。

有替换掉的Nuget套餐吗?如果不是的话,我正在考虑自己来实现这一点。


我的吻,解决方案,适用于netstandard1.6

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static class Utils
{
    private static readonly Regex InvalidBase64UrlTokens = new Regex(
        @"[^=a-z0-9]",
        RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);

    public static string Base64UrlTokenEncode(byte[] data)
    {
        var padding = 0;
        var base64String = Convert.ToBase64String(data);
        return InvalidBase64UrlTokens.Replace(base64String, m => {
            switch (m.Value)
            {
                case"+": return"-";
                case"=":
                    padding++;
                    return"";
                default: return"_";
            }
        }) + padding;
    }
}

通过以下Nunit测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[TestFixture]
public class Base64UrlTokenEncodingTests
{        
    private static IEnumerable<TestCaseData> CompareAgainstSystemWebImplementationCases()
    {
        var random = new Random(42);
        for (var i = 0; i < 100; i++)
        {
            var bytes = new byte[i + 1];
            random.NextBytes(bytes);

            var name = Convert.ToBase64String(bytes);
            var systemWeb = System.Web.HttpServerUtility.UrlTokenEncode(bytes);
            yield return new TestCaseData(bytes).SetName(name).Returns(systemWeb);
        }
    }

    [TestCaseSource(nameof(CompareAgainstSystemWebImplementationCases))]
    public string CompareAgainstSystemWebImplementation(byte[] data) =>
        Utils.Base64UrlTokenEncode(data);
}