public void RegisterWebservice(string path, Webservice webservice) { lock (server) { if (server.IsListening) { throw new InvalidOperationException("Can not add a prefix to a running server"); } if (!path.EndsWith("/")) { throw new ArgumentException("path should end with /"); } // Register into route processing services.Add(path, webservice); } }
internal void DispatchWebservice(HttpListenerContext context) { // Resolve to method Match match = routingRegex.Match(context.Request.Url.AbsolutePath); Webservice service = ResolveWebservice(match); MethodInfo method = null; if (service != null) { method = service.ResolveMethod(match); } if (service == null || method == null) { context.Response.StatusCode = 404; context.Response.StatusDescription = "Service not found"; } else { // TODO: Parse POST then GET params? // TODO: Allow variables to be tagged with resolution order // void foo(@WebVar('POST') int x) object[] args = new object[method.GetParameters().Length]; foreach (var param in method.GetParameters()) { if (param.ParameterType == typeof(HttpListenerContext)) { args[param.Position] = context; } else if (param.ParameterType == typeof(HttpListenerRequest)) { args[param.Position] = context.Request; } else if (param.ParameterType == typeof(HttpListenerResponse)) { args[param.Position] = context.Response; } else { // // Pull argument from URI // Group group = match.Groups[Webservice.WebArgumentGroupName(param.Name)]; // If the assertion below fails, check the routing regex. Debug.Assert(group.Success && Webservice.ValidParameterTypes.Keys.Contains(param.ParameterType)); string argString = group.Value; object argValue = null; if (!group.Success) { throw new InvalidOperationException("Programmer Error: URL group match was not successful"); } else if (param.ParameterType == typeof(string)) { argValue = argString; } else if (Webservice.ValidParameterTypes.Keys.Contains(param.ParameterType)) { object[] temp = { argString }; argValue = param.ParameterType.InvokeMember("Parse", BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, null, null, temp); } else { throw new InvalidOperationException(string.Format("Programmer Error: Type {0} is not a supported WebArgument type")); } args[param.Position] = argValue; } } object returnValue = method.Invoke(service, args); if (context.Response.StatusCode == (int)HttpStatusCode.OK && returnValue != null) { Encoding encoding = context.Response.ContentEncoding; if (encoding == null) { context.Response.ContentEncoding = encoding = Encoding.UTF8; } byte[] buffer = null; if (method.ReturnType == typeof(string)) { buffer = encoding.GetBytes((string)returnValue); } if (buffer != null) { context.Response.OutputStream.Write(buffer, 0, buffer.Length); } else { context.Response.StatusCode = (int)HttpStatusCode.InternalServerError; context.Response.StatusDescription = "Invalid Return Type"; } } } context.Response.Close(); }
internal static string WebserviceGroupName(Webservice service) { return(String.Format("service_{0}", service.GetHashCode())); }
internal static string WebserviceGroupName(Webservice service) { return String.Format("service_{0}", service.GetHashCode()); }