Exemple #1
0
        public static Task SendDownstreamResponse(HttpRequest request, UpstreamResponse upstreamResponse, HttpResponse response, bool cached)
        {
            response.StatusCode = upstreamResponse.StatusCode;

            foreach (var header in upstreamResponse.Headers)
            {
                // For cached responses, copy the client-request-id header from request since client requires these to match
                if (cached && header.Key == "x-ms-client-request-id")
                {
                    response.Headers.Add(header.Key, request.Headers[header.Key]);
                }
                else
                {
                    response.Headers.Add(header.Key, header.Value);
                }
            }

            return(response.Body.WriteAsync(upstreamResponse.Content, 0, upstreamResponse.Content.Length));
        }
Exemple #2
0
        static void Run()
        {
            Console.WriteLine("=== Options ===");
            Console.WriteLine(JsonSerializer.Serialize(Options, Options.GetType(), new JsonSerializerOptions()
            {
                WriteIndented = true,
            }));
            Console.WriteLine();

            var allHeaders = Options.Headers.Concat(ServiceHeaders.Get(Options.Service));

            Console.WriteLine("=== Headers ===");
            foreach (var header in allHeaders)
            {
                Console.WriteLine(header);
            }
            Console.WriteLine();

            Console.WriteLine("=== Startup ===");
            new WebHostBuilder()
            .UseKestrel(options =>
            {
                options.Listen(IPAddress.Any, 7777);
                options.Listen(IPAddress.Any, 7778, listenOptions =>
                {
                    listenOptions.UseHttps("testCert.pfx", "testPassword");
                });
            })
            .UseContentRoot(Directory.GetCurrentDirectory())
            .Configure(app => app.Run(async context =>
            {
                try
                {
                    var request  = context.Request;
                    var response = context.Response;

                    if (Options.Debug && request.Path.Value == "/debug")
                    {
                        if (Options.Dots)
                        {
                            Console.Write("#");
                        }

                        var buffer = Encoding.UTF8.GetBytes("debug");
                        await response.Body.WriteAsync(buffer, 0, buffer.Length);
                        return;
                    }

                    var key = new RequestCacheKey(request, allHeaders);

                    if (_cache.TryGetValue(key, out var upstreamResponse))
                    {
                        if (Options.Dots)
                        {
                            Console.Write(".");
                        }

                        if (Options.CacheLast)
                        {
                            _lastUpstreamResponse = upstreamResponse;
                        }
                        await Proxy.SendDownstreamResponse(request, upstreamResponse, response, cached: true);
                    }
                    else if (Options.CacheLast && request.Path.Value == "/last")
                    {
                        if (Options.Dots)
                        {
                            Console.Write("@");
                        }

                        // Used for perf testing the cache lookup and downstream response generation.  This allows a perf client like
                        // "wrk" to directly request the last response without using the server as an HTTP proxy, since "wrk" is much
                        // slower when using a proxy (50k vs 6k RPS).
                        await Proxy.SendDownstreamResponse(request, _lastUpstreamResponse, response, cached: true);
                    }
                    else
                    {
                        if (Options.Dots)
                        {
                            Console.Write("*");
                        }

                        upstreamResponse = await Proxy.SendUpstreamRequest(request);
                        await Proxy.SendDownstreamResponse(request, upstreamResponse, response, cached: false);
                        _cache.AddOrUpdate(key, upstreamResponse, (k, r) => upstreamResponse);

                        if (Options.CacheLast)
                        {
                            _lastUpstreamResponse = upstreamResponse;
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }))
            .Build()
            .Run();
        }