public Method FindMethodByName(string name) { // // First make a quick, case-sensitive look-up. // int i = InvariantStringArray.BinarySearch(_methodNames, name); if (i >= 0) { return(_sortedMethods[i]); } // // Failing, use a slower case-insensitive look-up. // TODO: Consider speeding up FindMethodByName for case-insensitive look-ups. // foreach (Method method in _methods) { if (CaselessString.Equals(method.Name, name)) { return(method); } } return(null); }
protected virtual object InferFeature() { HttpRequest request = Context.Request; string verb = request.RequestType; if (CaselessString.Equals(verb, "GET") || CaselessString.Equals(verb, "HEAD")) { // // If there is path tail then it indicates a GET-safe RPC. // if (request.PathInfo.Length > 1) { return(GetFeatureByName("getrpc")); } // // Otherwise, get the feature name from anonymous query // string parameter. // return(GetFeatureByName(Mask.EmptyString(request.QueryString[null], "help"))); } else if (CaselessString.Equals(verb, "POST")) { // // POST means RPC. // return(GetFeatureByName("rpc")); } return(null); }
protected override void ProcessRequest() { if (!CaselessString.Equals(Request.RequestType, "POST")) { throw new JsonRpcException(string.Format("HTTP {0} is not supported for RPC execution. Use HTTP POST only.", Request.RequestType)); } // // Sets the "Cache-Control" header value to "no-cache". // NOTE: It does not send the common HTTP 1.0 request directive // "Pragma" with the value "no-cache". // Response.Cache.SetCacheability(HttpCacheability.NoCache); // // Response will be plain text, though it would have been nice to // be more specific, like text/json. // Response.ContentType = "application/json"; // // Delegate rest of the work to JsonRpcServer. // JsonRpcDispatcher dispatcher = JsonRpcDispatcherFactory.CreateDispatcher(Service); using (new JsonRpcDispatchScope(dispatcher, Context)) using (TextReader reader = GetRequestReader()) dispatcher.Process(reader, Response.Output); }
private static object ReadParameters(Method method, JsonReader reader, JsonImportHandler importer) { Debug.Assert(method != null); Debug.Assert(reader != null); Debug.Assert(importer != null); reader.MoveToContent(); Parameter[] parameters = method.GetParameters(); if (reader.TokenClass == JsonTokenClass.Array) { reader.Read(); ArrayList argList = new ArrayList(parameters.Length); for (int i = 0; i < parameters.Length && reader.TokenClass != JsonTokenClass.EndArray; i++) { argList.Add(importer(parameters[i].ParameterType, reader)); } reader.StepOut(); return(argList.ToArray()); } else if (reader.TokenClass == JsonTokenClass.Object) { reader.Read(); JsonObject argByName = new JsonObject(); while (reader.TokenClass != JsonTokenClass.EndObject) { // TODO: Imporve this lookup. // FIXME: Does not work when argument is positional. Type parameterType = AnyType.Value; string name = reader.ReadMember(); foreach (Parameter parameter in parameters) { if (CaselessString.Equals(parameter.Name, name)) { parameterType = parameter.ParameterType; break; } } argByName.Put(name, importer(parameterType, reader)); } reader.Read(); return(argByName); } else { return(importer(AnyType.Value, reader)); } }
private TextReader GetRequestReader() { string contentType = Request.ContentType.Split(';')[0]; if (CaselessString.Equals(contentType, "application/x-www-form-urlencoded")) { string request = Request.Form.Count == 1 ? Request.Form[0] : Request.Form["JSON-RPC"]; return(new StringReader(request)); } else { return(new StreamReader(Request.InputStream, Request.ContentEncoding)); } }
protected override void ProcessRequest() { string httpMethod = Request.RequestType; if (!CaselessString.Equals(httpMethod, "GET") && !CaselessString.Equals(httpMethod, "HEAD")) { throw new JsonRpcException(string.Format("HTTP {0} is not supported for RPC execution. Use HTTP GET or HEAD only.", httpMethod)); } string callback = Mask.NullString(Request.QueryString["jsonp"]); bool padded = callback.Length > 0; // // The response type depends on whether JSONP (JSON with // Padding) is in effect or not. // Response.ContentType = padded ? "text/javascript" : "application/json"; // // Validate that the JSONP callback method conforms to the // allowed syntax. If not, issue a client-side exception // that will certainly help to bring problem to light, even if // a little too aggressively. // if (padded) { if (!_jsonpex.IsMatch(callback)) { Response.Write("throw new Error('Invalid JSONP callback parameter value.');"); Response.End(); } } // // Convert the query string into a call object. // StringWriter sw = new StringWriter(); JsonWriter writer = JsonText.CreateWriter(sw); writer.WriteStartObject(); writer.WriteMember("id"); writer.WriteNumber(-1); writer.WriteMember("method"); string methodName = Mask.NullString(Request.PathInfo); if (methodName.Length == 0) { writer.WriteNull(); } else { // // If the method name contains periods then we replace it // with dashes to mean the one and same thing. This is // done to provide dashes as an alternative to some periods // since some web servers may block requests (for security // reasons) if a path component of the URL contains more // than one period. // writer.WriteString(methodName.Substring(1).Replace('-', '.')); } writer.WriteMember("params"); NameValueCollection query = new NameValueCollection(Request.QueryString); query.Remove(string.Empty); JsonConvert.Export(Request.QueryString, writer); writer.WriteEndObject(); // // Delegate rest of the work to JsonRpcDispatcher. // JsonRpcDispatcher dispatcher = JsonRpcDispatcherFactory.CreateDispatcher(Service); using (new JsonRpcDispatchScope(dispatcher, Context)) { dispatcher.RequireIdempotency = true; if (padded) { // // For JSONP, see details here: // http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/ // Response.Write(callback); Response.Write('('); } dispatcher.Process(new StringReader(sw.ToString()), Response.Output, true); if (padded) { Response.Write(')'); } } }