Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit bd47922

Browse files
committed
Replace With to use more flexible + binary resilient HttpRequestConfig
1 parent e586113 commit bd47922

File tree

5 files changed

+179
-39
lines changed

5 files changed

+179
-39
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#nullable enable
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Text;
6+
7+
namespace ServiceStack;
8+
9+
public class HttpRequestConfig
10+
{
11+
public string? Accept { get; set; }
12+
public string? UserAgent { get; set; }
13+
public string? ContentType { get; set; }
14+
public KeyValuePair<string,string>? Authorization { get; set; }
15+
public Dictionary<string, string>? Headers { get; set; }
16+
17+
public string AuthBearer
18+
{
19+
set => Authorization = new("Bearer", value);
20+
}
21+
22+
public KeyValuePair<string, string> AuthBasic
23+
{
24+
set => Authorization = new("Basic",
25+
Convert.ToBase64String(Encoding.UTF8.GetBytes(value.Key + ":" + value.Value)));
26+
}
27+
}

src/ServiceStack.Text/HttpStatus.cs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
namespace ServiceStack.Text;
2+
3+
public static class HttpStatus
4+
{
5+
public static string GetStatusDescription(int statusCode)
6+
{
7+
if (statusCode is >= 100 and < 600)
8+
{
9+
int i = statusCode / 100;
10+
int j = statusCode % 100;
11+
12+
if (j < Descriptions[i].Length)
13+
return Descriptions[i][j];
14+
}
15+
16+
return string.Empty;
17+
}
18+
19+
private static readonly string[][] Descriptions =
20+
{
21+
null,
22+
new[]
23+
{
24+
/* 100 */ "Continue",
25+
/* 101 */ "Switching Protocols",
26+
/* 102 */ "Processing"
27+
},
28+
new[]
29+
{
30+
/* 200 */ "OK",
31+
/* 201 */ "Created",
32+
/* 202 */ "Accepted",
33+
/* 203 */ "Non-Authoritative Information",
34+
/* 204 */ "No Content",
35+
/* 205 */ "Reset Content",
36+
/* 206 */ "Partial Content",
37+
/* 207 */ "Multi-Status"
38+
},
39+
new[]
40+
{
41+
/* 300 */ "Multiple Choices",
42+
/* 301 */ "Moved Permanently",
43+
/* 302 */ "Found",
44+
/* 303 */ "See Other",
45+
/* 304 */ "Not Modified",
46+
/* 305 */ "Use Proxy",
47+
/* 306 */ string.Empty,
48+
/* 307 */ "Temporary Redirect"
49+
},
50+
new[]
51+
{
52+
/* 400 */ "Bad Request",
53+
/* 401 */ "Unauthorized",
54+
/* 402 */ "Payment Required",
55+
/* 403 */ "Forbidden",
56+
/* 404 */ "Not Found",
57+
/* 405 */ "Method Not Allowed",
58+
/* 406 */ "Not Acceptable",
59+
/* 407 */ "Proxy Authentication Required",
60+
/* 408 */ "Request Timeout",
61+
/* 409 */ "Conflict",
62+
/* 410 */ "Gone",
63+
/* 411 */ "Length Required",
64+
/* 412 */ "Precondition Failed",
65+
/* 413 */ "Request Entity Too Large",
66+
/* 414 */ "Request-Uri Too Long",
67+
/* 415 */ "Unsupported Media Type",
68+
/* 416 */ "Requested Range Not Satisfiable",
69+
/* 417 */ "Expectation Failed",
70+
/* 418 */ string.Empty,
71+
/* 419 */ string.Empty,
72+
/* 420 */ string.Empty,
73+
/* 421 */ string.Empty,
74+
/* 422 */ "Unprocessable Entity",
75+
/* 423 */ "Locked",
76+
/* 424 */ "Failed Dependency"
77+
},
78+
new[]
79+
{
80+
/* 500 */ "Internal Server Error",
81+
/* 501 */ "Not Implemented",
82+
/* 502 */ "Bad Gateway",
83+
/* 503 */ "Service Unavailable",
84+
/* 504 */ "Gateway Timeout",
85+
/* 505 */ "Http Version Not Supported",
86+
/* 506 */ string.Empty,
87+
/* 507 */ "Insufficient Storage"
88+
}
89+
};
90+
}

