├── .github
└── workflows
│ └── dotnet.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Directory.Build.props
├── LICENSE
├── README.md
├── appveyor.yml
├── src
├── Vlingo.Xoom.Http.Tests
│ ├── BodyTest.cs
│ ├── ChunkedBodyTest.cs
│ ├── Content
│ │ ├── css
│ │ │ └── styles.css
│ │ ├── index.html
│ │ ├── js
│ │ │ └── vuetify.js
│ │ └── views
│ │ │ ├── About.vue
│ │ │ └── test 2
│ │ │ └── index.html
│ ├── ContentEncodingMethodTest.cs
│ ├── ContentEncodingTest.cs
│ ├── ContentTypeTest.cs
│ ├── Converter.cs
│ ├── ExtendedCharactersFixture.cs
│ ├── FiltersTest.cs
│ ├── Media
│ │ ├── AcceptMediaTypeTest.cs
│ │ ├── ContentMediaTypeTest.cs
│ │ ├── MediaTypeParserTest.cs
│ │ └── ResponseContentMediaTypeSelectorTest.cs
│ ├── MethodExtensionsTest.cs
│ ├── QueryParametersParserTest.cs
│ ├── RequestHeaderTest.cs
│ ├── RequestParserTest.cs
│ ├── RequestTest.cs
│ ├── Resource
│ │ ├── ActionTest.cs
│ │ ├── ClientTest.cs
│ │ ├── ConfigurationResourceTest.cs
│ │ ├── ConfigurationTest.cs
│ │ ├── DefaultTextPlainMapperTest.cs
│ │ ├── DynamicResourceDispatcherTest.cs
│ │ ├── DynamicResourceHandlerTest.cs
│ │ ├── FailResource.cs
│ │ ├── Feed
│ │ │ ├── EventsFeedProducerActor.cs
│ │ │ └── FeedResourceTest.cs
│ │ ├── FluentTestResource.cs
│ │ ├── MediaTypeMapperTest.cs
│ │ ├── MockCompletesEventuallyResponse.cs
│ │ ├── ParameterResolverTest.cs
│ │ ├── RequestHandler0Test.cs
│ │ ├── RequestHandler1Test.cs
│ │ ├── RequestHandler2Test.cs
│ │ ├── RequestHandler3Test.cs
│ │ ├── RequestHandler4Test.cs
│ │ ├── RequestHandler5Test.cs
│ │ ├── RequestHandler6Test.cs
│ │ ├── RequestHandlerTest.cs
│ │ ├── RequestHandlerTestBase.cs
│ │ ├── ResourceBuilderTest.cs
│ │ ├── ResourceDispatcherGeneratorTest.cs
│ │ ├── ResourceFailureTest.cs
│ │ ├── ResourceTestFixtures.cs
│ │ ├── ResourcesTest.cs
│ │ ├── SecureClientTest.cs
│ │ ├── ServerBootstrap.cs
│ │ ├── ServerCORSTest.cs
│ │ ├── ServerTest.cs
│ │ ├── SinglePageApplicationResourceTest.cs
│ │ ├── Sse
│ │ │ ├── MessageEventTest.cs
│ │ │ ├── MockRequestResponseContext.cs
│ │ │ ├── MockResponseSenderChannel.cs
│ │ │ ├── MockSseStreamResource.cs
│ │ │ ├── SseClientTest.cs
│ │ │ ├── SseEventTest.cs
│ │ │ ├── SseFeedTest.cs
│ │ │ ├── SseStreamResourceTest.cs
│ │ │ └── SseSubscriberTest.cs
│ │ ├── StaticFilesResourceTest.cs
│ │ ├── TestDispatcher.cs
│ │ ├── TestMapper.cs
│ │ ├── TestResponseChannelConsumer.cs
│ │ └── TestResponseConsumer.cs
│ ├── ResponseParserTest.cs
│ ├── ResponseTest.cs
│ ├── Sample
│ │ └── User
│ │ │ ├── AllSseFeedActor.cs
│ │ │ ├── ContactData.cs
│ │ │ ├── Model
│ │ │ ├── Contact.cs
│ │ │ ├── IProfile.cs
│ │ │ ├── IUser.cs
│ │ │ ├── Name.cs
│ │ │ ├── ProfileActor.cs
│ │ │ ├── ProfileRepository.cs
│ │ │ ├── ProfileState.cs
│ │ │ ├── ProfileStateFactory.cs
│ │ │ ├── UserActor.cs
│ │ │ ├── UserRepository.cs
│ │ │ ├── UserState.cs
│ │ │ ├── UserStateFactory.cs
│ │ │ └── User__Proxy.cs
│ │ │ ├── NameData.cs
│ │ │ ├── ProfileData.cs
│ │ │ ├── ProfileDataMapper.cs
│ │ │ ├── ProfileResource.cs
│ │ │ ├── ProfileResourceFluent.cs
│ │ │ ├── Serialization
│ │ │ └── UserDataConverter.cs
│ │ │ ├── UserData.cs
│ │ │ ├── UserDataMapper.cs
│ │ │ ├── UserResource.cs
│ │ │ └── UserResourceFluent.cs
│ ├── ToSpecParserTest.cs
│ ├── VersionTest.cs
│ ├── Vlingo.Xoom.Http.Tests.csproj
│ ├── vlingo-actors.json
│ └── vlingo-http.json
├── Vlingo.Xoom.Http.sln
├── Vlingo.Xoom.Http.sln.licenseheader
└── Vlingo.Xoom.Http
│ ├── BinaryBody.cs
│ ├── Body.cs
│ ├── CORSResponseFilter.cs
│ ├── ChunkedBody.cs
│ ├── ContentEncoding.cs
│ ├── ContentEncodingMethod.cs
│ ├── ContentPacket.cs
│ ├── ContentType.cs
│ ├── Context.cs
│ ├── Filter.cs
│ ├── Filters.cs
│ ├── Header.cs
│ ├── Headers.cs
│ ├── Media
│ ├── ContentMediaType.cs
│ ├── MediaTypeDescriptor.cs
│ ├── MediaTypeParser.cs
│ └── ResponseMediaTypeSelector.cs
│ ├── Method.cs
│ ├── PlainBody.cs
│ ├── QueryParameters.cs
│ ├── Request.cs
│ ├── RequestData.cs
│ ├── RequestFilter.cs
│ ├── RequestHeader.cs
│ ├── RequestParser.cs
│ ├── Resource
│ ├── AbstractDispatcherPool.cs
│ ├── Action.cs
│ ├── Actions.cs
│ ├── AgentDispatcherPool.cs
│ ├── Client.cs
│ ├── ClientConsumerCommons.cs
│ ├── ClientConsumerWorkerActor.cs
│ ├── ClientConsumer__Proxy.cs
│ ├── ClientCorrelatingRequesterConsumerActor.cs
│ ├── Configuration.cs
│ ├── ConfigurationResource.cs
│ ├── Content.cs
│ ├── DefaultErrorHandler.cs
│ ├── DefaultJsonMapper.cs
│ ├── DefaultMediaTypeMapper.cs
│ ├── DefaultTextPlainMapper.cs
│ ├── DispatcherActor.cs
│ ├── Dispatcher__Proxy.cs
│ ├── DynamicResource.cs
│ ├── DynamicResourceHandler.cs
│ ├── EmbeddedResourceLoader.cs
│ ├── Feed
│ │ ├── FeedProducer__Proxy.cs
│ │ ├── FeedProductRequest.cs
│ │ ├── FeedResource.cs
│ │ ├── FeedResourceDispatcher.cs
│ │ └── IFeedProducer.cs
│ ├── HandlerMissingException.cs
│ ├── HttpProperties.cs
│ ├── IClientConsumer.cs
│ ├── IConfigurationResource.cs
│ ├── IDispatcher.cs
│ ├── IDispatcherPool.cs
│ ├── IErrorHandler.cs
│ ├── IMapper.cs
│ ├── IRequestSender.cs
│ ├── IResource.cs
│ ├── IResourceRequestHandler.cs
│ ├── IResponseConsumer.cs
│ ├── IServer.cs
│ ├── LoadBalancingClientRequestConsumerActor.cs
│ ├── Loader.cs
│ ├── MediaTypeMapper.cs
│ ├── MediaTypeNotSupportedException.cs
│ ├── ObjectResponse.cs
│ ├── ParameterResolver.cs
│ ├── RequestExecutor.cs
│ ├── RequestHandler.cs
│ ├── RequestHandler0.cs
│ ├── RequestHandler1.cs
│ ├── RequestHandler2.cs
│ ├── RequestHandler3.cs
│ ├── RequestHandler4.cs
│ ├── RequestHandler5.cs
│ ├── RequestHandler6.cs
│ ├── RequestHandler7.cs
│ ├── RequestHandler8.cs
│ ├── RequestObjectExecutor.cs
│ ├── RequestSenderProbeActor.cs
│ ├── RequestSender__Proxy.cs
│ ├── Resource.cs
│ ├── ResourceBuilder.cs
│ ├── ResourceDispatcherGenerator.cs
│ ├── ResourceErrorProcessor.cs
│ ├── ResourceHandler.cs
│ ├── ResourceRequestHandlerActor.cs
│ ├── ResourceRequestHandler__Proxy.cs
│ ├── Resources.cs
│ ├── RoundRobinClientRequestConsumerActor.cs
│ ├── ServerActor.cs
│ ├── Server__Proxy.cs
│ ├── SinglePageApplicationConfiguration.cs
│ ├── SinglePageApplicationResource.cs
│ ├── Sse
│ │ ├── ISseFeed.cs
│ │ ├── ISsePublisher.cs
│ │ ├── MessageEvent.cs
│ │ ├── SseClient.cs
│ │ ├── SseEvent.cs
│ │ ├── SseFeed__Proxy.cs
│ │ ├── SsePublisher__Proxy.cs
│ │ ├── SseStreamResource.cs
│ │ ├── SseStreamResourceDispatcher.cs
│ │ └── SseSubscriber.cs
│ ├── StaticFilesResource.cs
│ ├── StaticFilesResourceDispatcher.cs
│ └── TypeLoader.cs
│ ├── Response.cs
│ ├── ResponseFilter.cs
│ ├── ResponseHeader.cs
│ ├── ResponseParser.cs
│ ├── UrlFactory.cs
│ ├── Version.cs
│ └── Vlingo.Xoom.Http.csproj
└── vlingo-64x64.png
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ${{ matrix.os }}
13 | strategy:
14 | matrix:
15 | os: [ ubuntu-latest, windows-latest, macOS-latest ]
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Setup .NET 6.0.x
20 | id: setup-dotnet6
21 | uses: actions/setup-dotnet@v1
22 | with:
23 | dotnet-version: 6.0.x
24 | - name: Restore dependencies
25 | id: restore-deps
26 | run: dotnet restore ./src/Vlingo.Xoom.Http.sln
27 | - name: Build
28 | id: build
29 | run: dotnet build ./src/Vlingo.Xoom.Http.sln --no-restore
30 | - name: Test
31 | id: test
32 | run: dotnet test ./src/Vlingo.Xoom.Http.Tests/Vlingo.Xoom.Http.Tests.csproj --no-build --verbosity normal
33 | - name: slack - GitHub Actions Slack integration
34 | uses: act10ns/slack@v1.2.2
35 | env:
36 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
37 | with:
38 | status: ${{ job.status }}
39 | steps: ${{ toJson(steps) }}
40 | if: always()
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## How to contribute to the xoom-net-http
2 |
3 | #### **Did you find a bug?**
4 |
5 | * Make sure the bug was not already reported here: [Issues](https://github.com/vlingo-net/xoom-net-http/issues).
6 |
7 | * If nonexisting, open a new issue for the problem: [Open New Issue](https://github.com/vlingo-net/xoom-net-http/issues/new). Always provide a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring.
8 |
9 | #### **Patches and bug fixes**
10 |
11 | * Open a new GitHub pull request with the patch.
12 |
13 | * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable.
14 |
15 | * It would be really nice if your followed the basic code format used prevelently.
16 |
17 | #### **Please don't reformat existing code**
18 |
19 | * Just because you don't like a given code style doesn't mean you have the authority to change it. Cosmeic changes add zero to little value.
20 |
21 | #### **New features and enhancements**
22 |
23 | * Email your post your suggestion and provide an example implementation.
24 |
25 | * After agreement open a PR or issue.
26 |
27 | #### **Direct questions to...**
28 |
29 | * Vaughn Vernon: vaughn at kalele dot io
30 |
31 | #### **Contribute to documentation**
32 |
33 | * Vaughn Vernon: vaughn at kalele dot io
34 |
35 | Thanks for your kind assistance! :smile:
36 |
37 | Vaughn Vernon and the Vlingo .NET team
38 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 1.10.1
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # xoom-net-http
2 |
3 | [](https://ci.appveyor.com/project/VlingoNetOwner/xoom-net-http/branch/master)
4 | 
5 | [](https://www.nuget.org/packages/Vlingo.Xoom.Http)
6 | [](https://gitter.im/vlingo-platform-net/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
7 |
8 | ### Usage
9 |
10 | Reactive, scalable, and resilient HTTP servers and RESTful services running on vlingo-net/cluster and vlingo-net/actors.
11 |
12 | 1. The essential features are completed
13 | * Fully actor-based asynchronous requests and responses.
14 | * The request handling is resource based.
15 | * Requests that require message body content are auto-mapped to simple Java objects.
16 |
17 | 2. To run the Server:
18 | * [Use Server#StartWith() to start the Server actor](https://github.com/vlingo/xoom-net-http/blob/master/src/Vlingo.Xoom.Http/Resource/Server.cs)
19 | * The light-weight Server is meant to be run inside vlingo/cluster nodes the require RESTful HTTP support.
20 |
21 | 3. See the following for usage examples:
22 | * [vlingo/http properties file](https://github.com/vlingo/xoom-net-http/blob/master/src/Vlingo.Xoom.Http.Tests/Resources/vlingo-http.properties)
23 | * [The user resource sample](#) (Sample link to be provided)
24 | * [The user profile resource sample](#) (Sample link to be provided)
25 |
26 |
27 | License (See LICENSE file for full license)
28 | -------------------------------------------
29 | Copyright © 2012-2021 VLINGO LABS. All rights reserved.
30 |
31 | This Source Code Form is subject to the terms of the
32 | Mozilla Public License, v. 2.0. If a copy of the MPL
33 | was not distributed with this file, You can obtain
34 | one at https://mozilla.org/MPL/2.0/.
35 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 1.10.1.{build}
2 | image:
3 | - Visual Studio 2022
4 | - Ubuntu
5 | - macOS
6 | - macOS-Monterey
7 | - macOS-Bigsur
8 | configuration: Release
9 | skip_commits:
10 | message: /.*\[ci\-skip\].*/
11 | before_build:
12 | - dotnet restore src/Vlingo.Xoom.Http.sln
13 | build:
14 | project: src/Vlingo.Xoom.Http.sln
15 | verbosity: minimal
16 | publish_nuget: true
17 | for:
18 | -
19 | matrix:
20 | only:
21 | - image: Visual Studio 2019
22 | before_test:
23 | - netsh advfirewall set currentprofile state off
24 | after_test:
25 | - netsh advfirewall set currentprofile state on
26 | test_script:
27 | - dotnet test src/Vlingo.Xoom.Http.Tests
28 | deploy:
29 | - provider: NuGet
30 | api_key:
31 | secure: 4VJZEFZNaDrk3FJmRSmBW+wQugDoPi6DtVlsLZ+26IOo+wb0u9JlnTOTQF+NXs2s
32 | skip_symbols: true
33 | artifact: /.*\.nupkg/
34 | on:
35 | branch: master
36 | notifications:
37 | - provider: Webhook
38 | url: https://webhooks.gitter.im/e/37621a855e91c31ab1da
39 | method: POST
40 | on_build_success: true
41 | on_build_failure: true
42 | on_build_status_changed: true
43 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/ChunkedBodyTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Xunit;
9 |
10 | namespace Vlingo.Xoom.Http.Tests;
11 |
12 | public class ChunkedBodyTest
13 | {
14 | private const string Chunk1 = "ABCDEFGHIJKLMNOPQRSTUVWYYZ0123";
15 | private const string Chunk2 = "abcdefghijklmnopqrstuvwxyz012345";
16 |
17 | [Fact]
18 | public void TestThatChunkedBodyChunks()
19 | {
20 | var body =
21 | Body
22 | .BeginChunked()
23 | .AppendChunk(Chunk1)
24 | .AppendChunk(Chunk2)
25 | .End();
26 |
27 | Assert.Contains(AsChunk(Chunk1), body.Content);
28 | Assert.Contains(AsChunk(Chunk2), body.Content);
29 | }
30 |
31 | private string AsChunk(string content) => $"{content.Length:x8}\r\n{content}\r\n";
32 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Content/css/styles.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | text-align: center;
3 | color: blue;
4 | }
5 |
6 | h2 {
7 | text-align: center;
8 | color: blue;
9 | }
10 |
11 | p {
12 | text-align: center;
13 | color: blue;
14 | }
15 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Content/index.html:
--------------------------------------------------------------------------------
1 |
2 |
Test
3 | Test1
4 | Test paragraph.
5 |
6 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Content/js/vuetify.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuetify from 'vuetify'
3 | import 'vuetify/dist/vuetify.min.css'
4 |
5 | Vue.use(Vuetify, {
6 | theme: {
7 | primary: "#00796B",
8 | secondary: "#B2DFDB",
9 | accent: "#009688",
10 | error: "#f44336",
11 | warning: "#ffeb3b",
12 | info: "#2196f3",
13 | success: "#4caf50"
14 | },
15 | iconfont: 'md',
16 | })
17 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Content/views/About.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
This is an about page
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Content/views/test 2/index.html:
--------------------------------------------------------------------------------
1 |
2 | Test
3 | Test2
4 | Test paragraph.
5 |
6 |
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/ContentEncodingMethodTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Xunit;
9 |
10 | namespace Vlingo.Xoom.Http.Tests;
11 |
12 | public class ContentEncodingMethodTest
13 | {
14 | [Fact]
15 | public void MethodParseReturnsMethod()
16 | {
17 | var method = "gzip";
18 | var result = ContentEncodingMethodHelper.Parse(method);
19 | Assert.True(result.IsPresent);
20 | Assert.Equal(ContentEncodingMethod.Gzip, result.Get());
21 | }
22 |
23 | [Fact]
24 | public void MethodParseReturnsEmpty()
25 | {
26 | var method = "jarjar";
27 | var result = ContentEncodingMethodHelper.Parse(method);
28 | Assert.False(result.IsPresent);
29 | }
30 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/ContentEncodingTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Xunit;
9 |
10 | namespace Vlingo.Xoom.Http.Tests;
11 |
12 | public class ContentEncodingTest
13 | {
14 | [Fact]
15 | public void CreateEncodingFrom()
16 | {
17 | var results = ContentEncoding.ParseFromHeader("gzip, br");
18 | ContentEncodingMethod[] expectedMethods =
19 | {
20 | ContentEncodingMethod.Gzip, ContentEncodingMethod.Brotli
21 | };
22 |
23 | Assert.Equal(expectedMethods, results.EncodingMethods);
24 | }
25 |
26 | [Fact]
27 | public void CreateEncodingSkipsUnkownEncoding()
28 | {
29 | var results = ContentEncoding.ParseFromHeader("gzip, br, foo");
30 | ContentEncodingMethod[] expectedMethods = {
31 | ContentEncodingMethod.Gzip, ContentEncodingMethod.Brotli
32 | };
33 |
34 | Assert.Equal(expectedMethods, results.EncodingMethods);
35 | }
36 |
37 | [Fact]
38 | public void CreateEncodingEmpty()
39 | {
40 | ContentEncoding results = ContentEncoding.ParseFromHeader("");
41 | ContentEncodingMethod[] expectedMethods = {};
42 | Assert.Equal(expectedMethods, results.EncodingMethods);
43 | }
44 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/ContentTypeTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Xunit;
9 |
10 | namespace Vlingo.Xoom.Http.Tests;
11 |
12 | public class ContentTypeTest
13 | {
14 | [Fact]
15 | public void TestThatContentTypeHasMediaTypeOnly()
16 | {
17 | var contentType = ContentType.Of("text/html");
18 |
19 | Assert.NotNull(contentType);
20 | Assert.Equal("text/html", contentType.MediaType);
21 | Assert.Equal("text/html", contentType.ToString());
22 | Assert.Equal(string.Empty, contentType.Charset);
23 | Assert.Equal(string.Empty, contentType.Boundary);
24 | }
25 |
26 | [Fact]
27 | public void TestThatContentTypeHasMediaTypeCharsetOnly()
28 | {
29 | var contentType = ContentType.Of("text/html", "charset=UTF-8");
30 |
31 | Assert.NotNull(contentType);
32 | Assert.Equal("text/html", contentType.MediaType);
33 | Assert.Equal("charset=UTF-8", contentType.Charset);
34 | Assert.Equal("text/html; charset=UTF-8", contentType.ToString());
35 | Assert.Equal(string.Empty, contentType.Boundary);
36 | }
37 |
38 | [Fact]
39 | public void TestThatContentTypeHasMediaTypeCharsetBoundaryOnly()
40 | {
41 | var contentType = ContentType.Of("text/html", "charset=UTF-8", "boundary=something");
42 |
43 | Assert.NotNull(contentType);
44 | Assert.Equal("text/html", contentType.MediaType);
45 | Assert.Equal("charset=UTF-8", contentType.Charset);
46 | Assert.Equal("boundary=something", contentType.Boundary);
47 | Assert.Equal("text/html; charset=UTF-8; boundary=something", contentType.ToString());
48 | }
49 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Converter.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System;
9 | using System.IO;
10 | using System.Text;
11 | using Xunit.Abstractions;
12 |
13 | namespace Vlingo.Xoom.Http.Tests;
14 |
15 | public class Converter : TextWriter
16 | {
17 | private readonly ITestOutputHelper _output;
18 |
19 | public Converter(ITestOutputHelper output) => _output = output;
20 |
21 | public override Encoding Encoding => Encoding.UTF8;
22 |
23 | public override void WriteLine(string message)
24 | {
25 | try
26 | {
27 | _output.WriteLine(message);
28 | }
29 | catch (InvalidOperationException e)
30 | {
31 | if (e.Message != "There is no currently active test.")
32 | {
33 | throw;
34 | }
35 | }
36 | }
37 |
38 | public override void WriteLine(string format, params object[] args) => _output.WriteLine(format, args);
39 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/ExtendedCharactersFixture.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System.Text;
9 |
10 | namespace Vlingo.Xoom.Http.Tests;
11 |
12 | public class ExtendedCharactersFixture
13 | {
14 | public static string AsciiWithExtendedCharacters()
15 | {
16 | var builder = new StringBuilder();
17 |
18 | var asciiBegin = 0x0020;
19 | var asciiEnd = 0x007E;
20 |
21 | for (var ascii = asciiBegin; ascii <= asciiEnd; ++ascii)
22 | {
23 | builder.Append((char) ascii);
24 | }
25 |
26 | var cyrillicBegin = 0x0409;
27 | var cyrillicEnd = 0x04FF;
28 |
29 | for (var cyrillic = cyrillicBegin; cyrillic <= cyrillicEnd; ++cyrillic)
30 | {
31 | builder.Append((char) cyrillic);
32 | }
33 |
34 | var greekCopticBegin = 0x0370;
35 | var greekCopticEnd = 0x03FF;
36 |
37 | for (var greekCoptic = greekCopticBegin; greekCoptic <= greekCopticEnd; ++greekCoptic)
38 | {
39 | builder.Append((char) greekCoptic);
40 | }
41 |
42 | return builder.ToString();
43 | }
44 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Media/AcceptMediaTypeTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Vlingo.Xoom.Http.Media;
9 | using Xunit;
10 |
11 | namespace Vlingo.Xoom.Http.Tests.Media;
12 |
13 | public class AcceptMediaTypeTest
14 | {
15 | [Fact]
16 | public void SpecificMimeTypeGreaterThanGeneric()
17 | {
18 | var acceptMediaType1 = new ResponseMediaTypeSelector.AcceptMediaType("application", "json");
19 | var acceptMediaType2 = new ResponseMediaTypeSelector.AcceptMediaType("*", "*");
20 | Assert.Equal( 1, acceptMediaType1.CompareTo(acceptMediaType2));
21 | Assert.Equal( -1, acceptMediaType2.CompareTo(acceptMediaType1));
22 | }
23 |
24 | [Fact]
25 | public void SpecificMimeSubTypeGreaterThanGeneric()
26 | {
27 | var acceptMediaType1 = new ResponseMediaTypeSelector.AcceptMediaType("application", "json");
28 | var acceptMediaType2 = new ResponseMediaTypeSelector.AcceptMediaType("application", "*");
29 | Assert.Equal( 1, acceptMediaType1.CompareTo(acceptMediaType2));
30 | Assert.Equal( -1, acceptMediaType2.CompareTo(acceptMediaType1));
31 | }
32 |
33 | [Fact]
34 | public void SpecificParameterGreaterThanGenericWithSameQualityFactor()
35 | {
36 | var acceptMediaType1 = new MediaTypeDescriptor.Builder(
37 | (a, b, c) => new ResponseMediaTypeSelector.AcceptMediaType(a, b, c))
38 | .WithMimeType("application")
39 | .WithMimeSubType("xml")
40 | .WithParameter("version", "1.0")
41 | .Build();
42 |
43 | var acceptMediaType2 = new ResponseMediaTypeSelector.AcceptMediaType("application", "json");
44 | Assert.Equal( 1, acceptMediaType1.CompareTo(acceptMediaType2));
45 | Assert.Equal( -1, acceptMediaType2.CompareTo(acceptMediaType1));
46 | }
47 |
48 | [Fact]
49 | public void QualityFactorTrumpsSpecificity()
50 | {
51 | var acceptMediaType1 = new MediaTypeDescriptor.Builder(
52 | (a, b, c) => new ResponseMediaTypeSelector.AcceptMediaType(a, b, c))
53 | .WithMimeType("text")
54 | .WithMimeSubType("*")
55 | .Build();
56 |
57 | var acceptMediaType2 = new MediaTypeDescriptor.Builder(
58 | (a, b, c) => new ResponseMediaTypeSelector.AcceptMediaType(a, b, c))
59 | .WithMimeType("text")
60 | .WithMimeSubType("json")
61 | .WithParameter("q", "0.8")
62 | .Build();
63 |
64 | Assert.Equal( 1, acceptMediaType1.CompareTo(acceptMediaType2));
65 | Assert.Equal( -1, acceptMediaType2.CompareTo(acceptMediaType1));
66 | }
67 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Media/ContentMediaTypeTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Vlingo.Xoom.Http.Media;
9 | using Vlingo.Xoom.Http.Resource;
10 | using Xunit;
11 |
12 | namespace Vlingo.Xoom.Http.Tests.Media;
13 |
14 | public class ContentMediaTypeTest
15 | {
16 | [Fact]
17 | public void WildCardsAreNotAllowed()
18 | {
19 | Assert.Throws(() => new ContentMediaType("application", "*"));
20 | }
21 |
22 | [Fact]
23 | public void InvalidMimeTypeNotAllowed()
24 | {
25 | Assert.Throws(() => new ContentMediaType("unknownMimeType", "foo"));
26 | }
27 |
28 | [Fact]
29 | public void BuilderCreates()
30 | {
31 | var builder = new MediaTypeDescriptor.Builder((a, b, c) => new ContentMediaType(a, b, c));
32 | var contentMediaType = builder
33 | .WithMimeType(ContentMediaType.MimeTypes.Application.ToString().ToLower())
34 | .WithMimeSubType("json")
35 | .Build();
36 |
37 | Assert.Equal(ContentMediaType.Json, contentMediaType);
38 | }
39 |
40 | [Fact]
41 | public void BuiltInTypesHaveCorrectFormat()
42 | {
43 | var jsonType = new ContentMediaType("application", "json");
44 | Assert.Equal(jsonType, ContentMediaType.Json);
45 |
46 | var xmlType = new ContentMediaType("application", "xml");
47 | Assert.Equal(xmlType, ContentMediaType.Xml);
48 | }
49 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Media/MediaTypeParserTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System.Collections.Generic;
9 | using Vlingo.Xoom.Http.Media;
10 | using Xunit;
11 |
12 | namespace Vlingo.Xoom.Http.Tests.Media;
13 |
14 | public class MediaTypeParserTest
15 | {
16 | [Fact]
17 | public void SimpleTypeEmptyParameters()
18 | {
19 | var mediaType = Parse("application/json");
20 | var mediaTypeExpected = new MediaTypeDescriptor.Builder(
21 | (a, b, c) => new MediaTypeTest(a, b, c))
22 | .WithMimeType("application")
23 | .WithMimeSubType("json")
24 | .Build();
25 |
26 | Assert.Equal(mediaTypeExpected, mediaType);
27 | }
28 |
29 | [Fact]
30 | public void ParseParameters()
31 | {
32 | var mediaTypeDescriptor = Parse("application/*;q=0.8;foo=bar");
33 |
34 | var mediaTypeExpected = new MediaTypeDescriptor.Builder(
35 | (a, b, c) => new MediaTypeTest(a, b, c))
36 | .WithMimeType("application")
37 | .WithMimeSubType("*")
38 | .WithParameter("q", "0.8")
39 | .WithParameter("foo", "bar")
40 | .Build();
41 |
42 | Assert.Equal(mediaTypeExpected, mediaTypeDescriptor);
43 | Assert.Equal("application/*;q=0.8;foo=bar", mediaTypeDescriptor.ToString());
44 | }
45 |
46 | [Fact]
47 | public void IncorrectFormatUsesEmptyStringAndDefaultQuality()
48 | {
49 | var mediaType = Parse("typeOnly");
50 | var mediaTypeExpected = new MediaTypeDescriptor.Builder(
51 | (a, b, c) => new MediaTypeTest(a, b, c))
52 | .WithMimeType("")
53 | .WithMimeSubType("")
54 | .Build();
55 |
56 | Assert.Equal(mediaTypeExpected, mediaType);
57 | }
58 |
59 | private MediaTypeTest Parse(string descriptor)
60 | {
61 | return MediaTypeParser.ParseFrom(descriptor,
62 | new MediaTypeDescriptor.Builder(
63 | (a, b, c) => new MediaTypeTest(a, b, c)));
64 | }
65 |
66 | private class MediaTypeTest : MediaTypeDescriptor
67 | {
68 | public MediaTypeTest(string mimeType, string mimeSubType, IDictionary parameters)
69 | : base(mimeType, mimeSubType, parameters)
70 | {
71 | }
72 | }
73 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Media/ResponseContentMediaTypeSelectorTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Vlingo.Xoom.Http.Media;
9 | using Xunit;
10 |
11 | namespace Vlingo.Xoom.Http.Tests.Media;
12 |
13 | public class ResponseContentMediaTypeSelectorTest
14 | {
15 | [Fact]
16 | public void Single_media_type_matches()
17 | {
18 | var specificTypeAccepted = "application/json";
19 | var selector = new ResponseMediaTypeSelector(specificTypeAccepted);
20 | var selected = selector.SelectType(new[]{ContentMediaType.Json});
21 | Assert.Equal(ContentMediaType.Json, selected);
22 | }
23 |
24 | [Fact]
25 | public void Wild_card_media_type_matches()
26 | {
27 | var xmlAndJsonSuperTypeAccepted = "application/*";
28 | var selector = new ResponseMediaTypeSelector(xmlAndJsonSuperTypeAccepted);
29 | var selected = selector.SelectType(new[]{ContentMediaType.Json});
30 | Assert.Equal(ContentMediaType.Json, selected);
31 | }
32 |
33 | [Fact]
34 | public void Generic_media_type_select_by_order_of_media_type()
35 | {
36 | var xmlAndJsonSuperTypeAccepted = "application/*";
37 | var selector = new ResponseMediaTypeSelector(xmlAndJsonSuperTypeAccepted);
38 | var selected = selector.SelectType(new[]{ContentMediaType.Xml, ContentMediaType.Json});
39 | Assert.Equal(ContentMediaType.Xml, selected);
40 | }
41 |
42 | [Fact]
43 | public void Specific_media_type_select_highest_ranked()
44 | {
45 | var jsonHigherPriorityXmlLowerPriorityAccepted = "application/xml;q=0.8, application/json";
46 | var selector = new ResponseMediaTypeSelector(jsonHigherPriorityXmlLowerPriorityAccepted);
47 | var selected = selector.SelectType(new[]{ContentMediaType.Xml, ContentMediaType.Json});
48 | Assert.Equal(ContentMediaType.Json, selected);
49 | }
50 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Resource/DefaultTextPlainMapperTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System;
9 | using Vlingo.Xoom.Http.Resource;
10 | using Xunit;
11 |
12 | namespace Vlingo.Xoom.Http.Tests.Resource;
13 |
14 | public class DefaultTextPlainMapperTest
15 | {
16 | [Fact]
17 | public void TestFromObjectToStringUsesToString()
18 | {
19 | var mapper = new DefaultTextPlainMapper();
20 | Assert.Equal("toStringResult", mapper.From(new ObjectForTest()));
21 | }
22 |
23 | [Fact]
24 | public void TestDeserializationToNonStringFails()
25 | {
26 | var mapper = new DefaultTextPlainMapper();
27 | Assert.Throws(() => mapper.From("some string", typeof(ObjectForTest)));
28 | }
29 |
30 | [Fact]
31 | public void TestDeserializationToStringSucceed()
32 | {
33 | var mapper = new DefaultTextPlainMapper();
34 | var canBeSerialized = mapper.From("some string", typeof(string));
35 | Assert.Equal("some string", canBeSerialized);
36 | }
37 | }
38 |
39 | internal class ObjectForTest
40 | {
41 | public override string ToString() => "toStringResult";
42 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Resource/FailResource.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using Vlingo.Xoom.Common;
9 | using Vlingo.Xoom.Http.Resource;
10 | using Xunit.Abstractions;
11 |
12 | namespace Vlingo.Xoom.Http.Tests.Resource;
13 |
14 | public class FailResource : ResourceHandler
15 | {
16 | private readonly ITestOutputHelper _output;
17 |
18 | public FailResource(ITestOutputHelper output) => _output = output;
19 |
20 | public ICompletes Query()
21 | {
22 | _output.WriteLine("QUERY");
23 | return Xoom.Common.Completes.WithFailure(Response.Of(ResponseStatus.BadRequest));
24 | }
25 |
26 | public override Http.Resource.Resource Routes()
27 | => ResourceBuilder.Resource("Failure API", ResourceBuilder.Get("/fail").Handle(Query));
28 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Resource/Feed/EventsFeedProducerActor.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System.Text;
9 | using Vlingo.Xoom.Actors;
10 | using Vlingo.Xoom.Http.Resource.Feed;
11 |
12 | namespace Vlingo.Xoom.Http.Tests.Resource.Feed;
13 |
14 | public class EventsFeedProducerActor : Actor, IFeedProducer
15 | {
16 | public void ProduceFeedFor(FeedProductRequest request)
17 | {
18 | var body =
19 | new StringBuilder()
20 | .Append(request.FeedName)
21 | .Append(":")
22 | .Append(request.FeedProductId)
23 | .Append(":");
24 |
25 | for (var count = 1; count <= request.FeedProductElements; ++count)
26 | {
27 | body.Append(count).Append("\n");
28 | }
29 |
30 | var response = Response.Of(ResponseStatus.Ok, body.ToString());
31 | request.Context?.Completes.With(response);
32 | }
33 | }
--------------------------------------------------------------------------------
/src/Vlingo.Xoom.Http.Tests/Resource/MediaTypeMapperTest.cs:
--------------------------------------------------------------------------------
1 | // Copyright © 2012-2023 VLINGO LABS. All rights reserved.
2 | //
3 | // This Source Code Form is subject to the terms of the
4 | // Mozilla Public License, v. 2.0. If a copy of the MPL
5 | // was not distributed with this file, You can obtain
6 | // one at https://mozilla.org/MPL/2.0/.
7 |
8 | using System;
9 | using Vlingo.Xoom.Http.Media;
10 | using Vlingo.Xoom.Http.Resource;
11 | using Xunit;
12 |
13 | namespace Vlingo.Xoom.Http.Tests.Resource;
14 |
15 | public class MediaTypeMapperTest
16 | {
17 | [Fact]
18 | public void Registered_mapper_maps_type()
19 | {
20 | var mappedToObject = new Object();
21 | var mappedToString = "mappedToString";
22 |
23 | var testMapper = new TestMapper