public void ProcessRequest(HttpContext context) { IRequest request = new AspNetRequest(context.Request); IResponse response = Invoke(request); AspNet.WriteResponse(context.Response, response); }
public virtual Task ProcessRequestAsync(HttpContextBase context) { var operationName = this.RequestName ?? context.Request.GetOperationName(); RememberLastRequestInfo(operationName, context.Request.PathInfo); if (String.IsNullOrEmpty(operationName)) { return(EmptyTask); } if (DefaultHandledRequest(context)) { return(EmptyTask); } var httpReq = new AspNetRequest(context, operationName); if (RunAsAsync()) { return(ProcessRequestAsync(httpReq, httpReq.Response, operationName)); } return(CreateProcessRequestTask(httpReq, httpReq.Response, operationName)); }
public AspNetContext(HttpContext httpContext) { // Assign properties _request = new AspNetRequest(httpContext.Request); _session = new AspNetSession(httpContext); _response = new AspNetResponse(httpContext.Response); }
private AspNetResponse ProcessRequest(AspNetRequest request) { var response = application.ProcessRequest(request); ExtractCookies(response); return(FollowAnyRedirect(response)); }
public void Uri_gets_QueryString_from_QueryString() { request = new AspNetRequest(GetRequest("GET", "/", "")); Assert.That(request.QueryString, Is.EqualTo("")); request = new AspNetRequest(GetRequest("GET", "/", "foo=bar")); Assert.That(request.QueryString, Is.EqualTo("foo=bar")); }
public void Uri_includes_query_strings_from_QueryString() { request = new AspNetRequest(GetRequest("GET", "/", "")); Assert.That(request.Uri, Is.EqualTo("/")); request = new AspNetRequest(GetRequest("GET", "/", "foo=bar")); Assert.That(request.Uri, Is.EqualTo("/?foo=bar")); }
public void Uri_gets_set_using_Request_Path() { request = new AspNetRequest(GetRequest("/")); Assert.That(request.Uri, Is.EqualTo("/")); request = new AspNetRequest(GetRequest("/foo/bar")); Assert.That(request.Uri, Is.EqualTo("/foo/bar")); }
public void Method_gets_set_using_Request_RequestType() { request = new AspNetRequest(GetRequest()); Assert.That(request.Method, Is.EqualTo("GET")); request = new AspNetRequest(GetRequest("POST", "/")); Assert.That(request.Method, Is.EqualTo("POST")); }
public void owin_server_port_gets_set_to_Request_Url_Port() { request = new AspNetRequest(GetRequest("http://localhost/")); Assert.That(request.Port, Is.EqualTo(80)); request = new AspNetRequest(GetRequest("http://localhost:1234/")); Assert.That(request.Port, Is.EqualTo(1234)); }
public void owin_url_scheme_gets_set_using_scheme_seen_in_Request_Url_Scheme() { request = new AspNetRequest(GetRequest("http://localhost/")); Assert.That(request.Scheme, Is.EqualTo("http")); request = new AspNetRequest(GetRequest("https://localhost/")); Assert.That(request.Scheme, Is.EqualTo("https")); }
public void owin_server_name_gets_set_to_Request_Url_Host() { request = new AspNetRequest(GetRequest("http://localhost/")); Assert.That(request.Host, Is.EqualTo("localhost")); request = new AspNetRequest(GetRequest("http://google.com/")); Assert.That(request.Host, Is.EqualTo("google.com")); }
public AspNetContext(HttpContext httpContext, string resourcePath = null) { // Assign properties _request = new AspNetRequest(httpContext.Request); _request.ResourcePath = new Uri(resourcePath, UriKind.RelativeOrAbsolute); _session = new AspNetSession(httpContext); _response = new AspNetResponse(httpContext.Response); }
public void owin_base_path_gets_set_to_Request_ApplicationPath() { HttpRequest native = GetRequest(); Assert.That(native.ApplicationPath, Is.Null); // it returns null and we can't change it request = new AspNetRequest(native); Assert.That(request.BasePath, Is.EqualTo("")); }
public Task ProcessRequestAsync(HttpContextBase context) { #if V3 var httpContext = context.ApplicationInstance.Context; return CreateProcessRequestTask(new HttpRequestWrapper(httpContext.Request), new HttpResponseWrapper(httpContext.Response), httpContext.Request.GetOperationName()); #else var operationName = context.Request.GetOperationName(); var httpReq = new AspNetRequest(context, operationName); return CreateProcessRequestTask(httpReq, httpReq.Response, operationName); #endif }
public Task ProcessRequestAsync(HttpContextBase context) { #if V3 var httpContext = context.ApplicationInstance.Context; return(CreateProcessRequestTask(new HttpRequestWrapper(httpContext.Request), new HttpResponseWrapper(httpContext.Response), httpContext.Request.GetOperationName())); #else var operationName = context.Request.GetOperationName(); var httpReq = new AspNetRequest(context, operationName); return(CreateProcessRequestTask(httpReq, httpReq.Response, operationName)); #endif }
public virtual void ProcessRequest(HttpContextBase context) { var operationName = this.RequestName ?? context.Request.GetOperationName(); if (String.IsNullOrEmpty(operationName)) return; if (DefaultHandledRequest(context)) return; var httpReq = new AspNetRequest(context, operationName); ProcessRequest(httpReq, httpReq.Response, operationName); }
private AspNetResponse FollowAnyRedirect(AspNetResponse response) { if (response.Status == 302 || response.Status == 301) { var location = response.Headers.First(x => x.Key == "Location").Value; var locationUri = new Uri(location, UriKind.RelativeOrAbsolute); var url = locationUri.IsAbsoluteUri ? locationUri.PathAndQuery : location; var request = new AspNetRequest(url, null, null, "GET", CreateRequestHeaders(new WebHeaderCollection()), null); return(ProcessRequest(request)); } return(response); }
public void owin_remote_endpoint_gets_set_using_Request_UserHostAddress_and_Port() { HttpRequest native = GetRequest(); // unfortunately, we can't set this :/ Assert.That(native.UserHostAddress, Is.Null); // if it's null, we'll do 0.0.0.0:80 ... cause, why not? request = new AspNetRequest(native); Assert.That(request.IPEndPoint.ToString(), Is.EqualTo("0.0.0.0:80")); // if we change the port, it should change the port in the end point request = new AspNetRequest(GetRequest("http://localhost:1234/foo")); Assert.That(request.IPEndPoint.ToString(), Is.EqualTo("0.0.0.0:1234")); }
public virtual Task ProcessRequestAsync(HttpContextBase context) { var operationName = this.RequestName ?? context.Request.GetOperationName(); if (String.IsNullOrEmpty(operationName)) return EmptyTask; if (DefaultHandledRequest(context)) return EmptyTask; var httpReq = new AspNetRequest(context, operationName); if (RunAsAsync()) return ProcessRequestAsync(httpReq, httpReq.Response, operationName); return new Task(() => ProcessRequest(httpReq, httpReq.Response, operationName)); }
public virtual Task ProcessRequestAsync(HttpContextBase context) { var operationName = this.RequestName ?? context.Request.GetOperationName(); RememberLastRequestInfo(operationName, context.Request.PathInfo); if (String.IsNullOrEmpty(operationName)) return EmptyTask; if (DefaultHandledRequest(context)) return EmptyTask; var httpReq = new AspNetRequest(context, operationName); if (RunAsAsync()) return ProcessRequestAsync(httpReq, httpReq.Response, operationName); return CreateProcessRequestTask(httpReq, httpReq.Response, operationName); }
public virtual void ProcessRequest(HttpContextBase context) { var operationName = this.RequestName ?? context.Request.GetOperationName(); if (string.IsNullOrEmpty(operationName)) { return; } if (DefaultHandledRequest(context)) { return; } var httpReq = new AspNetRequest(context, operationName); ProcessRequest(httpReq, httpReq.Response, operationName); }
public void read_values_from_the_response() { var request = new AspNetRequest { Headers = new Header[] { new Header("x_a", "1"), new Header("x_b", "2") }, StatusCode = 201, StatusDescription = "Weird" }; var response = TestApplication.Endpoints.PostJson(request).ReadAsJson <AspNetResponse>(); response.Description.ShouldEqual(request.StatusDescription); response.StatusCode.ShouldEqual(request.StatusCode); request.Headers.Each(x => { response.ResponseHeaders.ShouldContain(x); }); }
// Entry point for ASP.NET public IHttpHandler GetHandler(HttpContext ctx, string requestType, string url, string pathTranslated) { var context = ctx.Request.RequestContext.HttpContext; var appHost = HostContext.AppHost; DebugLastHandlerArgs = requestType + "|" + url + "|" + pathTranslated; var httpReq = new AspNetRequest(context, pathTranslated); foreach (var rawHttpHandler in appHost.RawHttpHandlers) { var reqInfo = rawHttpHandler(httpReq); if (reqInfo != null) { return(reqInfo); } } var mode = appHost.Config.ServiceStackHandlerFactoryPath; var pathInfo = context.Request.GetPathInfo(); //WebDev Server auto requests '/default.aspx' so recorrect path to different default document if (mode == null && (url == "/default.aspx" || url == "/Default.aspx")) { pathInfo = "/"; } //Default Request / if (string.IsNullOrEmpty(pathInfo) || pathInfo == "/") { //Exception calling context.Request.Url on Apache+mod_mono if (ApplicationBaseUrl == null) { var absoluteUrl = Env.IsMono ? url.ToParentPath() : context.Request.GetApplicationUrl(); SetApplicationBaseUrl(absoluteUrl); } //e.g. CatchAllHandler to Process Markdown files var catchAllHandler = GetCatchAllHandlerIfAny(httpReq.HttpMethod, pathInfo, httpReq.GetPhysicalPath()); if (catchAllHandler != null) { return(catchAllHandler); } if (mode == null) { return(DefaultHttpHandler); } if (DefaultRootFileName != null) { return(StaticFileHandler); } return(NonRootModeDefaultHttpHandler); } if (mode != null && pathInfo.EndsWith(mode)) { var requestPath = context.Request.Path.ToLower(); if (requestPath == "/" + mode || requestPath == mode || requestPath == mode + "/") { var pathProvider = appHost.VirtualPathProvider; var defaultDoc = pathProvider.CombineVirtualPath(context.Request.PhysicalPath, DefaultRootFileName ?? ""); if (context.Request.PhysicalPath != WebHostPhysicalPath || !pathProvider.FileExists(defaultDoc)) { return(new IndexPageHttpHandler()); } } var okToServe = ShouldAllow(context.Request.FilePath); return(okToServe ? DefaultHttpHandler : ForbiddenHttpHandler); } return(GetHandlerForPathInfo( context.Request.HttpMethod, pathInfo, context.Request.FilePath, pathTranslated) ?? NotFoundHttpHandler); }
public void Handle(AspNetRequest request, AspNetResponse response) { var handleScope = IronRubyEngine.Engine.CreateScope(); //handle_scope.SetVariable("__request", request); handleScope.SetVariable("__response", response); // The environment must be an true instance of Hash (no subclassing // allowed) that includes CGI-like headers. The application is free // to modify the environment. The environment is required to // include these variables (adopted from PEP333), except when // they’d be empty, but see below. var env = new Hash(IronRubyEngine.Context); // REQUEST_METHOD: The HTTP request method, such as “GET” or // “POST”. This cannot ever be an empty string, and so is always // required. // The REQUEST_METHOD must be a valid token. SetEnv(env, "REQUEST_METHOD", request.OrigionalRequest.RequestType); // SCRIPT_NAME: The initial portion of the request URL’s “path” // that corresponds to the application object, so that the // application knows its virtual “location”. This may be an empty // string, if the application corresponds to the “root” of the // server. // The SCRIPT_NAME, if non-empty, must start with / string scriptName = request.OrigionalRequest.ApplicationPath; if (scriptName.Length > 0 && !scriptName.StartsWith("/")) { scriptName = "/" + scriptName; } // SCRIPT_NAME never should be /, but instead be empty. if (scriptName == "/") { scriptName = string.Empty; } SetEnv(env, "SCRIPT_NAME", scriptName); // PATH_INFO: The remainder of the request URL’s “path”, // designating the virtual “location” of the request’s target // within the application. This may be an empty string, if the // request URL targets the application root and does not have a // trailing slash. This value may be percent-encoded when I // originating from a URL. // The PATH_INFO, if non-empty, must start with / string pathInfo = request.OrigionalRequest.Path.Substring( request.OrigionalRequest.Path.IndexOf(request.OrigionalRequest.ApplicationPath) + request.OrigionalRequest.ApplicationPath.Length ); if (pathInfo.Length > 0 && !pathInfo.StartsWith("/")) { pathInfo = "/" + pathInfo; } // PATH_INFO should be / if SCRIPT_NAME is empty. if (pathInfo.Length == 0) { pathInfo = "/"; } SetEnv(env, "PATH_INFO", pathInfo); // One of SCRIPT_NAME or PATH_INFO must be set. // TODO // QUERY_STRING: The portion of the request URL that follows the // ?, if any. May be empty, but is always required! SetEnv(env, "QUERY_STRING", request.QueryString ?? ""); // SERVER_NAME, SERVER_PORT: When combined with SCRIPT_NAME and // PATH_INFO, these variables can be used to complete the URL. // Note, however, that HTTP_HOST, if present, should be used in // preference to SERVER_NAME for reconstructing the request URL. // SERVER_NAME and SERVER_PORT can never be empty strings, and so // are always required. SetEnv(env, "SERVER_NAME", request.OrigionalRequest.Url.Host); SetEnv(env, "SERVER_PORT", request.OrigionalRequest.Url.Port.ToString()); // HTTP_ Variables: Variables corresponding to the client-supplied // HTTP request headers (i.e., variables whose names begin with // HTTP_). The presence or absence of these variables should // correspond with the presence or absence of the appropriate // HTTP header in the request. // The CONTENT_LENGTH, if given, must consist of digits only. foreach (var pair in request.Headers) { var prepend = "HTTP_"; if (pair.Key.ToString() == "Content-Length" || pair.Key.ToString() == "Content-Type") { prepend = ""; } SetEnv(env, prepend + pair.Key.ToString().ToUpper().Replace("-", "_"), pair.Value.ToString()); } // In addition to this, the Rack environment must include these // Rack-specific variables: // // rack.version: The Array (for example: [1, 0], representing // this version of Rack. SetEnv(env, "rack.version", App.ActualRackVersion); // rack.url_scheme: http or https, depending on the request URL. SetEnv(env, "rack.url_scheme", request.OrigionalRequest.IsSecureConnection ? "https" : "http"); // rack.input: The input stream is an IO-like object which contains // the raw HTTP POST data. If it is a file then it must be opened // in binary mode. The input stream must respond to gets, each, // read and rewind. // // gets must be called without arguments and return a string, or // nil on EOF. // read behaves like IO#read. Its signature is // read([length, [buffer]]). If given, length must be an // non-negative Integer (>= 0) or nil, and buffer must be a String // and may not be nil. If length is given and not nil, then this // method reads at most length bytes from the input stream. If // length is not given or nil, then this method reads all data // until EOF. When EOF is reached, this method returns nil if // length is given and not nil, or “” if length is not given or // is nil. If buffer is given, then the read data will be placed // into buffer instead of a newly created String object. // each must be called without arguments and only yield Strings. // rewind must be called without arguments. It rewinds the input // stream back to the beginning. It must not raise Errno::ESPIPE: // that is, it may not be a pipe or a socket. Therefore, handler // developers must buffer the input data into some rewindable // object if the underlying input stream is not rewindable. // close must never be called on the input stream. SetEnv(env, "rack.input", request.Body); // rack.errors: The error stream must respond to puts, write and flush. // // puts must be called with a single argument that responds to to_s. // write must be called with a single argument that is a String. // flush must be called without arguments and must be called in // order to make the error appear for sure. // close must never be called on the error stream. SetEnv(env, "rack.errors", IronRubyEngine.Context.StandardErrorOutput); // rack.multithread: true if the application object may be simultaneously // invoked by another thread in the same process, false otherwise. SetEnv(env, "rack.multithread", true); // rack.multiprocess: true if an equivalent application object may be // simultaneously invoked by another process, false otherwise. SetEnv(env, "rack.multiprocess", false); // rack.run_once: true if the server expects (but does not guarantee!) // that the application will only be invoked this one time during the // life of its containing process. Normally, this will only be true for // a server based on CGI (or something similar). SetEnv(env, "rack.run_once", false); // Additional environment specifications have approved to standardized // middleware APIs. None of these are required to be implemented by the server. // // rack.session: A hash like interface for storing request session data. // The store must implement: // store(key, value) (aliased as []=); // fetch(key, default = nil) (aliased as []); // delete(key); // clear; // noop // The server or the application can store their own data in the // environment, too. The keys must contain at least one dot, and // should be prefixed uniquely. The prefix rack. is reserved for // use with the Rack core distribution and other accepted // specifications and must not be used otherwise. // noop // The environment // must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH // (use the versions without HTTP_). The CGI keys (named without a period) // must have String values. RemoveEnv(env, "HTTP_CONTENT_LENGTH"); RemoveEnv(env, "HTTP_CONTENT_TYPE"); // Set other vars based on what WEBrick sets: SetEnv(env, "REMOTE_HOST", request.OrigionalRequest.Url.Host); SetEnv(env, "SERVER_PROTOCOL", request.OrigionalRequest.Params["SERVER_PROTOCOL"]); SetEnv(env, "REQUEST_PATH", request.OrigionalRequest.Path); SetEnv(env, "SERVER_SOFTWARE", request.OrigionalRequest.Params["SERVER_SOFTWARE"]); SetEnv(env, "REMOTE_ADDR", request.OrigionalRequest.Url.AbsoluteUri); SetEnv(env, "HTTP_VERSION", request.OrigionalRequest.Params["SERVER_PROTOCOL"]); SetEnv(env, "REQUEST_URI", request.OrigionalRequest.Url.AbsoluteUri); SetEnv(env, "GATEWAY_INTERFACE", request.OrigionalRequest.Params["GATEWAY_INTERFACE"]); // A Rack application is an Ruby object (not a class) that responds // to call. It takes exactly one argument, the environment and // returns an Array of exactly three values: The status, the headers, // and the body. RubyArray ruby_response = App.Call(env); try { // The Response // ============ // The Status // ---------- // This is an HTTP status. When parsed as integer (to_i), it // must be greater than or equal to 100. response.Status = (int)ruby_response[0]; // The Headers // ----------- // The header must respond to each, and yield values of key and // value. The header keys must be Strings. The header must not // contain a Status key, contain keys with : or newlines in // their name, contain keys names that end in - or _, but only // contain keys that consist of letters, digits, _ or - and // start with a letter. The values of the header must be // Strings, consisting of lines (for multiple header values, // e.g. multiple Set-Cookie values) seperated by “n“. The lines // must not contain characters below 037. foreach (var header in ((Hash)ruby_response[1])) { foreach (var value in header.Value.ToString().Split('\n')) { response.AppendHeader(header.Key.ToString(), value.ToString()); } } // The Content-Type // ---------------- // There must be a Content-Type, except when the Status is 1xx, // 204 or 304, in which case there must be none given. // TODO // The Content-Length // ------------------ // There must not be a Content-Length header when the Status is // 1xx, 204 or 304. // TODO // The Body // -------- // The Body must respond to each and must only yield String // values. The Body itself should not be an instance of String, // as this will break in Ruby 1.9. If the Body responds to // close, it will be called after iteration. If the Body // responds to to_path, it must return a String identifying the // location of a file whose contents are identical to that // produced by calling each; this may be used by the server as // an alternative, possibly more efficient way to transport the // response. The Body commonly is an Array of Strings, the // application instance itself, or a File-like object. var body = ruby_response[2]; var each_block = (Func <IronRuby.Runtime.BlockParam, object, object, object>)((block, notUsed, part) => { response.Write(((MutableString)part).ToByteArray()); return(null); }); handleScope.SetVariable("__body", ruby_response[2]); handleScope.SetVariable("__each_block", Proc.CreateSimple(IronRubyEngine.Context, each_block)); IronRubyEngine.Execute("__body.each(&__each_block)", handleScope); } finally { var body = ruby_response[2]; if (IronRubyEngine.ExecuteMethod <bool>(body, "respond_to?", "close")) { IronRubyEngine.ExecuteMethod(body, "close"); } } }
public void owin_request_protocol_gets_set_to_HTTP_1_1() { request = new AspNetRequest(GetRequest()); Assert.That(request.Protocol, Is.EqualTo("HTTP/1.1")); // not sure if we can detect this - just use 1.1 }
public void Before() { request = null; }
public void Handle(AspNetRequest request, AspNetResponse response) { var handleScope = IronRubyEngine.Engine.CreateScope(); //handle_scope.SetVariable("__request", request); handleScope.SetVariable("__response", response); // The environment must be an true instance of Hash (no subclassing // allowed) that includes CGI-like headers. The application is free // to modify the environment. The environment is required to // include these variables (adopted from PEP333), except when // they’d be empty, but see below. var env = new Hash(IronRubyEngine.Context); // REQUEST_METHOD: The HTTP request method, such as “GET” or // “POST”. This cannot ever be an empty string, and so is always // required. // The REQUEST_METHOD must be a valid token. SetEnv(env, "REQUEST_METHOD", request.OrigionalRequest.RequestType); // SCRIPT_NAME: The initial portion of the request URL’s “path” // that corresponds to the application object, so that the // application knows its virtual “location”. This may be an empty // string, if the application corresponds to the “root” of the // server. // The SCRIPT_NAME, if non-empty, must start with / string scriptName = request.OrigionalRequest.ApplicationPath; if(scriptName.Length > 0 && !scriptName.StartsWith("/")) { scriptName = "/" + scriptName; } // SCRIPT_NAME never should be /, but instead be empty. if (scriptName == "/") scriptName = string.Empty; SetEnv(env, "SCRIPT_NAME", scriptName); // PATH_INFO: The remainder of the request URL’s “path”, // designating the virtual “location” of the request’s target // within the application. This may be an empty string, if the // request URL targets the application root and does not have a // trailing slash. This value may be percent-encoded when I // originating from a URL. // The PATH_INFO, if non-empty, must start with / string pathInfo = request.OrigionalRequest.Path.Substring( request.OrigionalRequest.Path.IndexOf(request.OrigionalRequest.ApplicationPath) + request.OrigionalRequest.ApplicationPath.Length ); if(pathInfo.Length > 0 && !pathInfo.StartsWith("/")) { pathInfo = "/" + pathInfo; } // PATH_INFO should be / if SCRIPT_NAME is empty. if(pathInfo.Length == 0) pathInfo = "/"; SetEnv(env, "PATH_INFO", pathInfo); // One of SCRIPT_NAME or PATH_INFO must be set. // TODO // QUERY_STRING: The portion of the request URL that follows the // ?, if any. May be empty, but is always required! SetEnv(env, "QUERY_STRING", request.QueryString ?? ""); // SERVER_NAME, SERVER_PORT: When combined with SCRIPT_NAME and // PATH_INFO, these variables can be used to complete the URL. // Note, however, that HTTP_HOST, if present, should be used in // preference to SERVER_NAME for reconstructing the request URL. // SERVER_NAME and SERVER_PORT can never be empty strings, and so // are always required. SetEnv(env, "SERVER_NAME", request.OrigionalRequest.Url.Host); SetEnv(env, "SERVER_PORT", request.OrigionalRequest.Url.Port.ToString()); // HTTP_ Variables: Variables corresponding to the client-supplied // HTTP request headers (i.e., variables whose names begin with // HTTP_). The presence or absence of these variables should // correspond with the presence or absence of the appropriate // HTTP header in the request. // The CONTENT_LENGTH, if given, must consist of digits only. foreach (var pair in request.Headers) { var prepend = "HTTP_"; if (pair.Key.ToString() == "Content-Length" || pair.Key.ToString() == "Content-Type") prepend = ""; SetEnv(env, prepend + pair.Key.ToString().ToUpper().Replace("-", "_"), pair.Value.ToString()); } // In addition to this, the Rack environment must include these // Rack-specific variables: // // rack.version: The Array (for example: [1, 0], representing // this version of Rack. SetEnv(env, "rack.version", App.ActualRackVersion); // rack.url_scheme: http or https, depending on the request URL. SetEnv(env, "rack.url_scheme", request.OrigionalRequest.IsSecureConnection ? "https" : "http"); // rack.input: The input stream is an IO-like object which contains // the raw HTTP POST data. If it is a file then it must be opened // in binary mode. The input stream must respond to gets, each, // read and rewind. // // gets must be called without arguments and return a string, or // nil on EOF. // read behaves like IO#read. Its signature is // read([length, [buffer]]). If given, length must be an // non-negative Integer (>= 0) or nil, and buffer must be a String // and may not be nil. If length is given and not nil, then this // method reads at most length bytes from the input stream. If // length is not given or nil, then this method reads all data // until EOF. When EOF is reached, this method returns nil if // length is given and not nil, or “” if length is not given or // is nil. If buffer is given, then the read data will be placed // into buffer instead of a newly created String object. // each must be called without arguments and only yield Strings. // rewind must be called without arguments. It rewinds the input // stream back to the beginning. It must not raise Errno::ESPIPE: // that is, it may not be a pipe or a socket. Therefore, handler // developers must buffer the input data into some rewindable // object if the underlying input stream is not rewindable. // close must never be called on the input stream. SetEnv(env, "rack.input", request.Body); // rack.errors: The error stream must respond to puts, write and flush. // // puts must be called with a single argument that responds to to_s. // write must be called with a single argument that is a String. // flush must be called without arguments and must be called in // order to make the error appear for sure. // close must never be called on the error stream. SetEnv(env, "rack.errors", IronRubyEngine.Context.StandardErrorOutput); // rack.multithread: true if the application object may be simultaneously // invoked by another thread in the same process, false otherwise. SetEnv(env, "rack.multithread", true); // rack.multiprocess: true if an equivalent application object may be // simultaneously invoked by another process, false otherwise. SetEnv(env, "rack.multiprocess", false); // rack.run_once: true if the server expects (but does not guarantee!) // that the application will only be invoked this one time during the // life of its containing process. Normally, this will only be true for // a server based on CGI (or something similar). SetEnv(env, "rack.run_once", false); // Additional environment specifications have approved to standardized // middleware APIs. None of these are required to be implemented by the server. // // rack.session: A hash like interface for storing request session data. // The store must implement: // store(key, value) (aliased as []=); // fetch(key, default = nil) (aliased as []); // delete(key); // clear; // noop // The server or the application can store their own data in the // environment, too. The keys must contain at least one dot, and // should be prefixed uniquely. The prefix rack. is reserved for // use with the Rack core distribution and other accepted // specifications and must not be used otherwise. // noop // The environment // must not contain the keys HTTP_CONTENT_TYPE or HTTP_CONTENT_LENGTH // (use the versions without HTTP_). The CGI keys (named without a period) // must have String values. RemoveEnv(env, "HTTP_CONTENT_LENGTH"); RemoveEnv(env, "HTTP_CONTENT_TYPE"); // Set other vars based on what WEBrick sets: SetEnv(env, "REMOTE_HOST", request.OrigionalRequest.Url.Host); SetEnv(env, "SERVER_PROTOCOL", request.OrigionalRequest.Params["SERVER_PROTOCOL"]); SetEnv(env, "REQUEST_PATH", request.OrigionalRequest.Path); SetEnv(env, "SERVER_SOFTWARE", request.OrigionalRequest.Params["SERVER_SOFTWARE"]); SetEnv(env, "REMOTE_ADDR", request.OrigionalRequest.Url.AbsoluteUri); SetEnv(env, "HTTP_VERSION", request.OrigionalRequest.Params["SERVER_PROTOCOL"]); SetEnv(env, "REQUEST_URI", request.OrigionalRequest.Url.AbsoluteUri); SetEnv(env, "GATEWAY_INTERFACE", request.OrigionalRequest.Params["GATEWAY_INTERFACE"]); // A Rack application is an Ruby object (not a class) that responds // to call. It takes exactly one argument, the environment and // returns an Array of exactly three values: The status, the headers, // and the body. RubyArray ruby_response = App.Call(env); try { // The Response // ============ // The Status // ---------- // This is an HTTP status. When parsed as integer (to_i), it // must be greater than or equal to 100. response.Status = (int)ruby_response[0]; // The Headers // ----------- // The header must respond to each, and yield values of key and // value. The header keys must be Strings. The header must not // contain a Status key, contain keys with : or newlines in // their name, contain keys names that end in - or _, but only // contain keys that consist of letters, digits, _ or - and // start with a letter. The values of the header must be // Strings, consisting of lines (for multiple header values, // e.g. multiple Set-Cookie values) seperated by “n“. The lines // must not contain characters below 037. foreach (var header in ((Hash)ruby_response[1])) { foreach (var value in header.Value.ToString().Split('\n')) { response.AppendHeader(header.Key.ToString(), value.ToString()); } } // The Content-Type // ---------------- // There must be a Content-Type, except when the Status is 1xx, // 204 or 304, in which case there must be none given. // TODO // The Content-Length // ------------------ // There must not be a Content-Length header when the Status is // 1xx, 204 or 304. // TODO // The Body // -------- // The Body must respond to each and must only yield String // values. The Body itself should not be an instance of String, // as this will break in Ruby 1.9. If the Body responds to // close, it will be called after iteration. If the Body // responds to to_path, it must return a String identifying the // location of a file whose contents are identical to that // produced by calling each; this may be used by the server as // an alternative, possibly more efficient way to transport the // response. The Body commonly is an Array of Strings, the // application instance itself, or a File-like object. var body = ruby_response[2]; var each_block = (Func<IronRuby.Runtime.BlockParam, object, object, object>)((block, notUsed, part) => { response.Write(((MutableString)part).ToByteArray()); return null; }); handleScope.SetVariable("__body", ruby_response[2]); handleScope.SetVariable("__each_block", Proc.CreateSimple(IronRubyEngine.Context, each_block)); IronRubyEngine.Execute("__body.each(&__each_block)", handleScope); } finally { var body = ruby_response[2]; if (IronRubyEngine.ExecuteMethod<bool>(body, "respond_to?", "close")) { IronRubyEngine.ExecuteMethod(body, "close"); } } }
// Entry point for ASP.NET public IHttpHandler GetHandler(HttpContext ctx, string requestType, string url, string pathTranslated) { var context = ctx.Request.RequestContext.HttpContext; var appHost = HostContext.AppHost; DebugLastHandlerArgs = requestType + "|" + url + "|" + pathTranslated; //var httpReq = new AspNetRequest(context, url); var httpReq = new AspNetRequest(context, url.SanitizedVirtualPath()); foreach (var rawHttpHandler in appHost.RawHttpHandlers) { var reqInfo = rawHttpHandler(httpReq); if (reqInfo != null) { return(reqInfo); } } var mode = appHost.Config.HandlerFactoryPath; var pathInfo = context.Request.GetPathInfo(); //WebDev Server auto requests '/default.aspx' so recorrect path to different default document if (mode == null && (url == "/default.aspx" || url == "/Default.aspx")) { pathInfo = "/"; } //Default Request / if (string.IsNullOrEmpty(pathInfo) || pathInfo == "/") { //If the fallback route can handle it, let it if (appHost.Config.FallbackRestPath != null) { string contentType; var sanitizedPath = RestHandler.GetSanitizedPathInfo(pathInfo, out contentType); var restPath = appHost.Config.FallbackRestPath(context.Request.HttpMethod, sanitizedPath, pathTranslated); if (restPath != null) { return(new RestHandler { RestPath = restPath, RequestName = restPath.RequestType.GetOperationName(), ResponseContentType = contentType }); } } //Exception calling context.Request.Url on Apache+mod_mono var absoluteUrl = Env.IsMono ? url.ToParentPath() : context.Request.GetApplicationUrl(); SetApplicationBaseUrl(absoluteUrl); //e.g. CatchAllHandler to Process Markdown files var catchAllHandler = GetCatchAllHandlerIfAny(httpReq.HttpMethod, pathInfo, httpReq.GetPhysicalPath()); if (catchAllHandler != null) { return(catchAllHandler); } if (mode == null) { return(DefaultHttpHandler); } if (DefaultRootFileName != null) { return(StaticFilesHandler); } return(NonRootModeDefaultHttpHandler); } if (mode != null && pathInfo.EndsWith("/" + mode)) { return(ReturnDefaultHandler(httpReq)); } return(GetHandlerForPathInfo( httpReq.HttpMethod, pathInfo, context.Request.FilePath, pathTranslated) ?? NotFoundHttpHandler); }
// Entry point for ASP.NET public IHttpHandler GetHandler(HttpContext ctx, string requestType, string url, string pathTranslated) { var context = ctx.Request.RequestContext.HttpContext; var appHost = HostContext.AppHost; DebugLastHandlerArgs = requestType + "|" + url + "|" + pathTranslated; //var httpReq = new AspNetRequest(context, url); var httpReq = new AspNetRequest(context, url.SanitizedVirtualPath()); foreach (var rawHttpHandler in appHost.RawHttpHandlers) { var reqInfo = rawHttpHandler(httpReq); if (reqInfo != null) return reqInfo; } var mode = appHost.Config.HandlerFactoryPath; var pathInfo = context.Request.GetPathInfo(); //WebDev Server auto requests '/default.aspx' so recorrect path to different default document if (mode == null && (url == "/default.aspx" || url == "/Default.aspx")) pathInfo = "/"; //Default Request / if (string.IsNullOrEmpty(pathInfo) || pathInfo == "/") { //If the fallback route can handle it, let it if (appHost.Config.FallbackRestPath != null) { string contentType; var sanitizedPath = RestHandler.GetSanitizedPathInfo(pathInfo, out contentType); var restPath = appHost.Config.FallbackRestPath(context.Request.HttpMethod, sanitizedPath, pathTranslated); if (restPath != null) { return new RestHandler { RestPath = restPath, RequestName = restPath.RequestType.GetOperationName(), ResponseContentType = contentType }; } } //Exception calling context.Request.Url on Apache+mod_mono var absoluteUrl = Env.IsMono ? url.ToParentPath() : context.Request.GetApplicationUrl(); SetApplicationBaseUrl(absoluteUrl); //e.g. CatchAllHandler to Process Markdown files var catchAllHandler = GetCatchAllHandlerIfAny(httpReq.HttpMethod, pathInfo, httpReq.GetPhysicalPath()); if (catchAllHandler != null) return catchAllHandler; if (mode == null) return DefaultHttpHandler; if (DefaultRootFileName != null) return StaticFilesHandler; return NonRootModeDefaultHttpHandler; } if (mode != null && pathInfo.EndsWith("/" + mode)) { return ReturnDefaultHandler(httpReq); } return GetHandlerForPathInfo( httpReq.HttpMethod, pathInfo, context.Request.FilePath, pathTranslated) ?? NotFoundHttpHandler; }
// Entry point for ASP.NET public IHttpHandler GetHandler(HttpContext ctx, string requestType, string url, string pathTranslated) { var context = ctx.Request.RequestContext.HttpContext; var appHost = HostContext.AppHost; DebugLastHandlerArgs = requestType + "|" + url + "|" + pathTranslated; var httpReq = new AspNetRequest(context, pathTranslated); foreach (var rawHttpHandler in appHost.RawHttpHandlers) { var reqInfo = rawHttpHandler(httpReq); if (reqInfo != null) return reqInfo; } var mode = appHost.Config.ServiceStackHandlerFactoryPath; var pathInfo = context.Request.GetPathInfo(); //WebDev Server auto requests '/default.aspx' so recorrect path to different default document if (mode == null && (url == "/default.aspx" || url == "/Default.aspx")) pathInfo = "/"; //Default Request / if (string.IsNullOrEmpty(pathInfo) || pathInfo == "/") { //Exception calling context.Request.Url on Apache+mod_mono if (ApplicationBaseUrl == null) { var absoluteUrl = Env.IsMono ? url.ToParentPath() : context.Request.GetApplicationUrl(); SetApplicationBaseUrl(absoluteUrl); } //e.g. CatchAllHandler to Process Markdown files var catchAllHandler = GetCatchAllHandlerIfAny(httpReq.HttpMethod, pathInfo, httpReq.GetPhysicalPath()); if (catchAllHandler != null) return catchAllHandler; if (mode == null) return DefaultHttpHandler; if (DefaultRootFileName != null) return StaticFileHandler; return NonRootModeDefaultHttpHandler; } if (mode != null && pathInfo.EndsWith(mode)) { var requestPath = context.Request.Path.ToLower(); if (requestPath == "/" + mode || requestPath == mode || requestPath == mode + "/") { var pathProvider = appHost.VirtualPathProvider; var defaultDoc = pathProvider.CombineVirtualPath(context.Request.PhysicalPath, DefaultRootFileName ?? ""); if (context.Request.PhysicalPath != WebHostPhysicalPath || !pathProvider.FileExists(defaultDoc)) { return new IndexPageHttpHandler(); } } var okToServe = ShouldAllow(context.Request.FilePath); return okToServe ? DefaultHttpHandler : ForbiddenHttpHandler; } return GetHandlerForPathInfo( context.Request.HttpMethod, pathInfo, context.Request.FilePath, pathTranslated) ?? NotFoundHttpHandler; }
public override void ProcessRequest(HttpContext context) { var request = context.Request; var response = context.Response; var httpReq = new AspNetRequest("NotFoundHttpHandler", request); if (!request.IsLocal) { ProcessRequestAsync(httpReq, new AspNetResponse(response), null); return; } Log.ErrorFormat("{0} Request not found: {1}", request.UserHostAddress, request.RawUrl); var sb = new StringBuilder(); sb.AppendLine("Handler for Request not found: \n\n"); sb.AppendLine("Request.ApplicationPath: " + request.ApplicationPath); sb.AppendLine("Request.CurrentExecutionFilePath: " + request.CurrentExecutionFilePath); sb.AppendLine("Request.FilePath: " + request.FilePath); sb.AppendLine("Request.HttpMethod: " + request.HttpMethod); sb.AppendLine("Request.MapPath('~'): " + request.MapPath("~")); sb.AppendLine("Request.Path: " + request.Path); sb.AppendLine("Request.PathInfo: " + request.PathInfo); sb.AppendLine("Request.ResolvedPathInfo: " + httpReq.PathInfo); sb.AppendLine("Request.PhysicalPath: " + request.PhysicalPath); sb.AppendLine("Request.PhysicalApplicationPath: " + request.PhysicalApplicationPath); sb.AppendLine("Request.QueryString: " + request.QueryString); sb.AppendLine("Request.RawUrl: " + request.RawUrl); try { sb.AppendLine("Request.Url.AbsoluteUri: " + request.Url.AbsoluteUri); sb.AppendLine("Request.Url.AbsolutePath: " + request.Url.AbsolutePath); sb.AppendLine("Request.Url.Fragment: " + request.Url.Fragment); sb.AppendLine("Request.Url.Host: " + request.Url.Host); sb.AppendLine("Request.Url.LocalPath: " + request.Url.LocalPath); sb.AppendLine("Request.Url.Port: " + request.Url.Port); sb.AppendLine("Request.Url.Query: " + request.Url.Query); sb.AppendLine("Request.Url.Scheme: " + request.Url.Scheme); sb.AppendLine("Request.Url.Segments: " + request.Url.Segments); } catch (Exception ex) { sb.AppendLine("Request.Url ERROR: " + ex.Message); } if (IsIntegratedPipeline.HasValue) sb.AppendLine("App.IsIntegratedPipeline: " + IsIntegratedPipeline); if (!WebHostPhysicalPath.IsNullOrEmpty()) sb.AppendLine("App.WebHostPhysicalPath: " + WebHostPhysicalPath); if (!WebHostRootFileNames.IsEmpty()) sb.AppendLine("App.WebHostRootFileNames: " + TypeSerializer.SerializeToString(WebHostRootFileNames)); if (!ApplicationBaseUrl.IsNullOrEmpty()) sb.AppendLine("App.ApplicationBaseUrl: " + ApplicationBaseUrl); if (!DefaultRootFileName.IsNullOrEmpty()) sb.AppendLine("App.DefaultRootFileName: " + DefaultRootFileName); if (!DefaultHandler.IsNullOrEmpty()) sb.AppendLine("App.DefaultHandler: " + DefaultHandler); if (!HttpHandlerFactory.DebugLastHandlerArgs.IsNullOrEmpty()) sb.AppendLine("App.DebugLastHandlerArgs: " + HttpHandlerFactory.DebugLastHandlerArgs); response.ContentType = "text/plain"; response.StatusCode = 404; response.EndHttpHandlerRequest(skipClose:true, afterBody: r => r.Write(sb.ToString())); }
public HttpPlasmaResponse Post(string url, string queryString = "", byte[] body = null, WebHeaderCollection headers = null) { var request = new AspNetRequest(url, null, queryString, "POST", CreateRequestHeaders(headers), body); return(new HttpPlasmaResponse(ProcessRequest(request))); }