src/ServiceStack.Text/HttpUtils.HttpClient.cs

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,6 +1007,9 @@ public static async Task<HttpResponseMessage> PutFileToUrlAsync(this string url,
10071007
method: HttpMethods.Post, requestFilter: requestFilter, responseFilter: responseFilter, token: token).ConfigAwait();
10081008
}
10091009

1010+
public static void AddHeader(this HttpRequestMessage res, string name, string value) =>
1011+
res.WithHeader(name, value);
1012+
10101013
public static string? GetHeader(this HttpRequestMessage res, string name) =>
10111014
res.Headers.TryGetValues(name, out var values) ? values.FirstOrDefault() : null;
10121015

@@ -1020,7 +1023,13 @@ public static HttpRequestMessage WithHeader(this HttpRequestMessage httpReq, str
10201023
httpReq.Headers.Authorization =
10211024
new AuthenticationHeaderValue(value.LeftPart(' '), value.RightPart(' '));
10221025
}
1023-
else if (name.Equals(HttpHeaders.UserAgent))
1026+
else if (name.Equals(HttpHeaders.ContentType, StringComparison.OrdinalIgnoreCase))
1027+
{
1028+
if (httpReq.Content == null)
1029+
throw new NotSupportedException("Can't set ContentType before Content is populated");
1030+
httpReq.Content.Headers.ContentType = new MediaTypeHeaderValue(value);
1031+
}
1032+
else if (name.Equals(HttpHeaders.UserAgent, StringComparison.OrdinalIgnoreCase))
10241033
{
10251034
if (value.IndexOf('/') >= 0)
10261035
{
@@ -1030,7 +1039,7 @@ public static HttpRequestMessage WithHeader(this HttpRequestMessage httpReq, str
10301039
}
10311040
else
10321041
{
1033-
// Avoid format excetions
1042+
// Avoid format exceptions
10341043
var commentFmt = value[0] == '(' && value[^1] == ')' ? value : $"({value})";
10351044
httpReq.Headers.UserAgent.Add(new ProductInfoHeaderValue(commentFmt));
10361045
}
@@ -1042,22 +1051,24 @@ public static HttpRequestMessage WithHeader(this HttpRequestMessage httpReq, str
10421051
return httpReq;
10431052
}
10441053

1045-
public static HttpRequestMessage With(this HttpRequestMessage httpReq,
1046-
string? accept = null,
1047-
string? userAgent = null,
1048-
KeyValuePair<string,string>? authorization = null,
1049-
Dictionary<string, string>? headers = null)
1054+
public static HttpRequestMessage With(this HttpRequestMessage httpReq, Action<HttpRequestConfig> configure)
10501055
{
1051-
headers ??= new Dictionary<string, string>();
1052-
1053-
if (accept != null)
1054-
headers[HttpHeaders.Accept] = accept;
1055-
if (userAgent != null)
1056-
headers[HttpHeaders.UserAgent] = userAgent;
1057-
if (authorization != null)
1056+
var config = new HttpRequestConfig();
1057+
configure(config);
1058+
1059+
config.Headers ??= new Dictionary<string, string>();
1060+
var headers = config.Headers;
1061+
1062+
if (config.Accept != null)
1063+
headers[HttpHeaders.Accept] = config.Accept;
1064+
if (config.UserAgent != null)
1065+
headers[HttpHeaders.UserAgent] = config.UserAgent;
1066+
if (config.ContentType != null)
1067+
headers[HttpHeaders.ContentType] = config.ContentType;
1068+
if (config.Authorization != null)
10581069
httpReq.Headers.Authorization =
1059-
new AuthenticationHeaderValue(authorization.Value.Key, authorization.Value.Value);
1060-
1070+
new AuthenticationHeaderValue(config.Authorization.Value.Key, config.Authorization.Value.Value);
1071+
10611072
foreach (var entry in headers)
10621073
{
10631074
httpReq.WithHeader(entry.Key, entry.Value);
@@ -1071,7 +1082,10 @@ public static void DownloadFileTo(this string downloadUrl, string fileName,
10711082
{
10721083
var client = Create();
10731084
var httpReq = new HttpRequestMessage(HttpMethod.Get, downloadUrl)
1074-
.With(accept:"*/*", headers:headers);
1085+
.With(c => {
1086+
c.Accept = "*/*";
1087+
c.Headers = headers;
1088+
});
10751089

10761090
var httpRes = client.Send(httpReq);
10771091
httpRes.EnsureSuccessStatusCode();

src/ServiceStack.Text/HttpUtils.WebRequest.cs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,11 +1073,6 @@ private static byte[] GetHeaderBytes(string fileName, string mimeType, string fi
10731073
return headerBytes;
10741074
}
10751075

1076-
public static string GetHeader(this HttpWebRequest res, string name) =>
1077-
res.Headers.Get(name);
1078-
public static string GetHeader(this HttpWebResponse res, string name) =>
1079-
res.Headers.Get(name);
1080-
10811076
public static void DownloadFileTo(this string downloadUrl, string fileName,
10821077
Dictionary<string,string> headers = null)
10831078
{
@@ -1091,27 +1086,41 @@ public static void DownloadFileTo(this string downloadUrl, string fileName,
10911086
}
10921087
webClient.DownloadFile(downloadUrl, fileName);
10931088
}
1094-
1095-
public static HttpWebRequest With(this HttpWebRequest httpReq,
1096-
string accept = null,
1097-
string userAgent = null,
1098-
KeyValuePair<string,string>? authorization = null,
1099-
Dictionary<string,string> headers = null)
1089+
1090+
public static void AddHeader(this HttpWebRequest res, string name, string value) =>
1091+
res.Headers[name] = value;
1092+
public static string GetHeader(this HttpWebRequest res, string name) =>
1093+
res.Headers.Get(name);
1094+
public static string GetHeader(this HttpWebResponse res, string name) =>
1095+
res.Headers.Get(name);
1096+
1097+
public static HttpWebRequest WithHeader(this HttpWebRequest httpReq, string name, string value)
11001098
{
1101-
if (accept != null)
1102-
httpReq.Headers.Add(HttpHeaders.Accept, accept);
1099+
httpReq.Headers[name] = value;
1100+
return httpReq;
1101+
}
1102+
1103+
public static HttpWebRequest With(this HttpWebRequest httpReq, Action<HttpRequestConfig> configure)
1104+
{
1105+
var config = new HttpRequestConfig();
1106+
configure(config);
1107+
1108+
if (config.Accept != null)
1109+
httpReq.Headers.Add(HttpHeaders.Accept, config.Accept);
11031110

1104-
if (userAgent != null)
1105-
httpReq.UserAgent = userAgent;
1111+
if (config.UserAgent != null)
1112+
httpReq.UserAgent = config.UserAgent;
11061113

1107-
if (authorization != null)
1108-
{
1109-
httpReq.Headers[HttpHeaders.Authorization] = authorization.Value.Key + " " + authorization.Value.Value;
1110-
}
1114+
if (config.ContentType != null)
1115+
httpReq.ContentType = config.ContentType;
11111116

1112-
if (headers != null)
1117+
if (config.Authorization != null)
1118+
httpReq.Headers[HttpHeaders.Authorization] =
1119+
config.Authorization.Value.Key + " " + config.Authorization.Value.Value;
1120+
1121+
if (config.Headers != null)
11131122
{
1114-
foreach (var entry in headers)
1123+
foreach (var entry in config.Headers)
11151124
{
11161125
httpReq.Headers[entry.Key] = entry.Value;
11171126
}

tests/ServiceStack.Text.Tests/UseCases/GithubV3ApiTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public T GetJson<T>(string route, params object[] routeArgs)
3838
{
3939
var url = GithubApiBaseUrl.AppendUrlPathsRaw(route.Fmt(routeArgs));
4040
return url
41-
.GetJsonFromUrl(requestFilter:x => x.With(userAgent:$"ServiceStack/{Env.VersionString}"))
41+
.GetJsonFromUrl(requestFilter:x => x.With(c => c.UserAgent = $"ServiceStack/{Env.VersionString}"))
4242
.FromJson<T>();
4343
}
4444

0 commit comments

Comments
 (0)