Пример #1
0
        public static AppDelegate App()
        {
            return (env, result, fault) =>
            {
                var request = new Request(env);
                var response = new Response(result);

                if (request.Path == "/")
                {
                    response.Status = "200 OK";
                    response.ContentType = "text/html";
                    response.Start(() =>
                    {
                        response.Write("<h1>Sample.App</h1>");
                        response.Write("<p><a href='{0}/wilson/'>Wilson</a></p>", request.PathBase);
                        response.Write("<p><a href='{0}/wilsonasync/'>Wilson (async)</a></p>", request.PathBase);
                        response.Write("<p><a href='{0}/nancy/'>Nancy</a></p>", request.PathBase);
                        response.Write("<p><a href='{0}/fileupload'>File Upload</a></p>", request.PathBase);
                        response.End();
                    });
                }
                else
                {
                    NotFound.Call(env, result, fault);
                }
            };
        }
Пример #2
0
        public Task<RouteResult> Route(Request request, ITrace tracer)
        {
            Requires.NotNull(request, "request");
            Requires.NotNull(tracer, "tracer");

            // This is so slooooow!
            IFile file;
            string[] pathFragments = request.Path.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
            for (int end = pathFragments.Length - 1; end >= 0; end--)
            {
                Tuple<string, string> candidate = CreateCandidate(pathFragments, end);
                file = ResolveCandidate(candidate.Item1.Replace('/', Path.DirectorySeparatorChar));
                if (file != null)
                {
                    return Task.FromResult(RouteResult.Successful(file, candidate.Item2));
                }
            }
            file = ResolveCandidate(String.Empty);
            if (file != null)
            {
                return Task.FromResult(RouteResult.Successful(file, request.Path.TrimStart('/')));
            }
            else
            {
                return Task.FromResult(RouteResult.Failed());
            }
        }
Пример #3
0
        static AppFunc ShowFormValues(AppFunc next)
        {
            return env =>
            {
                var req = new Request(env);
                if (req.Method != "POST")
                {
                    return next(env);
                }

                var res = new Response(env) { ContentType = "text/plain" };
                return req.ReadFormAsync().Then(
                    form =>
                    {
                        using (var writer = new StreamWriter(res.OutputStream))
                        {
                            foreach (var kv in form)
                            {
                                writer.Write(kv.Key);
                                writer.Write(": ");
                                writer.WriteLine(kv.Value);
                            }
                        }
                    });
            };
        }
Пример #4
0
 void RootIsAlphaHtml(Request req)
 {
     if (req.Path == "/")
     {
         req.Path = "/Alpha.html";
     }
 }
Пример #5
0
        public Task<ResultParameters> Invoke(CallParameters call)
        {
            var request = new Request(call);
            var response = new Response();

            if (request.Path == "/")
            {
                response.Status = "200 OK";
                response.ContentType = "text/html";
                response.StartAsync().Then(resp1 =>
                {
                    resp1.Write("<h1>Sample.App</h1>");
                    resp1.Write("<p><a href='{0}/wilson/'>Wilson</a></p>", request.PathBase);
                    resp1.Write("<p><a href='{0}/wilsonasync/'>Wilson (async)</a></p>", request.PathBase);
                    resp1.Write("<p><a href='{0}/nancy/'>Nancy</a></p>", request.PathBase);
                    resp1.Write("<p><a href='{0}/fileupload'>File Upload</a></p>", request.PathBase);
                    resp1.End();
                });
                return response.ResultTask;
            }
            else
            {
                response.StatusCode = 404;
                return response.EndAsync();
            }
        }
Пример #6
0
 private static async Task<Response> ExecuteCore(IEdgePage page, Request request, ITrace tracer)
 {
     Response resp = new Response(200);
     resp.Start();
     await page.Run(request, resp);
     resp.End();
     return resp;
 }
Пример #7
0
        public Task<Response> Execute(IEdgePage page, Request request, ITrace tracer)
        {
            Requires.NotNull(page, "page");
            Requires.NotNull(request, "request");
            Requires.NotNull(tracer, "tracer");

            return ExecuteCore(page, request, tracer);
        }
