Skip to content

Instantly share code, notes, and snippets.

@joelverhagen
Last active March 29, 2023 03:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joelverhagen/6e85230bd43f194c1e7f3a40368a21de to your computer and use it in GitHub Desktop.
Save joelverhagen/6e85230bd43f194c1e7f3a40368a21de to your computer and use it in GitHub Desktop.
using System.Diagnostics;
using System.Net;
using System.Text;
var sw = Stopwatch.StartNew();
string? previousRequest = null;
string? previousResponse = null;
while (true)
{
using var httpClient = new HttpClient();
using var request = new HttpRequestMessage(HttpMethod.Get, "https://api.nuget.org/v3/flatcontainer/microsoft.extensions.logging/5.0.0/microsoft.extensions.logging.5.0.0.nupkg");
request.Headers.TryAddWithoutValidation("x-ms-version", "2013-08-15");
request.Headers.TryAddWithoutValidation("If-Match", "0x8D8850AF6EC22DC");
request.Headers.TryAddWithoutValidation("Range", "bytes=107866-107887");
using var response = await httpClient.SendAsync(request);
Console.WriteLine($"[{sw.Elapsed}] {(int)response.StatusCode} {response.ReasonPhrase}");
if (response.StatusCode != HttpStatusCode.PartialContent)
{
Console.WriteLine();
Console.WriteLine("=== Previous session ===");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine(previousRequest);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine(previousResponse);
Console.WriteLine();
Console.WriteLine();
Console.WriteLine("=== Current ===");
Console.WriteLine();
Console.WriteLine();
Console.WriteLine(await GetRequestDebugStringAsync(request));
Console.WriteLine();
Console.WriteLine();
Console.WriteLine(await GetResponseDebugStringAsync(response));
Console.WriteLine();
Console.WriteLine();
return;
}
previousRequest = await GetRequestDebugStringAsync(request);
previousResponse = await GetResponseDebugStringAsync(response);
}
static async Task<string> GetRequestDebugStringAsync(HttpRequestMessage request)
{
var builder = new StringBuilder();
builder.AppendFormat("{0} {1} HTTP/{2}\r\n", request.Method, request.RequestUri.AbsoluteUri, request.Version);
await AppendHeadersAndBody(builder, request.Headers, request.Content);
return builder.ToString();
}
static async Task<string> GetResponseDebugStringAsync(HttpResponseMessage response)
{
var builder = new StringBuilder();
builder.AppendFormat("HTTP/{0} {1} {2}\r\n", response.Version, (int)response.StatusCode, response.ReasonPhrase);
await AppendHeadersAndBody(builder, response.Headers, response.Content);
return builder.ToString();
}
static async Task AppendHeadersAndBody(
StringBuilder builder,
IEnumerable<KeyValuePair<string, IEnumerable<string>>> headers,
HttpContent content)
{
if (content != null)
{
headers = headers.Concat(content.Headers);
}
// Write the headers.
foreach (var header in headers)
{
foreach (var value in header.Value)
{
builder.AppendFormat("{0}: {1}\r\n", header.Key, value);
}
}
builder.Append("\r\n");
// Write the request or response body.
if (content != null)
{
using (var stream = await content.ReadAsStreamAsync())
{
var buffer = new byte[1024 * 32 + 1];
var totalRead = 0;
int read;
do
{
read = await stream.ReadAsync(buffer, totalRead, buffer.Length - totalRead);
totalRead += read;
}
while (totalRead < buffer.Length && read > 0);
var hasMore = totalRead == buffer.Length;
var dataLength = Math.Min(totalRead, buffer.Length - 1);
try
{
using (var memoryStream = new MemoryStream(buffer, 0, dataLength))
using (var reader = new StreamReader(memoryStream))
{
// Write the response body as a string.
builder.Append(reader.ReadToEnd());
}
}
catch (Exception)
{
// Write the response body as base64 bytes.
builder.Append("<base64>\r\n");
builder.Append(Convert.ToBase64String(buffer, 0, dataLength));
}
if (hasMore)
{
builder.Append("\r\n<truncated>");
}
}
}
}
=== Previous session ===
GET https://api.nuget.org/v3/flatcontainer/microsoft.extensions.logging/5.0.0/microsoft.extensions.logging.5.0.0.nupkg HTTP/1.1
x-ms-version: 2013-08-15
If-Match: 0x8D8850AF6EC22DC
Range: bytes=107866-107887
HTTP/1.1 206 Partial Content
Accept-Ranges: bytes
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: x-ms-request-id,Server,x-ms-version,x-ms-meta-da7b2905_0f3c_4262_921c_b1593d1336f1_ESRP_RequestId,x-ms-meta-SHA512,Content-Type,Cache-Control,Last-Modified,ETag,x-ms-lease-status,x-ms-lease-state,x-ms-blob-type,Accept-Ranges,Content-Length,Date,Transfer-Encoding
Cache-Control: max-age=86400
Date: Wed, 29 Mar 2023 03:46:49 GMT
ETag: "0x8D8850AF6EC22DC"
Server: Windows-Azure-Blob/1.0
Server: Microsoft-HTTPAPI/2.0
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-CDN-Rewrite: Root path in dist
X-Content-Type-Options: nosniff
x-ms-blob-type: BlockBlob
x-ms-lease-state: available
x-ms-lease-status: unlocked
x-ms-meta-da7b2905_0f3c_4262_921c_b1593d1336f1_ESRP_RequestId: 47b474a7-936e-41c5-a44d-cdee53336147
x-ms-meta-SHA512: GGUVP+sruHXiWkeVXFPzGVgmX8GbiQyq3B1UMJzHelDyyLjVsWPB6IXone4+mJQCMvR9rsnpsSxdRYjb5+WyRQ==
x-ms-request-id: 2c8cf38f-601e-0004-18f1-6130f0000000
x-ms-version: 2013-08-15
Content-Range: bytes 107866-107887/107888
Content-Type: application/octet-stream
Expires: Thu, 30 Mar 2023 03:46:50 GMT
Last-Modified: Mon, 09 Nov 2020 23:55:41 GMT
Content-Length: 22
PK♣♠►►?♦g?☺
=== Current ===
GET https://api.nuget.org/v3/flatcontainer/microsoft.extensions.logging/5.0.0/microsoft.extensions.logging.5.0.0.nupkg HTTP/1.1
x-ms-version: 2013-08-15
If-Match: 0x8D8850AF6EC22DC
Range: bytes=107866-107887
HTTP/1.1 400 Bad Request
Cache-Control: public, max-age=86400
Accept-Ranges: bytes
ETag: "0x8D8850AF6EC22DC"
X-Cache: TCP_REMOTE_HIT
x-ms-request-id: a88d25ee-b01e-0038-63eb-611937000000
x-ms-version: 2013-08-15
x-ms-meta-da7b2905_0f3c_4262_921c_b1593d1336f1_ESRP_RequestId: 47b474a7-936e-41c5-a44d-cdee53336147
x-ms-meta-SHA512: GGUVP+sruHXiWkeVXFPzGVgmX8GbiQyq3B1UMJzHelDyyLjVsWPB6IXone4+mJQCMvR9rsnpsSxdRYjb5+WyRQ==
x-ms-lease-status: unlocked
x-ms-lease-state: available
x-ms-blob-type: BlockBlob
Access-Control-Expose-Headers: x-ms-request-id,Server,x-ms-version,x-ms-meta-da7b2905_0f3c_4262_921c_b1593d1336f1_ESRP_RequestId,x-ms-meta-SHA512,Content-Type,Cache-Control,Last-Modified,ETag,Content-MD5,x-ms-lease-status,x-ms-lease-state,x-ms-blob-type,Accept-Ranges,Content-Length,Date,Transfer-Encoding
Access-Control-Allow-Origin: *
X-Azure-Ref-OriginShield: 0qrQjZAAAAAD3M/brsAjGRbzGs0mQqQ67RE0yQUExMDkxMjA3MDIxADgwZDFiZGUzLTJjYWQtNDJkZi1iYTQyLTRjYzUwMjA0ZTJmYg==
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Azure-Ref: 0qrQjZAAAAACVAzreOR40SLJdNlg7T9IQQ0hHRURHRTE1MDgAODBkMWJkZTMtMmNhZC00MmRmLWJhNDItNGNjNTAyMDRlMmZi
Date: Wed, 29 Mar 2023 03:46:50 GMT
Content-Length: 23
Content-Type: application/octet-stream
Content-MD5: rXQv22f9ySXp5PWQ6Xuhfw==
Last-Modified: Mon, 09 Nov 2020 23:55:41 GMT
ERROR 400: Bad Request.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment