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); } }; }
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()); } }
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); } } }); }; }
void RootIsAlphaHtml(Request req) { if (req.Path == "/") { req.Path = "/Alpha.html"; } }
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(); } }
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; }
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); }
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)); }); }
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); }; }
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(); } }
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); }
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); }
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); }; }
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); }); }
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); } }); }
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; }); }
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; }); }
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(); }
/// <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(); }
private void TraceResponse(IRobot robo, Request request, Response response) { robo.Log.Trace("-> http {0} {1}", response.StatusCode.ToString().PadRight("PATCH".Length), request.Path); }
private void TraceRequest(IRobot robo, Request request) { robo.Log.Trace("<- http {0} {1}", request.Method.PadRight("PATCH".Length), request.Path); }
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); }
private async Task App(Request req, Response res) { res.ContentType = "text/plain"; res.Write("You did a {0} at {1}", req.Method, req.Path); }
// 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; }
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; }
/// <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; } }
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); }
/// <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(); }
internal ServerResponse(Request request, Response response) { _request = request; _response = response; _cancellationToken = request.CallDisposed; }
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); }