Пример #8
0
 public override void AttachToHttpApp(IRobot robo, IAppBuilder app)
 {
     app.UseFunc(next => async environment => {
         var req = new Request(environment);
         TraceRequest(robo, req);
         await next(environment);
         TraceResponse(robo, req, new Response(environment));
     });
 }
Пример #9
0
 public static AppDelegate LogToConsole(AppDelegate app)
 {
     return
         (env, result, fault) =>
         {
             var req = new Request(env);
             Console.WriteLine(req.Method + " " + req.PathBase + req.Path);
             app(env, result, fault);
         };
 }
Пример #10
0
        public Task Invoke(IDictionary<string, object> env)
        {
            IList<string> warnings = new List<string>();
            if (!TryValidateCall(env, warnings))
            {
                return TaskHelpers.Completed();
            }

            var req = new Request(env);
            Stream originalStream = req.Body;
            TriggerStream triggerStream = new TriggerStream(originalStream);
            req.Body = triggerStream;

            // Validate response headers and values on first write.
            bool responseValidated = false;
            Action responseValidation = () =>
            {
                if (responseValidated)
                {
                    return;
                }

                responseValidated = true;

                if (!TryValidateResult(env, warnings))
                {
                    return;
                }

                if (warnings.Count > 0)
                {
                    req.Headers["X-OwinValidatorWarning"] = warnings.ToArray();
                }
            };
            triggerStream.OnFirstWrite = responseValidation;

            try
            {
                return nextApp(env)
                    // Run response validation explicitly in case there was no response data written.
                    .Then(responseValidation)
                    .Catch(errorInfo =>
                    {
                        SetFatalResult(env, "6.1", "An asynchronous exception was thrown from the AppFunc: <br>"
                            + errorInfo.Exception.ToString().Replace(Environment.NewLine, "<br>"));
                        return errorInfo.Handled();
                    });
            }
            catch (Exception ex)
            {
                SetFatalResult(env, "6.1", "A synchronous exception was thrown from the AppFunc: <br>"
                            + ex.ToString().Replace(Environment.NewLine, "<br>"));
                return TaskHelpers.Completed();
            }
        }
Пример #11
0
        private void TraceCall(IDictionary<string, object> env)
        {
            var req = new Request(env);
            traceSource.TraceEvent(TraceEventType.Start, 0, "Request: Environment#{0}", env.Count);

            traceSource.TraceInformation("Environment: ");
            TraceDictionary(env);

            traceSource.TraceInformation("Headers: ");
            TraceHeaders(req.Headers);
        }
Пример #12
0
        private void LogCall(TextWriter logger, IDictionary<string, object> env)
        {
            var req = new Request(env);

            logger.WriteLine("{0} - Request: Environment#{1}", DateTime.Now, env.Count);

            logger.WriteLine("Environment: ");
            LogDictionary(logger, env);

            logger.WriteLine("Headers: ");
            LogHeaders(logger, req.Headers);
        }
Пример #13
0
 public static AppDelegate Alias(AppDelegate app, string path, string alias)
 {
     return
         (env, result, fault) =>
         {
             var req = new Request(env);
             if (req.Path == path)
             {
                 req.Path = alias;
             }
             app(env, result, fault);
         };
 }
Пример #14
0
        public Task Invoke(IDictionary<string, object> env)
        {
            var req = new Request(env);
            var logger = loggerOverride ?? req.TraceOutput;

            if (logger == null)
            {
                return nextApp(env);
            }

            LogCall(logger, env);
            return nextApp(env).Then(() =>
            {
                LogResult(logger, env);
            });
        }
Пример #15
0
        public static IAppBuilder Post(this IAppBuilder builder, Action<Request, Response> app)
        {
            return builder.Use<AppDelegate>(next => (env, result, fault) =>
            {
                if ((string)env["owin.RequestMethod"] == "POST")
                {
                    var req = new Request(env);
                    var res = new Response(result);
                    app(req, res);

                }
                else
                {
                    next(env, result, fault);
                }
            });
        }
