I've a C# WinForms application that relies heavily on sending HttpWebRequest
s. I've build an HttpWebRequestBuilder
, and WebRequestBodyBuilder
.
public class HttpWebRequestBuilder
{
private HttpWebRequest _httpWebRequest; // The object that will be built.
public HttpWebRequestBuilder(string url) : this(url, Constants.FirefoxUserAgent) // Use firefox user-agent by default (Constants is a static class that has FirefoxUserAgent constant).
{
}
public HttpWebRequestBuilder(string url, string userAgent)
{
_httpWebRequest = WebRequest.CreateHttp(url); // Create an HttpWebRequest.
_httpWebRequest.UserAgent = userAgent; // Set the user-agent.
_httpWebRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; // Set automatic decompression. I want this value for all requests.
}
public HttpWebRequestBuilder WithMethod(string method) // Set the method, "GET", "POST", etc. The default is "GET".
{
_httpWebRequest.Method = method;
return this;
}
public HttpWebRequestBuilder Accepts(string accept) // Set the "Accept" header.
{
_httpWebRequest.Accept = accept;
return this;
}
public HttpWebRequestBuilder WithContentType(string contentType) // Set the "Content-Type" header.
{
_httpWebRequest.ContentType = contentType;
return this;
}
public HttpWebRequestBuilder WithCookies(CookieContainer container) // Set a cookie container.
{
_httpWebRequest.CookieContainer = container;
return this;
}
public HttpWebRequestBuilder AllowAutoRedirect(bool allow) // Set AllowAutoRedirect
{
_httpWebRequest.AllowAutoRedirect = allow;
return this;
}
public HttpWebRequestBuilder WithReferer(string referer) // Set referer.
{
_httpWebRequest.Referer = referer;
return this;
}
public HttpWebRequestBuilder WithCustomHeader(string name, string value) // Add a custom header.
{
_httpWebRequest.Headers.Add(name, value);
return this;
}
public async Task<HttpWebRequestBuilder> PostAsync(WebRequestBodyBuilder bodyBuilder) // Takes an object of WebRequestBodyBuilder (which just makes a string like "param1=value1¶m2=value2&...."
{
byte[] buffer = Encoding.UTF8.GetBytes(bodyBuilder.ToString());
using (var reqStrm = await _httpWebRequest.GetRequestStreamAsync()) // Write the body in the request stream.
{
reqStrm.Write(buffer, 0, buffer.Length);
}
return this;
}
public HttpWebRequest Build() // Returns the actual HttpWebRequest
{
return _httpWebRequest;
}
}
public class WebRequestBodyBuilder
{
private StringBuilder _stringBuilder = new StringBuilder();
public WebRequestBodyBuilder SetKeyValuePair(string key, string value)
{
if (string.IsNullOrWhiteSpace(key))
throw new ArgumentException($"Argument {nameof(key)} can't be null or whitespace."); // key can't be null, but value CAN!
if (!string.IsNullOrWhiteSpace(_stringBuilder.ToString()))
_stringBuilder.Append("&"); // First call shouldn't add "&" in the first.
_stringBuilder.Append($"{WebUtility.UrlEncode(key)}={WebUtility.UrlEncode(value)}");
return this;
}
public override string ToString()
{
return _stringBuilder.ToString(); // ToString is used in the HttpWebRequestBuilder, in the PostAsync method.
}
}
An example usage of these is like the following:
var bodyBuilder = new WebRequestBodyBuilder()
.SetKeyValuePair("username", Account.Username)
.SetKeyValuePair("password", Account.Password)
.SetKeyValuePair("auth_token", _token);
HttpWebRequest req = (await (new HttpWebRequestBuilder() // The await is for PostAsync.
.WithMethod("POST")
.WithReferer("https://website.com/login")
.WithCookies(_cookies)
.Accepts("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
.WithContentType("application/x-www-form-urlencoded")
.AllowAutoRedirect(false).PostAsync(bodyBuilder))).Build();
// Do something with req, like await req.GetResponseAsync()
I'm just starting learning design patterns, so I want to make sure that I'm not misusing them.
Aucun commentaire:
Enregistrer un commentaire