mirror of
https://github.com/nsnail/Ocelot.git
synced 2025-04-25 10:12:50 +08:00
262 lines
11 KiB
C#
262 lines
11 KiB
C#
namespace Ocelot.AcceptanceTests
|
|
{
|
|
using Butterfly.Client.AspNetCore;
|
|
using Configuration.File;
|
|
using Microsoft.AspNetCore.Builder;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Rafty.Infrastructure;
|
|
using Shouldly;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net;
|
|
using TestStack.BDDfy;
|
|
using Xunit;
|
|
using Xunit.Abstractions;
|
|
|
|
public class ButterflyTracingTests : IDisposable
|
|
{
|
|
private IWebHost _serviceOneBuilder;
|
|
private IWebHost _serviceTwoBuilder;
|
|
private IWebHost _fakeButterfly;
|
|
private readonly Steps _steps;
|
|
private string _downstreamPathOne;
|
|
private string _downstreamPathTwo;
|
|
private int _butterflyCalled;
|
|
private readonly ITestOutputHelper _output;
|
|
|
|
public ButterflyTracingTests(ITestOutputHelper output)
|
|
{
|
|
_output = output;
|
|
_steps = new Steps();
|
|
}
|
|
|
|
[Fact]
|
|
public void should_forward_tracing_information_from_ocelot_and_downstream_services()
|
|
{
|
|
var configuration = new FileConfiguration
|
|
{
|
|
ReRoutes = new List<FileReRoute>
|
|
{
|
|
new FileReRoute
|
|
{
|
|
DownstreamPathTemplate = "/api/values",
|
|
DownstreamScheme = "http",
|
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
|
{
|
|
new FileHostAndPort
|
|
{
|
|
Host = "localhost",
|
|
Port = 51887,
|
|
}
|
|
},
|
|
UpstreamPathTemplate = "/api001/values",
|
|
UpstreamHttpMethod = new List<string> { "Get" },
|
|
HttpHandlerOptions = new FileHttpHandlerOptions
|
|
{
|
|
UseTracing = true
|
|
}
|
|
},
|
|
new FileReRoute
|
|
{
|
|
DownstreamPathTemplate = "/api/values",
|
|
DownstreamScheme = "http",
|
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
|
{
|
|
new FileHostAndPort
|
|
{
|
|
Host = "localhost",
|
|
Port = 51388,
|
|
}
|
|
},
|
|
UpstreamPathTemplate = "/api002/values",
|
|
UpstreamHttpMethod = new List<string> { "Get" },
|
|
HttpHandlerOptions = new FileHttpHandlerOptions
|
|
{
|
|
UseTracing = true
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var butterflyUrl = "http://localhost:9618";
|
|
|
|
this.Given(x => GivenFakeButterfly(butterflyUrl))
|
|
.And(x => GivenServiceOneIsRunning("http://localhost:51887", "/api/values", 200, "Hello from Laura", butterflyUrl))
|
|
.And(x => GivenServiceTwoIsRunning("http://localhost:51388", "/api/values", 200, "Hello from Tom", butterflyUrl))
|
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
|
.And(x => _steps.GivenOcelotIsRunningUsingButterfly(butterflyUrl))
|
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api001/values"))
|
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api002/values"))
|
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Tom"))
|
|
.BDDfy();
|
|
|
|
var commandOnAllStateMachines = Wait.WaitFor(10000).Until(() => _butterflyCalled >= 4);
|
|
|
|
_output.WriteLine($"_butterflyCalled is {_butterflyCalled}");
|
|
|
|
commandOnAllStateMachines.ShouldBeTrue();
|
|
}
|
|
|
|
[Fact]
|
|
public void should_return_tracing_header()
|
|
{
|
|
var configuration = new FileConfiguration
|
|
{
|
|
ReRoutes = new List<FileReRoute>
|
|
{
|
|
new FileReRoute
|
|
{
|
|
DownstreamPathTemplate = "/api/values",
|
|
DownstreamScheme = "http",
|
|
DownstreamHostAndPorts = new List<FileHostAndPort>
|
|
{
|
|
new FileHostAndPort
|
|
{
|
|
Host = "localhost",
|
|
Port = 51387,
|
|
}
|
|
},
|
|
UpstreamPathTemplate = "/api001/values",
|
|
UpstreamHttpMethod = new List<string> { "Get" },
|
|
HttpHandlerOptions = new FileHttpHandlerOptions
|
|
{
|
|
UseTracing = true
|
|
},
|
|
DownstreamHeaderTransform = new Dictionary<string, string>()
|
|
{
|
|
{"Trace-Id", "{TraceId}"},
|
|
{"Tom", "Laura"}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var butterflyUrl = "http://localhost:9618";
|
|
|
|
this.Given(x => GivenFakeButterfly(butterflyUrl))
|
|
.And(x => GivenServiceOneIsRunning("http://localhost:51387", "/api/values", 200, "Hello from Laura", butterflyUrl))
|
|
.And(x => _steps.GivenThereIsAConfiguration(configuration))
|
|
.And(x => _steps.GivenOcelotIsRunningUsingButterfly(butterflyUrl))
|
|
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/api001/values"))
|
|
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
|
|
.And(x => _steps.ThenTheResponseBodyShouldBe("Hello from Laura"))
|
|
.And(x => _steps.ThenTheTraceHeaderIsSet("Trace-Id"))
|
|
.And(x => _steps.ThenTheResponseHeaderIs("Tom", "Laura"))
|
|
.BDDfy();
|
|
}
|
|
|
|
private void GivenServiceOneIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
|
|
{
|
|
_serviceOneBuilder = new WebHostBuilder()
|
|
.UseUrls(baseUrl)
|
|
.UseKestrel()
|
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
.UseIISIntegration()
|
|
.ConfigureServices(services =>
|
|
{
|
|
services.AddButterfly(option =>
|
|
{
|
|
option.CollectorUrl = butterflyUrl;
|
|
option.Service = "Service One";
|
|
option.IgnoredRoutesRegexPatterns = new string[0];
|
|
});
|
|
})
|
|
.Configure(app =>
|
|
{
|
|
app.UsePathBase(basePath);
|
|
app.Run(async context =>
|
|
{
|
|
_downstreamPathOne = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
|
|
|
|
if (_downstreamPathOne != basePath)
|
|
{
|
|
context.Response.StatusCode = statusCode;
|
|
await context.Response.WriteAsync("downstream path didnt match base path");
|
|
}
|
|
else
|
|
{
|
|
context.Response.StatusCode = statusCode;
|
|
await context.Response.WriteAsync(responseBody);
|
|
}
|
|
});
|
|
})
|
|
.Build();
|
|
|
|
_serviceOneBuilder.Start();
|
|
}
|
|
|
|
private void GivenFakeButterfly(string baseUrl)
|
|
{
|
|
_fakeButterfly = new WebHostBuilder()
|
|
.UseUrls(baseUrl)
|
|
.UseKestrel()
|
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
.UseIISIntegration()
|
|
.Configure(app =>
|
|
{
|
|
app.Run(async context =>
|
|
{
|
|
_butterflyCalled++;
|
|
await context.Response.WriteAsync("OK...");
|
|
});
|
|
})
|
|
.Build();
|
|
|
|
_fakeButterfly.Start();
|
|
}
|
|
|
|
private void GivenServiceTwoIsRunning(string baseUrl, string basePath, int statusCode, string responseBody, string butterflyUrl)
|
|
{
|
|
_serviceTwoBuilder = new WebHostBuilder()
|
|
.UseUrls(baseUrl)
|
|
.UseKestrel()
|
|
.UseContentRoot(Directory.GetCurrentDirectory())
|
|
.UseIISIntegration()
|
|
.ConfigureServices(services =>
|
|
{
|
|
services.AddButterfly(option =>
|
|
{
|
|
option.CollectorUrl = butterflyUrl;
|
|
option.Service = "Service Two";
|
|
option.IgnoredRoutesRegexPatterns = new string[0];
|
|
});
|
|
})
|
|
.Configure(app =>
|
|
{
|
|
app.UsePathBase(basePath);
|
|
app.Run(async context =>
|
|
{
|
|
_downstreamPathTwo = !string.IsNullOrEmpty(context.Request.PathBase.Value) ? context.Request.PathBase.Value : context.Request.Path.Value;
|
|
|
|
if (_downstreamPathTwo != basePath)
|
|
{
|
|
context.Response.StatusCode = statusCode;
|
|
await context.Response.WriteAsync("downstream path didnt match base path");
|
|
}
|
|
else
|
|
{
|
|
context.Response.StatusCode = statusCode;
|
|
await context.Response.WriteAsync(responseBody);
|
|
}
|
|
});
|
|
})
|
|
.Build();
|
|
|
|
_serviceTwoBuilder.Start();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_serviceOneBuilder?.Dispose();
|
|
_serviceTwoBuilder?.Dispose();
|
|
_fakeButterfly?.Dispose();
|
|
_steps.Dispose();
|
|
}
|
|
}
|
|
}
|