Пример #1
0
        static void Initialize()
        {
            if (_initCalled)
            {
                return;
            }
            _initCalled = true;

            // Port that rhino.compute is running on
            // todo: figure out how to programatically determine this port
            ComputeChildren.ParentPort = 5000;
            // Set idle time child processes live. If rhino.compute is not called
            // for this period of time to proxy requests, the child processes will
            // shut down. The processes will be restarted on a later request
            ComputeChildren.ChildIdleSpan = new System.TimeSpan(1, 0, 0);
            // Number of child compute.geometry processes to start for processing.
            // Default to 4 instances, but we might want to set this based on the
            // number of cores available on the computer.
            ComputeChildren.SpawnCount = 4;

            _client = new HttpClient(new HttpClientHandler {
                AllowAutoRedirect = false
            });
            _client.DefaultRequestHeaders.Add("User-Agent", $"compute.rhino3d-proxy/1.0.0");

            // Launch child processes on start. Getting the base url is enough to get things rolling
            ComputeChildren.UpdateLastCall();
            Task.Run(() => ComputeChildren.GetComputeServerBaseUrl());
        }
Пример #2
0
        async Task <HttpResponseMessage> SendProxyRequest(HttpRequest initialRequest, HttpMethod method)
        {
            string baseurl  = ComputeChildren.GetComputeServerBaseUrl();
            string proxyUrl = $"{baseurl}{initialRequest.Path}{initialRequest.QueryString}";

            // mark the current time as a call to a compute child process
            ComputeChildren.UpdateLastCall();

            if (method == HttpMethod.Post)
            {
                using (var stream = initialRequest.BodyReader.AsStream(false))
                {
                    using (var sw = new System.IO.StreamReader(initialRequest.BodyReader.AsStream()))
                    {
                        string body = sw.ReadToEnd();
                        using (var stringContent = new StringContent(body, System.Text.Encoding.UTF8, "applicaton/json"))
                        {
                            return(await _client.PostAsync(proxyUrl, stringContent));
                        }
                    }
                }
            }

            if (method == HttpMethod.Get)
            {
                return(await _client.GetAsync(proxyUrl));
            }

            throw new System.NotSupportedException("Only GET and POST are currently supported for reverse proxy");
        }
Пример #3
0
        private async Task ReverseProxyPost(HttpRequest req, HttpResponse res)
        {
            var proxyResponse = await SendProxyRequest(req, HttpMethod.Post);

            ComputeChildren.UpdateLastCall();
            var s = await proxyResponse.Content.ReadAsStringAsync();

            await res.WriteAsync(s);
        }
Пример #4
0
        private async Task ReverseProxyGet(HttpRequest req, HttpResponse res)
        {
            string responseString;

            using (var tracker = new ConcurrentRequestTracker())
            {
                var proxyResponse = await SendProxyRequest(req, HttpMethod.Get);

                ComputeChildren.UpdateLastCall();
                responseString = await proxyResponse.Content.ReadAsStringAsync();
            }
            await res.WriteAsync(responseString);
        }
Пример #5
0
        public ReverseProxyModule()
        {
            Get("/healthcheck", async(req, res) => await res.WriteAsync("healthy"));
            Get("/robots.txt", async(req, res) => await res.WriteAsync("User-agent: *\nDisallow: / "));
            Get("/idlespan", async(req, res) => await res.WriteAsync($"{ComputeChildren.IdleSpan()}"));
            Get("/", async(req, res) => await res.WriteAsync("compute.rhino3d"));

            // routes that are proxied to compute.geometry
            Get("/{*uri}", ReverseProxyGet);
            Post("/grasshopper", ReverseProxyGrasshopper);
            Post("/{*uri}", ReverseProxyPost);

            Initialize();
        }
        Task LaunchChildren(HttpRequest request, HttpResponse response)
        {
            int children        = System.Convert.ToInt32(request.Query["children"]);
            int parentProcessId = System.Convert.ToInt32(request.Query["parent"]);

            if (Program.IsParentRhinoProcess(parentProcessId))
            {
                for (int i = 0; i < children; i++)
                {
                    ComputeChildren.LaunchCompute(false);
                }
            }
            return(null);
        }
