Ejemplo n.º 1
0
        /// <summary>
        /// Register the given method with the specified url.
        /// </summary>
        /// <param name="url">The URL that will be used, relative to the service.api handler.</param>
        /// <param name="mi">The method to be invoked.</param>
        public void RegisterHandler(object instance, String method, String url, MethodInfo mi)
        {
            RestMethodInfo rmi;

            //
            // Create the root level if it does not exist.
            //
            if (registeredHandlers == null)
            {
                registeredHandlers = new ArrayList();
            }

            //
            // Create the REST state method information.
            //
            rmi = new RestMethodInfo(instance, method.ToUpper(), url, mi);

            //
            // Add the new method information into the list of handlers.
            //
            registeredHandlers.Add(rmi);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Process the web request.
        /// </summary>
        /// <param name="context">The context of this single web request.</param>
        public void ProcessRequest(HttpContext context)
        {
            UriTemplateMatch templateMatch = null;
            RestMethodInfo   rmi = null;
            ArrayList        finalParameters = null;
            Object           result = null, p;


            //
            // Initialization phase, register all handlers and then find a match.
            //
            try
            {
                //
                // Register all handlers.
                //
                RegisterHandlers();

                String baseUrl = context.Request.Url.Scheme + "://" + context.Request.Url.Authority + context.Request.FilePath;
                rmi = FindHandler(context.Request.HttpMethod.ToUpper(), new Uri(baseUrl), context.Request.Url, ref templateMatch);
                if (rmi == null)
                {
                    throw new MissingMethodException();
                }
            }
            catch (Exception e)
            {
                context.Response.Write(String.Format("Exception occurred at init: {0}", e.Message + e.StackTrace));

                return;
            }

            //
            // Parse out any parameters for the method call.
            //
            try
            {
                finalParameters = new ArrayList();

                //
                // Walk each parameter in the method and see if we can convert
                // one of the query variables to the proper type.
                //
                foreach (ParameterInfo pi in rmi.methodInfo.GetParameters())
                {
                    try
                    {
                        p = null;
                        if (typeof(Stream).IsAssignableFrom(pi.ParameterType))
                        {
                            p = context.Request.InputStream;
                        }
                        else if (templateMatch.BoundVariables.AllKeys.Contains(pi.Name.ToUpper()) == true)
                        {
                            p = templateMatch.BoundVariables[pi.Name.ToUpper()];
                            if (p != null)
                            {
                                if (typeof(List <String>).IsAssignableFrom(pi.ParameterType))
                                {
                                    p = p.ToString().Split(new char[1] {
                                        ','
                                    }).ToList <String>();
                                }
                                else
                                {
                                    p = Convert.ChangeType(p, pi.ParameterType);
                                }
                            }
                        }
                    }
                    catch
                    {
                        p = null;
                    }

                    finalParameters.Add(p);
                }
            }
            catch (Exception e)
            {
                context.Response.Write(String.Format("Exception occurred at parameter parse: {0} at {1}", e.Message, e.StackTrace));

                return;
            }

            //
            // Force the context to be anonymous, then authenticate if the user
            // is calling a non-anonymous method.
            //
            try
            {
                ArenaContext.Current.SetWebServiceProperties(ArenaContext.Current.CreatePrincipal(""), new Arena.Core.Person());
                if (rmi.uriTemplate.ToString() != "/version" &&
                    rmi.uriTemplate.ToString() != "/login" &&
                    rmi.uriTemplate.ToString() != "/help" &&
                    rmi.methodInfo.GetCustomAttributes(typeof(RestApiAnonymous), true).Length == 0)
                {
                    String PathAndQuery = context.Request.RawUrl.ToLower();

                    PathAndQuery = PathAndQuery.Substring(context.Request.FilePath.Length + 1);
                    AuthenticationManager.SetupSessionForRequest(context.Request.QueryString["api_session"], false);
                    AuthenticationManager.VerifySignature(context.Request.Url, PathAndQuery, context.Request.QueryString["api_session"]);
                }
            }
            catch (Exception e)
            {
                RESTException restEx = e as RESTException;

                if (restEx != null)
                {
                    result = new RestErrorMessage(restEx);
                }
                else
                {
                    result = new RestErrorMessage(System.Net.HttpStatusCode.InternalServerError, e.ToString(), string.Empty);
                }
            }

            //
            // Perform the actual method call.
            //
            if (result == null)
            {
                try
                {
                    //
                    // Set some default response information.
                    //
                    context.Response.ContentType = "application/xml; charset=utf-8";

                    if (TypeIsServiceContract(rmi.instance.GetType()) == true)
                    {
                        //
                        // Run the request inside of a operation context so response information
                        // can be set. This is a bit of a cheat, but it works.
                        //
                        WebChannelFactory <NoOp> factory = new WebChannelFactory <NoOp>(new Uri("http://localhost/"));
                        NoOp channel = factory.CreateChannel();
                        using (new OperationContextScope((IContextChannel)channel))
                        {
                            result = rmi.methodInfo.Invoke(rmi.instance, (object[])finalParameters.ToArray(typeof(object)));
                            if (WebOperationContext.Current.OutgoingResponse.ContentType != null)
                            {
                                context.Response.ContentType = WebOperationContext.Current.OutgoingResponse.ContentType;
                            }
                        }
                    }
                    else
                    {
                        //
                        // This is a standard method call, just call it.
                        //
                        result = rmi.methodInfo.Invoke(rmi.instance, (object[])finalParameters.ToArray(typeof(object)));
                    }
                }
                catch (Exception e)
                {
                    RESTException restEx;

                    if (e.InnerException != null)
                    {
                        e = e.InnerException;
                    }

                    restEx = e as RESTException;
                    if (restEx != null)
                    {
                        result = new RestErrorMessage(restEx);
                    }
                    else
                    {
                        result = new RestErrorMessage(System.Net.HttpStatusCode.InternalServerError, e.ToString(), string.Empty);
                    }
                }
            }

            //
            // Deal with the response that was generated.
            //
            try
            {
                if (result != null)
                {
                    //
                    // There is probably a better way to do this, but this is the best
                    // I can come up with. Somebody feel free to make this cleaner.
                    //
                    if (typeof(Stream).IsAssignableFrom(result.GetType()) == true)
                    {
                        Stream s = (Stream)result;
                        int    count;

                        //
                        // Response is a data stream, just copy it to the response
                        // stream.
                        //
                        do
                        {
                            byte[] buf = new byte[8192];

                            count = s.Read(buf, 0, 8192);
                            context.Response.BinaryWrite(buf);
                        } while (count > 0);
                    }
                    else if (typeof(Message).IsAssignableFrom(result.GetType()) == true)
                    {
                        Message       msg = (Message)result;
                        StringBuilder sb  = new StringBuilder();
                        StringWriter  sw  = new StringWriter(sb);
                        XmlTextWriter xtw = new XmlTextWriter(sw);

                        //
                        // Response is a Message object. Write it out as an XML
                        // stream.
                        //
                        msg.WriteMessage(xtw);
                        context.Response.Write(sb.ToString());
                    }
                    else
                    {
                        DataContractSerializer serializer = new DataContractSerializer(result.GetType());

                        //
                        // Otherwise, use the DataContractSerializer to convert the object into
                        // an XML stream.
                        //
                        serializer.WriteObject(context.Response.OutputStream, result);
                    }
                }
            }
            catch (Exception e)
            {
                context.Response.Write(String.Format("Exception sending response: {0}", e.Message));

                return;
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Register the given method with the specified url.
        /// </summary>
        /// <param name="url">The URL that will be used, relative to the service.api handler.</param>
        /// <param name="mi">The method to be invoked.</param>
        public void RegisterHandler(object instance, String method, String url, MethodInfo mi)
        {
            RestMethodInfo rmi;

            //
            // Create the root level if it does not exist.
            //
            if (registeredHandlers == null)
            {
                registeredHandlers = new ArrayList();
            }

            //
            // Create the REST state method information.
            //
            rmi = new RestMethodInfo(instance, method.ToUpper(), url, mi);

            //
            // Add the new method information into the list of handlers.
            //
            registeredHandlers.Add(rmi);
        }