| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System.Diagnostics; |
| | | 5 | | using System.Diagnostics.CodeAnalysis; |
| | | 6 | | |
| | | 7 | | namespace System.Net.Http |
| | | 8 | | { |
| | | 9 | | internal static class UriRedactionHelper |
| | | 10 | | { |
| | 0 | 11 | | public static bool IsDisabled { get; } = GetDisableUriRedactionSettingValue(); |
| | | 12 | | |
| | | 13 | | private static bool GetDisableUriRedactionSettingValue() |
| | 0 | 14 | | { |
| | 0 | 15 | | if (AppContext.TryGetSwitch("System.Net.Http.DisableUriRedaction", out bool value)) |
| | 0 | 16 | | { |
| | 0 | 17 | | return value; |
| | | 18 | | } |
| | | 19 | | |
| | 0 | 20 | | string? envVar = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_HTTP_DISABLEURIREDACTION"); |
| | | 21 | | |
| | 0 | 22 | | if (bool.TryParse(envVar, out value)) |
| | 0 | 23 | | { |
| | 0 | 24 | | return value; |
| | | 25 | | } |
| | 0 | 26 | | else if (uint.TryParse(envVar, out uint intVal)) |
| | 0 | 27 | | { |
| | 0 | 28 | | return intVal != 0; |
| | | 29 | | } |
| | | 30 | | |
| | 0 | 31 | | return false; |
| | 0 | 32 | | } |
| | | 33 | | |
| | | 34 | | public static string GetRedactedPathAndQuery(string pathAndQuery) |
| | 0 | 35 | | { |
| | 0 | 36 | | Debug.Assert(pathAndQuery is not null); |
| | | 37 | | |
| | 0 | 38 | | if (!IsDisabled) |
| | 0 | 39 | | { |
| | 0 | 40 | | int queryIndex = pathAndQuery.IndexOf('?'); |
| | 0 | 41 | | if (queryIndex >= 0 && queryIndex < (pathAndQuery.Length - 1)) |
| | 0 | 42 | | { |
| | 0 | 43 | | pathAndQuery = $"{Slice(pathAndQuery, 0, queryIndex + 1)}*"; |
| | 0 | 44 | | } |
| | 0 | 45 | | } |
| | | 46 | | |
| | 0 | 47 | | return pathAndQuery; |
| | 0 | 48 | | } |
| | | 49 | | |
| | | 50 | | [return: NotNullIfNotNull(nameof(uri))] |
| | | 51 | | public static string? GetRedactedUriString(Uri? uri) |
| | 0 | 52 | | { |
| | 0 | 53 | | if (uri is null) |
| | 0 | 54 | | { |
| | 0 | 55 | | return null; |
| | | 56 | | } |
| | | 57 | | |
| | 0 | 58 | | if (IsDisabled) |
| | 0 | 59 | | { |
| | 0 | 60 | | return uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.ToString(); |
| | | 61 | | } |
| | | 62 | | |
| | 0 | 63 | | if (!uri.IsAbsoluteUri) |
| | 0 | 64 | | { |
| | | 65 | | // We cannot guarantee the redaction of UserInfo for relative Uris without implementing some subset of U |
| | | 66 | | // To avoid this, we redact the whole Uri. Seeing a relative Uri here requires a custom handler chain wi |
| | | 67 | | // custom expansion logic implemented by the user's HttpMessageHandler. |
| | | 68 | | // In such advanced scenarios we recommend users to log the Uri in their handler. |
| | 0 | 69 | | return "*"; |
| | | 70 | | } |
| | | 71 | | |
| | 0 | 72 | | string pathAndQuery = uri.PathAndQuery; |
| | 0 | 73 | | int queryIndex = pathAndQuery.IndexOf('?'); |
| | | 74 | | |
| | 0 | 75 | | bool redactQuery = queryIndex >= 0 && // Query is present. |
| | 0 | 76 | | queryIndex < pathAndQuery.Length - 1; // Query is not empty. |
| | | 77 | | |
| | 0 | 78 | | return (redactQuery, uri.IsDefaultPort) switch |
| | 0 | 79 | | { |
| | 0 | 80 | | (true, true) => $"{uri.Scheme}://{uri.Host}{Slice(pathAndQuery, 0, queryIndex + 1)}*", |
| | 0 | 81 | | (true, false) => $"{uri.Scheme}://{uri.Host}:{uri.Port}{Slice(pathAndQuery, 0, queryIndex + 1)}*", |
| | 0 | 82 | | (false, true) => $"{uri.Scheme}://{uri.Host}{pathAndQuery}", |
| | 0 | 83 | | (false, false) => $"{uri.Scheme}://{uri.Host}:{uri.Port}{pathAndQuery}" |
| | 0 | 84 | | }; |
| | 0 | 85 | | } |
| | | 86 | | |
| | | 87 | | #if NET |
| | 0 | 88 | | private static ReadOnlySpan<char> Slice(string text, int startIndex, int length) => text.AsSpan(startIndex, leng |
| | | 89 | | #else |
| | | 90 | | private static string Slice(string text, int startIndex, int length) => text.Substring(startIndex, length); |
| | | 91 | | #endif |
| | | 92 | | } |
| | | 93 | | } |