Пример #7
0
        async Task <HttpResponseMessage> SendProxyRequest(HttpRequest initialRequest, HttpMethod method)
        {
            var task = _initTask;

            if (task != null)
            {
                await task;
                _initTask = null;
            }

            string baseurl  = ComputeChildren.GetComputeServerBaseUrl();
            string proxyUrl = $"{baseurl}{initialRequest.Path}{initialRequest.QueryString}";

            // mark the current time as a call to a compute child process
            ComputeChildren.UpdateLastCall();

            if (method == HttpMethod.Post)
            {
                // include RhinoComputeKey header in request to compute child process
                var req = new HttpRequestMessage(HttpMethod.Post, proxyUrl);
                if (initialRequest.Headers.TryGetValue(_apiKeyHeader, out var keyHeader))
                {
                    req.Headers.Add(_apiKeyHeader, keyHeader.ToString());
                }

                using (var stream = initialRequest.BodyReader.AsStream(false))
                {
                    using (var sw = new System.IO.StreamReader(initialRequest.BodyReader.AsStream()))
                    {
                        string body = sw.ReadToEnd();
                        using (var stringContent = new StringContent(body, System.Text.Encoding.UTF8, "applicaton/json"))
                        {
                            req.Content = stringContent;
                            return(await _client.SendAsync(req));
                        }
                    }
                }
            }

            if (method == HttpMethod.Get)
            {
                return(await _client.GetAsync(proxyUrl));
            }

            throw new System.NotSupportedException("Only GET and POST are currently supported for reverse proxy");
        }
Пример #8
0
        static void Initialize()
        {
            if (_initCalled)
            {
                return;
            }
            _initCalled = true;

            _client = new HttpClient(new HttpClientHandler {
                AllowAutoRedirect = false
            });
            _client.DefaultRequestHeaders.Add("User-Agent", $"compute.rhino3d-proxy/1.0.0");

            // Launch child processes on start. Getting the base url is enough to get things rolling
            ComputeChildren.UpdateLastCall();
            _initTask = Task.Run(() => ComputeChildren.GetComputeServerBaseUrl());
        }
Пример #9
0
        public ReverseProxyModule()
        {
            Get("/healthcheck", async(req, res) => await res.WriteAsync("healthy"));
            Get("/robots.txt", async(req, res) => await res.WriteAsync("User-agent: *\nDisallow: / "));
            Get("/idlespan", async(req, res) => await res.WriteAsync($"{ComputeChildren.IdleSpan()}"));
            Get("/", async(req, res) => await res.WriteAsync("compute.rhino3d"));

            // I would like to catch all other GET endpoints and just pass them on. Currently,
            // to lazy to figure out the nice way to do this
            Get("/{a}", ReverseProxyGet);
            Get("/{a}/{b}", ReverseProxyGet);
            Get("/{a}/{b}/{c}", ReverseProxyGet);
            Get("/{a}/{b}/{c}/{d}", ReverseProxyGet);
            Get("/{a}/{b}/{c}/{d}/{e}", ReverseProxyGet);

            Post("/grasshopper", ReverseProxyGrasshopper);
            Post("/{uri}", ReverseProxyPost);

            Initialize();
        }
        private async Task ReverseProxyGet(HttpRequest req, HttpResponse res)
        {
            await AwaitInitTask();

            string responseString;

            using (var tracker = new ConcurrentRequestTracker())
            {
                var(baseurl, port) = ComputeChildren.GetComputeServerBaseUrl();
                var proxyResponse = await SendProxyRequest(req, HttpMethod.Get, baseurl);

                ComputeChildren.UpdateLastCall();
                if (proxyResponse.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    ComputeChildren.MoveToFrontOfQueue(port);
                }

                responseString = await proxyResponse.Content.ReadAsStringAsync();
            }
            await res.WriteAsync(responseString);
        }