Пример #16
0
        public static IAppBuilder UseDirect(this IAppBuilder builder, Func<Request, Response, Task> app)
        {
            return builder.UseFunc<AppDelegate>(next => call =>
            {
                var req = new Request(call);
                var resp = new Response
                {
                    Next = () => next(call)
                };

                app.Invoke(req, resp)
                    .Catch(caught =>
                    {
                        resp.Error(caught.Exception);
                        return caught.Handled();
                    });
                return resp.ResultTask;
            });
        }
Пример #17
0
        public static IAppBuilder UseDirect(this IAppBuilder builder, Func<Request, Response, Task> app)
        {
            return builder.UseFunc<AppFunc>(next => environment =>
            {
                var req = new Request(environment);
                var resp = new Response(environment)
                {
                    Next = () => next(environment)
                };

                app.Invoke(req, resp)
                    .Then(() => resp.EndAsync())
                    .Catch(caught =>
                    {
                        resp.End(caught.Exception);
                        return caught.Handled();
                    });
                return resp.Task;
            });
        }
Пример #18
0
        public Task Invoke(IDictionary<string, object> env)
        {
            var request = new Request(env);
            var response = new Response(env);

            if (request.Path == "/")
            {
                response.Status = "200 OK";
                response.ContentType = "text/html";
                response.Write("<h1>Sample.App</h1>");
                response.Write("<p><a href='{0}/wilson/'>Wilson</a></p>", request.PathBase);
                response.Write("<p><a href='{0}/wilsonasync/'>Wilson (async)</a></p>", request.PathBase);
                response.Write("<p><a href='{0}/nancy/'>Nancy</a></p>", request.PathBase);
                response.Write("<p><a href='{0}/fileupload'>File Upload</a></p>", request.PathBase);
            }
            else
            {
                response.StatusCode = 404;
            }
            return TaskHelpers.Completed();
        }
Пример #19
0
        /// <summary>
        /// Send data back to the user
        /// </summary>
        /// <param name="result">Result delegate from server-callback</param>
        /// <param name="bytes">byte-array to send</param>
        private void SendText(ResultDelegate result, IDictionary<string, object> env, string text, int httpCode = 200)
        {
            Response response = new Response(result);
            Request request = new Request(env);

            string requestString = (string)env[OwinConstants.RequestPath];

            response.ContentType = requestString.MimeType();

            response.Write(text);

            response.End();
        }
Пример #20
0
 private void TraceResponse(IRobot robo, Request request, Response response)
 {
     robo.Log.Trace("-> http {0} {1}", response.StatusCode.ToString().PadRight("PATCH".Length), request.Path);
 }
Пример #21
0
 private void TraceRequest(IRobot robo, Request request)
 {
     robo.Log.Trace("<- http {0} {1}", request.Method.PadRight("PATCH".Length), request.Path);
 }
Пример #22
0
 public Task Invoke(IDictionary<string, object> env)
 {
     var req = new Request(env);
     if (req.Path.EndsWith("/") && File.Exists(Path.Combine(req.Path.Substring(1), _fileName)))
     {
         req.Path += _fileName;
     }
     return _next(env);
 }
Пример #23
0
 private async Task App(Request req, Response res)
 {
     res.ContentType = "text/plain";
     res.Write("You did a {0} at {1}", req.Method, req.Path);
 }
Пример #24
0
        // Returns false for fatal errors, along with a resulting message.
        // Otherwise any warnings are appended.
        private static bool TryValidateCall(IDictionary<string, object> env, IList<string> warnings)
        {
            if (env == null)
            {
                throw new ArgumentNullException("env");
            }

            var req = new Request(env);

            // Must be mutable
            try
            {
                string key = "validator.MutableKey";
                string input = "Mutable Value";
                req.Set(key, input);
                string output = req.Get<string>(key);
                if (output == null || output != input)
                {
                    SetFatalResult(env, "3.2", "Environment is not fully mutable.");
                    return false;
                }
                req.Set<string>(key, null);
            }
            catch (Exception ex)
            {
                SetFatalResult(env, "3.2", "Environment is not mutable: \r\n" + ex.ToString());
                return false;
            }

            // Environment key names MUST be case sensitive.
            string upperKey = "Validator.CaseKey";
            string lowerKey = "validator.casekey";
            string[] caseValue = new string[] { "Case Value" };
            env[upperKey] = caseValue;
            string[] resultValue = req.Get<string[]>(lowerKey);
            if (resultValue != null)
            {
                SetFatalResult(env, "3.2", "Environment is not case sensitive.");
                return false;
            }
            env.Remove(upperKey);

            // Check for required owin.* keys and the HOST header.
            if (!CheckRequiredCallData(env, warnings))
            {
                return false;
            }

            return true;
        }
