-
Notifications
You must be signed in to change notification settings - Fork 1
2. Making an HTTP request
MemwLib comes with a simple static async function to make a request, which will return a ResponseEntity
, that represents the response part of an HTTP request.
To get started, we will invoke the HttpRequests.CreateRequest
method in our Main method of our program.
public static class Program
{
public static async Task Main()
{
ResponseEntity response = await HttpRequests.CreateRequest(new HttpRequestConfig{
Url = "https://example.com/api/data",
Method = RequestMethodType.Get, // can be any of the other methods.
Headers = (HeaderCollection)new HeaderCollection()
.Add("Header-Key", "Value"),
Body = new StringBody("Hello, I'm a body!")
});
}
}
This now returns us a structured response that has only what it needs to have.
The head is directly included into the ResponseEntity
properties, these being
-
HttpVersion
, which shows the HTTP version this request was made on. -
ResponseCode
, that's basically the HTTP response code that the server returned in the form ofResponseCodes
enumerable, itself containing the code reason. -
IsSuccessfulResponse
, that evaluates the following expression(int)ResponseCode < 400
.
The headers are just a MultipleParsingCollection<string, string>
since by standard there can be multiple headers with the same name, for example
Set-Cookie key1=value1
Set-Cookie key2=value2
Would map to response.Headers["Set-Cookie"]
returning an array of 2 elements ["Key1=value1", "Key2=value2"]
.
Since c# is statically typed, it always returns an array, no matter if there is only 1 header of the same type. Since MultipleParsingCollection
implements IEnumerable<TKey, TValue>
, Linq
is available, so you might just want to use the FirstOrDefault
method, to get the header or null
if it does not exist.
The body is a BodyConverter
instance, which contains the raw stream inside, you can use its ReadAs<TBody : IBody>
method to read its contents.
In the library, some IBody
implementations come built-in, but you can make your own ones, an example of implementation for strings would be
// this is a primary constructor, but a normal constructor should be used in `< net8.0`
public sealed class StringBody(string content) : IBody
{
// The ContentType header, will automatically be set on responses.
public string ContentType => "text/plain";
// Used when the ReadAs method is called.
public static IBody ParseImpl(MemoryStream content)
{
byte[] read = new byte[content.Length];
_ = content.Read(read, 0, read.Length);
return new StringBody(Encoding.ASCII.GetString(read));
}
// Used while building a ResponseEntity (setting a body to the response).
public byte[] ToArray()
=> Encoding.ASCII.GetBytes(content);
// ToString override, since the body is a string (not required).
public override string ToString()
=> content;
}
Note that this implementation is already built in MemwLib, the above code is merely a demonstration.
Now that we have a body, we can read the response, in this case in a plain string.
string content = response.Body.ReadAs<StringBody>().ToString();
The full implementation built up from this page is the following.
public static class Program
{
public static async Task Main()
{
ResponseEntity response = await HttpRequests.CreateRequest(new HttpRequestConfig{
Url = "https://example.com/api/data",
Method = RequestMethodType.Get,
Headers = (HeaderCollection)new HeaderCollection()
.Add("Header-Key", "Value"),
Body = new StringBody("Hello, I'm a body!")
});
Console.WriteLine(
$"""
The request returned {response.ResponseCode},
meaning that the response is{(response.IsSuccessfulResponse ? "successful" : "not successful")}."
"""
);
Console.WriteLine("\nThe following headers may be found in the response:");
foreach ((string key, string[] values) in response.Headers)
{
foreach (string value in values)
Console.WriteLine($"{key}: {value}");
}
Console.WriteLine($"\nThe response body is:\n\n{response.Body.ReadAs<StringBody>()}");
}
}