public override int GetHashCode() { throw null; }
public static bool operator ==(System.Net.Http.HttpMethod? left, System.Net.Http.HttpMethod? right) { throw null; }
public static bool operator !=(System.Net.Http.HttpMethod? left, System.Net.Http.HttpMethod? right) { throw null; }
+ public static System.Net.Http.HttpMethod Parse(ReadOnlySpan<char> method) { throw null; }
public override string ToString() { throw null; }
}
public sealed class HttpProtocolException : System.Net.Http.HttpIOException
return !(left == right);
}
+ /// <summary>Parses the provided <paramref name="method"/> into an <see cref="HttpMethod"/> instance.</summary>
+ /// <param name="method">The method to parse.</param>
+ /// <returns>An <see cref="HttpMethod"/> instance for the provided <paramref name="method"/>.</returns>
+ /// <remarks>
+ /// This method may return a singleton instance for known methods; for example, it may return <see cref="Get"/>
+ /// if "GET" is specified. The parsing is performed in a case-insensitive manner, so it may also return <see cref="Get"/>
+ /// if "get" is specified. For unknown methods, a new <see cref="HttpMethod"/> instance is returned, with the
+ /// same validation being performed as by the <see cref="HttpMethod(string)"/> constructor.
+ /// </remarks>
+ public static HttpMethod Parse(ReadOnlySpan<char> method) =>
+ GetKnownMethod(method) ??
+ new HttpMethod(method.ToString());
+
/// <summary>
/// Returns a singleton method instance with a capitalized method name for the supplied method
/// if it's known; otherwise, returns the original.
// _http3Index is only set for the singleton instances, so if it's not null,
// we can avoid the lookup. Otherwise, look up the method instance and return the
// normalized instance if it's found.
+ return method._http3Index is null && GetKnownMethod(method._method) is HttpMethod match ?
+ match :
+ method;
+ }
- if (method._http3Index is null && method._method.Length >= 3) // 3 == smallest known method
+ private static HttpMethod? GetKnownMethod(ReadOnlySpan<char> method)
+ {
+ if (method.Length >= 3) // 3 == smallest known method
{
- HttpMethod? match = (method._method[0] | 0x20) switch
+ HttpMethod? match = (method[0] | 0x20) switch
{
'c' => s_connectMethod,
'd' => s_deleteMethod,
'g' => s_getMethod,
'h' => s_headMethod,
'o' => s_optionsMethod,
- 'p' => method._method.Length switch
+ 'p' => method.Length switch
{
3 => s_putMethod,
4 => s_postMethod,
_ => null,
};
- if (match is not null && string.Equals(method._method, match._method, StringComparison.OrdinalIgnoreCase))
+ if (match is not null &&
+ method.Equals(match._method, StringComparison.OrdinalIgnoreCase))
{
return match;
}
}
- return method;
+ return null;
}
internal bool MustHaveRequestBody
{
using (HttpClient client = CreateHttpClient())
{
- HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("CONNECT"), url) { Version = UseVersion };
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Connect, url) { Version = UseVersion };
request.Headers.Host = "foo.com:345";
// We need to use ResponseHeadersRead here, otherwise we will hang trying to buffer the response body.
{
using (HttpClient client = CreateHttpClient())
{
- HttpRequestMessage request = new HttpRequestMessage(new HttpMethod("CONNECT"), url) { Version = UseVersion };
+ HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Connect, url) { Version = UseVersion };
request.Headers.Host = "foo.com:345";
// We need to use ResponseHeadersRead here, otherwise we will hang trying to buffer the response body.
Task<HttpResponseMessage> responseTask = client.SendAsync(TestAsync, request, HttpCompletionOption.ResponseHeadersRead);
Assert.Equal("PATCH", HttpMethod.Patch.Method);
}
+ public static IEnumerable<object[]> Parse_UsesKnownInstances_MemberData()
+ {
+ yield return new object[] { HttpMethod.Connect, nameof(HttpMethod.Connect) };
+ yield return new object[] { HttpMethod.Delete, nameof(HttpMethod.Delete) };
+ yield return new object[] { HttpMethod.Get, nameof(HttpMethod.Get) };
+ yield return new object[] { HttpMethod.Head, nameof(HttpMethod.Head) };
+ yield return new object[] { HttpMethod.Options, nameof(HttpMethod.Options) };
+ yield return new object[] { HttpMethod.Patch, nameof(HttpMethod.Patch) };
+ yield return new object[] { HttpMethod.Post, nameof(HttpMethod.Post) };
+ yield return new object[] { HttpMethod.Put, nameof(HttpMethod.Put) };
+ yield return new object[] { HttpMethod.Trace, nameof(HttpMethod.Trace) };
+ }
+
+ [Theory]
+ [MemberData(nameof(Parse_UsesKnownInstances_MemberData))]
+ public void Parse_KnownMethod_UsesKnownInstances(HttpMethod method, string methodName)
+ {
+ Assert.Same(method, HttpMethod.Parse(methodName));
+ Assert.Same(method, HttpMethod.Parse(methodName.ToUpperInvariant()));
+ Assert.Same(method, HttpMethod.Parse(methodName.ToLowerInvariant()));
+ }
+
+ [Theory]
+ [InlineData("Unknown")]
+ [InlineData("custom")]
+ public void Parse_UnknownMethod_UsesNewInstances(string method)
+ {
+ var h = HttpMethod.Parse(method);
+ Assert.NotNull(h);
+ Assert.NotSame(h, HttpMethod.Parse(method));
+ }
+
+ [Theory]
+ [InlineData("")]
+ [InlineData(" ")]
+ public void Parse_Whitespace_ThrowsArgumentException(string method)
+ {
+ AssertExtensions.Throws<ArgumentException>("method", () => HttpMethod.Parse(method));
+ }
+
+ [Theory]
+ [InlineData(" GET ")]
+ [InlineData(" Post")]
+ [InlineData("Put ")]
+ [InlineData("multiple things")]
+ public void Parse_InvalidToken_Throws(string method)
+ {
+ Assert.Throws<FormatException>(() => HttpMethod.Parse(method));
+ }
+
private static void AddStaticHttpMethods(List<object[]> staticHttpMethods)
{
staticHttpMethods.Add(new object[] { HttpMethod.Patch });
{
using HttpMessageInvoker client = CreateHttpMessageInvoker();
using InstrumentRecorder<double> recorder = SetupInstrumentRecorder<double>(InstrumentNames.RequestDuration);
- using HttpRequestMessage request = new(new HttpMethod(method), uri) { Version = UseVersion };
+ using HttpRequestMessage request = new(HttpMethod.Parse(method), uri) { Version = UseVersion };
using HttpResponseMessage response = await SendAsync(client, request);
throw new InvalidOperationException(SR.net_reqsubmitted);
}
- var request = new HttpRequestMessage(new HttpMethod(_originVerb), _requestUri);
+ var request = new HttpRequestMessage(HttpMethod.Parse(_originVerb), _requestUri);
bool disposeRequired = false;
HttpClient? client = null;