Пример #25
0
        private static bool CheckRequiredCallData(IDictionary<string, object> env, IList<string> warnings)
        {
            var req = new Request(env);
            string[] requiredKeys = new string[]
            {
                "owin.Version",
                "owin.CallCancelled",

                "owin.RequestBody",
                "owin.RequestHeaders",
                "owin.RequestMethod",
                "owin.RequestPath",
                "owin.RequestPathBase",
                "owin.RequestProtocol",
                "owin.RequestQueryString",
                "owin.RequestScheme",

                "owin.ResponseHeaders",
                "owin.ResponseBody",
            };

            object temp;
            foreach (string key in requiredKeys)
            {
                if (!env.TryGetValue(key, out temp))
                {
                    SetFatalResult(env, "3.2", "Missing required Environment key: " + key);
                    return false;
                }

                if (temp == null)
                {
                    SetFatalResult(env, "3.2", "Required Environment value is null: " + key);
                    return false;
                }
            }

            IDictionary<string, string[]> requestHeaders = req.Get<IDictionary<string, string[]>>("owin.RequestHeaders");
            IDictionary<string, string[]> responseHeaders = req.Get<IDictionary<string, string[]>>("owin.ResponseHeaders");

            if (!TryValidateHeaderCollection(env, requestHeaders, "Request", warnings))
            {
                return false;
            }

            if (!TryValidateHeaderCollection(env, responseHeaders, "Response", warnings))
            {
                return false;
            }

            string[] header;
            if (!requestHeaders.TryGetValue("HOST", out header) || header.Length == 0)
            {
                SetFatalResult(env, "5.2", "Missing Host header");
                return false;
            }

            // Validate values

            string[] stringValueTypes = new string[]
            {
                "owin.RequestMethod",
                "owin.RequestPath",
                "owin.RequestPathBase",
                "owin.RequestProtocol",
                "owin.RequestQueryString",
                "owin.RequestScheme",
                "owin.Version" 
            };

            foreach (string key in stringValueTypes)
            {
                if (!(env[key] is string))
                {
                    SetFatalResult(env, "3.2", key + " value is not of type string: " + env[key].GetType().FullName);
                    return false;
                }
            }

            if (!(env["owin.CallCancelled"] is CancellationToken))
            {
                SetFatalResult(env, "3.2.3", "owin.CallCancelled is not of type CancellationToken: " + env["owin.CallCancelled"].GetType().FullName);
                return false;
            }

            if (req.Get<CancellationToken>("owin.CallCancelled").IsCancellationRequested)
            {
                warnings.Add(CreateWarning("3.6", "The owin.CallCancelled CancellationToken was cancelled before processing the request."));
            }

            if (string.IsNullOrWhiteSpace(req.Get<string>("owin.RequestMethod")))
            {
                SetFatalResult(env, "3.2.1", "owin.RequestMethod is empty.");
                return false;
            }

            string pathBase = req.Get<string>("owin.RequestPathBase");
            if (pathBase.EndsWith("/"))
            {
                SetFatalResult(env, "5.3", "owin.RequestBasePath ends with a slash: " + pathBase);
                return false;
            }


            if (!(pathBase.StartsWith("/") || pathBase.Equals(string.Empty)))
            {
                SetFatalResult(env, "5.3", "owin.RequestBasePath is not empty and does not start with a slash: " + pathBase);
                return false;
            }

            string path = req.Get<string>("owin.RequestPath");
            if (!path.StartsWith("/"))
            {
                if (path.Equals(string.Empty))
                {
                    if (pathBase.Equals(string.Empty))
                    {
                        SetFatalResult(env, "5.3", "owin.RequestPathBase and owin.RequestPath are both empty.");
                        return false;
                    }
                }
                else
                {
                    SetFatalResult(env, "5.3", "owin.RequestPath does not start with a slash.");
                    return false;
                }
            }

            string protocol = req.Get<string>("owin.RequestProtocol");
            if (!protocol.Equals("HTTP/1.1", StringComparison.OrdinalIgnoreCase)
                && !protocol.Equals("HTTP/1.0", StringComparison.OrdinalIgnoreCase))
            {
                warnings.Add(CreateWarning("3.2.1", "Unrecognized request protocol: " + protocol));
            }

            // No query string validation.

            string scheme = req.Get<string>("owin.RequestScheme");
            if (!scheme.Equals("http", StringComparison.OrdinalIgnoreCase)
                && !scheme.Equals("https", StringComparison.OrdinalIgnoreCase))
            {
                warnings.Add(CreateWarning("5.1", "Unrecognized request scheme: " + scheme));
            }

            string version = req.Get<string>("owin.Version");
            Version parsedVersion;
            if (!Version.TryParse(version, out parsedVersion))
            {
                SetFatalResult(env, "7", "owin.Version could not be parsed: " + version);
                return false;
            }

            if (!parsedVersion.Equals(new Version(1, 0)))
            {
                warnings.Add(CreateWarning("7", "Unrecognized OWIN version: " + version));
            }

            return true;
        }
