sdk-csharp/test/CloudNative.CloudEvents.Uni.../Http/HttpWebExtensionsTest.cs

183 lines
8.3 KiB
C#

// Copyright 2021 Cloud Native Foundation.
// Licensed under the Apache 2.0 license.
// See LICENSE file in the project root for full license information.
using CloudNative.CloudEvents.Core;
using CloudNative.CloudEvents.NewtonsoftJson;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Mime;
using System.Threading.Tasks;
using Xunit;
using static CloudNative.CloudEvents.UnitTests.TestHelpers;
namespace CloudNative.CloudEvents.Http.UnitTests
{
public class HttpWebExtensionsTest : HttpTestBase
{
[Fact]
public async Task HttpBinaryWebRequestSendTest()
{
var cloudEvent = new CloudEvent
{
Type = "com.github.pull.create",
Source = new Uri("https://github.com/cloudevents/spec/pull/123"),
Id = "A234-1234-1234",
Time = SampleTimestamp,
DataContentType = MediaTypeNames.Text.Xml,
Data = "<much wow=\"xml\"/>",
["comexampleextension1"] = "value",
["utf8examplevalue"] = "æøå"
};
string ctx = Guid.NewGuid().ToString();
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(ListenerAddress + "ep");
httpWebRequest.Method = "POST";
await cloudEvent.CopyToHttpWebRequestAsync(httpWebRequest, ContentMode.Binary, new JsonEventFormatter());
httpWebRequest.Headers.Add(TestContextHeader, ctx);
PendingRequests.TryAdd(ctx, context =>
{
var receivedCloudEvent = context.Request.ToCloudEvent(new JsonEventFormatter());
Assert.Equal(CloudEventsSpecVersion.V1_0, receivedCloudEvent.SpecVersion);
Assert.Equal("com.github.pull.create", receivedCloudEvent.Type);
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), receivedCloudEvent.Source);
Assert.Equal("A234-1234-1234", receivedCloudEvent.Id);
AssertTimestampsEqual(SampleTimestamp, cloudEvent.Time.Value);
Assert.Equal(MediaTypeNames.Text.Xml, receivedCloudEvent.DataContentType);
Assert.Equal("<much wow=\"xml\"/>", receivedCloudEvent.Data);
// The non-ASCII attribute value should have been URL-encoded using UTF-8 for the header.
Assert.Equal("%C3%A6%C3%B8%C3%A5", context.Request.Headers["ce-utf8examplevalue"]);
Assert.Equal("value", receivedCloudEvent["comexampleextension1"]);
Assert.Equal("æøå", receivedCloudEvent["utf8examplevalue"]);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return Task.CompletedTask;
});
var result = (HttpWebResponse)await httpWebRequest.GetResponseAsync();
var content = new StreamReader(result.GetResponseStream()).ReadToEnd();
Assert.True(result.StatusCode == HttpStatusCode.NoContent, content);
}
[Fact]
public async Task HttpStructuredWebRequestSendTest()
{
var cloudEvent = new CloudEvent
{
Type = "com.github.pull.create",
Source = new Uri("https://github.com/cloudevents/spec/pull/123"),
Id = "A234-1234-1234",
Time = SampleTimestamp,
DataContentType = MediaTypeNames.Text.Xml,
Data = "<much wow=\"xml\"/>",
["comexampleextension1"] = "value",
["utf8examplevalue"] = "æøå"
};
string ctx = Guid.NewGuid().ToString();
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(ListenerAddress + "ep");
httpWebRequest.Method = "POST";
await cloudEvent.CopyToHttpWebRequestAsync(httpWebRequest, ContentMode.Structured, new JsonEventFormatter());
httpWebRequest.Headers.Add(TestContextHeader, ctx);
PendingRequests.TryAdd(ctx, context =>
{
var receivedCloudEvent = context.Request.ToCloudEvent(new JsonEventFormatter());
Assert.Equal(CloudEventsSpecVersion.V1_0, receivedCloudEvent.SpecVersion);
Assert.Equal("com.github.pull.create", receivedCloudEvent.Type);
Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), receivedCloudEvent.Source);
Assert.Equal("A234-1234-1234", receivedCloudEvent.Id);
AssertTimestampsEqual(SampleTimestamp, cloudEvent.Time.Value);
Assert.Equal(MediaTypeNames.Text.Xml, receivedCloudEvent.DataContentType);
Assert.Equal("<much wow=\"xml\"/>", receivedCloudEvent.Data);
Assert.Equal("value", receivedCloudEvent["comexampleextension1"]);
Assert.Equal("æøå", receivedCloudEvent["utf8examplevalue"]);
context.Response.StatusCode = (int)HttpStatusCode.NoContent;
return Task.CompletedTask;
});
var result = (HttpWebResponse) await httpWebRequest.GetResponseAsync();
var content = new StreamReader(result.GetResponseStream()).ReadToEnd();
Assert.True(result.StatusCode == HttpStatusCode.NoContent, content);
}
[Fact]
public async Task CopyToHttpWebRequestAsync_BinaryDataButNoDataContentType()
{
var cloudEvent = new CloudEvent
{
Data = new byte[10],
}.PopulateRequiredAttributes();
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(ListenerAddress + "ep");
httpWebRequest.Method = "POST";
await Assert.ThrowsAsync<ArgumentException>(
async () => await cloudEvent.CopyToHttpWebRequestAsync(httpWebRequest, ContentMode.Binary, new JsonEventFormatter()));
}
[Fact]
public async Task CopyToHttpWebRequestAsync_NonBinaryDataButNoDataContentType_ContentTypeIsInferred()
{
var cloudEvent = new CloudEvent
{
Data = "plain text",
}.PopulateRequiredAttributes();
HttpWebRequest httpWebRequest = WebRequest.CreateHttp(ListenerAddress + "ep");
httpWebRequest.Method = "POST";
await cloudEvent.CopyToHttpWebRequestAsync(httpWebRequest, ContentMode.Binary, new JsonEventFormatter());
Assert.Equal("application/json", httpWebRequest.ContentType);
}
[Fact]
public async Task CopyToHttpWebRequestAsync_Batch()
{
var batch = CreateSampleBatch();
HttpWebRequest request = WebRequest.CreateHttp(ListenerAddress + "ep");
request.Method = "POST";
await batch.CopyToHttpWebRequestAsync(request, new JsonEventFormatter());
var (bytes, contentType) = await SendRequestAsync(request, async context =>
{
var bytes = await BinaryDataUtilities.ToReadOnlyMemoryAsync(context.Request.InputStream);
var contentType = context.Request.Headers["Content-Type"];
return (bytes, contentType);
});
Assert.Equal(MimeUtilities.BatchMediaType + "+json; charset=utf-8", contentType);
var parsedBatch = new JsonEventFormatter().DecodeBatchModeMessage(bytes, MimeUtilities.CreateContentTypeOrNull(contentType), extensionAttributes: null);
AssertBatchesEqual(batch, parsedBatch);
}
/// <summary>
/// Executes the given request, expecting the given handler to be called.
/// An empty response is proided on success.
/// </summary>
private async Task<T> SendRequestAsync<T>(HttpWebRequest request, Func<HttpListenerContext, Task<T>> handler)
{
var guid = Guid.NewGuid().ToString();
request.Headers.Add(TestContextHeader, guid);
T result = default;
bool executed = false;
PendingRequests[guid] = async context =>
{
executed = true;
result = await handler(context);
context.Response.StatusCode = (int) HttpStatusCode.NoContent;
};
using var response = (HttpWebResponse) await request.GetResponseAsync();
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
Assert.True(executed);
return result!;
}
}
}