public static AspNetCoreServirtiumServer WithCommandLineArgs(string[] args, IInteractionMonitor monitor, IInteractionTransforms interactionTransforms) => new AspNetCoreServirtiumServer(Host.CreateDefaultBuilder(args), monitor, interactionTransforms, null);
//private static readonly private AspNetCoreServirtiumServer(IHostBuilder hostBuilder, IInteractionMonitor monitor, IInteractionTransforms interactionTransforms, int?port) { _interactionMonitor = monitor; _host = hostBuilder.ConfigureWebHostDefaults(webBuilder => { if (port != null) { //If a port is specified, override urls with specified port, listening on all available hosts, for HTTP. webBuilder.UseUrls($"http://*:{port}"); } webBuilder.Configure(app => { app.Run(async ctx => { var targetHost = new Uri($"{ctx.Request.Scheme}{Uri.SchemeDelimiter}{ctx.Request.Host}"); var requestInteraction = new MarkdownInteraction.Builder() .Number(_interactionCounter.Bump()) .Method(new System.Net.Http.HttpMethod(ctx.Request.Method)) .Path($"{ctx.Request.Path}{ctx.Request.QueryString}") //Remap headers from a dictionary of string lists to a list of (string, string) tuples .RequestHeaders ( ctx.Request.Headers .SelectMany(kvp => kvp.Value.Select(val => (kvp.Key, val))) .ToArray() ) .Build(); var serviceRequestInteraction = interactionTransforms.TransformClientRequestForRealService(requestInteraction); var responseFromService = await monitor.GetServiceResponseForRequest( targetHost, serviceRequestInteraction, false); var clientResponse = interactionTransforms.TransformRealServiceResponseForClient(responseFromService); //Always remove the 'Transfer-Encoding: chunked' header if present. //If it's present in the response.Headers collection ast this point, Kestrel expects you to add chunk notation to the body yourself //However if you just send it with no content-length, Kestrel will add the chunked header and chunk the body for you. clientResponse = clientResponse .WithRevisedHeaders( clientResponse.Headers .Where((h) => !(h.Name.ToLower() == "transfer-encoding" && h.Value.ToLower() == "chunked"))) .WithReadjustedContentLength(); ctx.Response.OnCompleted(() => { Console.WriteLine($"{requestInteraction.Method} Request to {targetHost}{requestInteraction.Path} returned to client with code {ctx.Response.StatusCode}"); return(Task.CompletedTask); }); //Transfer adjusted headers to the response going out to the client foreach ((string headerName, string headerValue) in clientResponse.Headers) { if (ctx.Response.Headers.TryGetValue(headerName, out var headerInResponse)) { ctx.Response.Headers[headerName] = new StringValues(headerInResponse.Append(headerValue).ToArray()); } else { ctx.Response.Headers[headerName] = new StringValues(headerValue); } } if (clientResponse.Body != null) { await ctx.Response.WriteAsync(clientResponse.Body.ToString()); } await ctx.Response.CompleteAsync(); }); }); }).Build(); }
public static AspNetCoreServirtiumServer WithTransforms(int port, IInteractionMonitor monitor, IInteractionTransforms interactionTransforms) => new AspNetCoreServirtiumServer(Host.CreateDefaultBuilder(), monitor, interactionTransforms, port);