Пример #26
0
        /// <summary>
        /// Queries sent from the client end up here
        /// </summary>
        /// <param name="env"></param>
        /// <param name="result"></param>
        /// <param name="fault"></param>
        private void ServerCallback(IDictionary<string, object> env, ResultDelegate result, Action<Exception> fault)
        {
            string requestString = (string)env[OwinConstants.RequestPath];

            Tracing.Info(requestString);

            var request = new Gate.Request(env);
            var response = new Gate.Response(result);

            if (!content.IsAvailable(requestString))
            {
                // File not found
                SendText(result, env, "Page not found: " + requestString);
                return;
            }
            else
            {
                // Send page back
                if (requestString.MimeType().IsBinaryMime())
                {
                    byte[] fileContents = content.GetBinaryContent(requestString);
                    SendData(result, env, fileContents);
                }
                else
                {
                    string fileContents = content.GetContent(requestString);
                    SendText(result, env, fileContents);
                }

                return;
            }
        }
Пример #27
0
            public Task Invoke(IDictionary<string, object> env)
            {
                var req = new Request(env);
                if (req.Path.StartsWith("/") && !req.Path.EndsWith("/") && Directory.Exists(req.Path.Substring(1)))
                {
                    var resp = new Response(env)
                    {
                        StatusCode = 301
                    };
                    resp.Headers["Location"] = new[] { req.PathBase + req.Path + "/" };
                    return TaskAsyncHelper.Empty;
                }

                return _next(env);
            }
Пример #28
0
        /// <summary>
        /// Send data back to the user
        /// </summary>
        /// <param name="result">Result delegate from server-callback</param>
        /// <param name="bytes">byte-array to send</param>
        private void SendData(ResultDelegate result, IDictionary<string, object> env, byte[] data)
        {
            Response response = new Response(result);
            Request request = new Request(env);

            string requestString = (string)env[OwinConstants.RequestPath];

            response.ContentType = requestString.MimeType();
            response.Headers["Content-Range"] = new string[] { "bytes 0-" + (data.Length - 1).ToString() };
            response.Headers["Content-Length"] = new string[] { data.Length.ToString() };

            response.Write(new ArraySegment<byte>(data));

            response.End();
        }
Пример #29
0
 internal ServerResponse(Request request, Response response)
 {
     _request = request;
     _response = response;
     _cancellationToken = request.CallDisposed;
 }
Пример #30
0
 public Task Invoke(IDictionary<string, object> env)
 {
     var req = new Request(env);
     var res = new Response(env);
     if (String.IsNullOrEmpty(res.ContentType) &&
         req.Path.EndsWith(_extension, StringComparison.OrdinalIgnoreCase))
     {
         res.ContentType = _contentType;
     }
     return _next(env);
 }