Beispiel #1
0
        /// <summary>
        /// Serves embedded resources of specified assembly.
        /// </summary>
        /// <param name="app">The application to extend.</param>
        /// <param name="urlPrefix">The url prefix.</param>
        /// <param name="assembly">The assembly to get resources from.</param>
        /// <param name="resourcePrefix">The name prefix of embedded resource.</param>
        public static ExpressApplication Embedded(this ExpressApplication app,
                                                  string urlPrefix, Assembly assembly, string resourcePrefix)
        {
            if (app == null)
            {
                throw new ArgumentNullException("app");
            }
            if (assembly == null)
            {
                throw new ArgumentNullException("assembly");
            }

            assembly
            .GetManifestResourceNames()
            .Where(s => s.StartsWith(resourcePrefix))
            .ToList()
            .ForEach(name =>
            {
                var path = name.Substring(resourcePrefix.Length);

                app.Get(Combine(urlPrefix, path), req =>
                {
                    using (var rs = assembly.GetManifestResourceStream(name))
                    {
                        req.ContentTypeByPath(name);
                        req.SendStream(rs);
                    }
                });
            });

            return(app);
        }
        private void ProcessExpressRequest(HttpListenerContext context, ExpressApplication app)
        {
            var wrapper = new HttpListenerContextImpl(context, _settings);
            var res     = wrapper.Response;

            using (res.OutputStream)
            {
                try
                {
                    if (!app.Process(wrapper))
                    {
                        res.StatusCode        = (int)HttpStatusCode.NotFound;
                        res.StatusDescription = "Not found";
                        res.ContentType       = "text/plain";
                        res.Write("Resource not found!");
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);

                    res.StatusCode  = (int)HttpStatusCode.InternalServerError;
                    res.ContentType = "text/plain";
                    res.Write(e.ToString());
                }

                res.Flush();
                res.End();
            }
        }
        private void ProcessExpressRequest(HttpListenerContext context, ExpressApplication app)
        {
            var wrapper = new HttpListenerContextImpl(context, _settings);
            var res = wrapper.Response;

            using (res.OutputStream)
            {
                try
                {
                    if (!app.Process(wrapper))
                    {
                        res.StatusCode = (int)HttpStatusCode.NotFound;
                        res.StatusDescription = "Not found";
                        res.ContentType = "text/plain";
                        res.Write("Resource not found!");
                    }
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine(e);

                    res.StatusCode = (int)HttpStatusCode.InternalServerError;
                    res.ContentType = "text/plain";
                    res.Write(e.ToString());
                }

                res.Flush();
                res.End();
            }
        }
Beispiel #4
0
        private static void Main(string[] args)
        {
            var options = (from arg in args
                           where arg.StartsWith("--")
                           let pair = arg.Substring(2).Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries)
                                      where pair.Length == 2
                                      let key = pair[0].Trim()
                                                let val = pair[1].Trim()
                                                          select new KeyValuePair <string, string>(key, val))
                          .ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase);

            var port        = options.Get("port", 80);
            var workerCount = options.Get("workers", 4);

            var app = new ExpressApplication();

            app.Static("{*url}", Environment.CurrentDirectory);

            using (new HttpServer(app, new HttpServerSettings
            {
                Port = port,
                WorkerCount = workerCount
            }))
            {
                Console.WriteLine("Listening port {0}. Press enter to stop the server.", port);
                Console.ReadLine();
            }
        }
Beispiel #5
0
 public static ExpressApplication Post <T, TResult>(this ExpressApplication app, string url, Func <T, TResult> func)
 {
     return(app.Post(url, req =>
     {
         var arg = req.ParseJson <T>();
         var result = func(arg);
         Send(req, result);
     }));
 }
Beispiel #6
0
        public static ExpressApplication Get <T1, TResult>(this ExpressApplication app, string url, Func <T1, TResult> func)
        {
            var p = ParseRouteParams(url);

            return(app.Get(url, req =>
            {
                var arg1 = req.Param <T1>(p[0]);
                var result = func(arg1);
                Send(req, result);
            }));
        }
        /// <summary>
        /// Serves specified directory.
        /// </summary>
        /// <param name="app">The application to extend.</param>
        /// <param name="url">The url prefix.</param>
        /// <param name="dir">The directory to serve.</param>
        public static ExpressApplication Static(this ExpressApplication app, string url, string dir)
        {
            if (!Directory.Exists(dir))
            {
                throw new DirectoryNotFoundException(
                          string.Format("Specified directory '{0}' does not exist.", dir)
                          );
            }

            return(app.Get(url, req =>
            {
                var relpath = req.ResolveRelativePath(url);
                var path = Path.Combine(dir, relpath);
                req.SendFile(path);
            }));
        }
Beispiel #8
0
        private static void MethodHandler(this ExpressApplication app, string urlPrefix,
                                          Func <object> serviceInstance, MethodInfo method, WebMethodAttribute meta)
        {
            // TODO support WebMethodAttribute options (caching, etc)
            var invoke = DynamicMethods.CompileMethod(method.DeclaringType, method);

            var parameters = method.GetParameters();

            if (parameters.Length == 0)
            {
                app.Get(
                    Combine(urlPrefix, method.Name),
                    req =>
                {
                    req.SetContext();
                    var result = invoke(serviceInstance(), new object[0]);
                    req.Json(result);
                });
            }
            else
            {
                app.Get(
                    Combine(urlPrefix, method.Name),
                    req =>
                {
                    req.SetContext();
                    var args   = ParseQueryArgs(req, parameters);
                    var result = invoke(serviceInstance(), args);
                    req.Json(result);
                });

                app.Post(
                    Combine(urlPrefix, method.Name),
                    req =>
                {
                    req.SetContext();
                    var args   = ParseArgs(req, parameters);
                    var result = invoke(serviceInstance(), args);
                    req.Json(result);
                });
            }
        }
Beispiel #9
0
        public static ExpressApplication HttpHandler <T>(this ExpressApplication app, string url, string verb)
        {
            if (string.IsNullOrEmpty(verb))
            {
                verb = "*";
            }

            Func <string, bool> hasVerb = v =>
            {
                if (string.Equals(verb, "*"))
                {
                    return(true);
                }
                return(verb.IndexOf(v, StringComparison.OrdinalIgnoreCase) >= 0);
            };

            IHttpHandler handler = null;

            Action <RequestContext> action = req =>
            {
                if (handler == null)
                {
                    handler = (IHttpHandler)Activator.CreateInstance <T>();
                }

                var context = req.HttpContext.Unwrap();
                handler.ProcessRequest(context);
            };

            if (hasVerb("GET"))
            {
                app.Get(url, action);
            }

            if (hasVerb("POST"))
            {
                app.Post(url, action);
            }

            return(app);
        }
Beispiel #10
0
        public static ExpressApplication WebService <T>(this ExpressApplication app, string urlPrefix)
        {
            if (app == null)
            {
                throw new ArgumentNullException("app");
            }
            if (urlPrefix == null)
            {
                throw new ArgumentNullException("urlPrefix");
            }

            var type = typeof(T);

            if (type.IsAbstract || type.IsInterface)
            {
                throw new InvalidOperationException("Need concrete type!");
            }

            var methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);

            object        service         = null;
            Func <object> serviceInstance = () => service ?? (service = Activator.CreateInstance <T>());

            foreach (var method in methods)
            {
                var meta = method.GetAttribute <WebMethodAttribute>(true);
                if (meta == null)
                {
                    continue;
                }

                MethodHandler(app, urlPrefix, serviceInstance, method, meta);
            }

            return(app);
        }
Beispiel #11
0
        private static ExpressApplication RestImpl(this ExpressApplication app,
                                                   string url, Type type, Func <int> nextIndex,
                                                   Func <RequestContext, object> getInstance,
                                                   Func <RequestContext, object> getModel)
        {
            app.Get(url, req => req.Json(getInstance(req)));

            var props = type
                        .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                        .Where(p => FilterProperty(p))
                        .ToList();

            props.ForEach(prop =>
            {
                var propertyUrl = Combine(url, prop.Name);
                var getter      = DynamicMethods.CompileGetter(type, prop);
                var setter      = DynamicMethods.CompileSetter(type, prop);

                Func <RequestContext, object> propertyInstance = req =>
                {
                    var instance = getInstance(req);
                    return(getter(instance));
                };

                app.Get(propertyUrl, req => req.Json(propertyInstance(req)));

                if (setter != null)
                {
                    app.Update(propertyUrl, req =>
                    {
                        req.SetContext();

                        var json       = req.ParseJson();
                        var hasChanges = ChangesDetector(req, getModel);
                        var instance   = getInstance(req);

                        // TODO get default value from metadata
                        var defval = GetDefaultValue(prop.PropertyType);
                        var value  = json.Get("value", defval, prop.PropertyType);

                        setter(instance, value);

                        req.Json(hasChanges() ? ModelPayload(req, getModel) : null);
                    });
                }

                if (IsCollection(prop.PropertyType))
                {
                    RestCollection(app, propertyUrl, prop.PropertyType, nextIndex, propertyInstance, getModel);
                }
                else if (IsObject(prop.PropertyType))
                {
                    RestImpl(app, propertyUrl, prop.PropertyType, nextIndex, propertyInstance, getModel);
                }
            });

            var methods = type
                          .GetMethods(BindingFlags.Public | BindingFlags.Instance)
                          .Where(m => m.GetAttribute <RestAttribute>(true) != null)
                          .ToList();

            methods.ForEach(method =>
            {
                var call = DynamicMethods.CompileMethod(type, method);

                app.Post(url, req =>
                {
                    req.SetContext();

                    var hasChanges = ChangesDetector(req, getModel);

                    var args       = req.ParseArgs(method.GetParameters());
                    var collection = getInstance(req);
                    var result     = call(collection, args);

                    req.Json(hasChanges() ? ModelPayload(req, getModel) : result);
                });
            });

            return(app);
        }
Beispiel #12
0
        // TODO detect recursive type hierarchies

        /// <summary>
        /// Builds REST handlers for given model function.
        /// </summary>
        /// <typeparam name="T">Model type.</typeparam>
        /// <param name="app"><see cref="ExpressApplication"/> to extend.</param>
        /// <param name="modelUrl">The model url.</param>
        /// <param name="getModel">The function which returns model instance.</param>
        public static ExpressApplication Rest <T>(this ExpressApplication app, string modelUrl, Func <RequestContext, T> getModel)
        {
            var i = 0;

            return(RestImpl(app, modelUrl, typeof(T), () => i++, req => getModel(req), req => getModel(req)));
        }
Beispiel #13
0
        private static void RestCollection(this ExpressApplication app, string url, Type type, Func <int> nextIndex,
                                           Func <RequestContext, object> getInstance, Func <RequestContext, object> getModel)
        {
            var indexer   = DynamicMethods.CompileIndexer(type);
            var indexName = "i" + nextIndex();
            var indexUrl  = Combine(url, string.Format("{{{0}}}", indexName));

            Func <RequestContext, object> getItem = req =>
            {
                var index      = req.Param <int>(indexName);
                var collection = getInstance(req);
                return(indexer(collection, index));
            };

            if (indexer != null)
            {
                app.Get(indexUrl, req => req.Json(getItem(req)));
            }

            // TODO dispatch multiple Add methods
            var addMethod = type.GetMethod("Add");

            if (addMethod != null)
            {
                var add = DynamicMethods.CompileMethod(type, addMethod);
                app.Put(url, req =>
                {
                    req.SetContext();

                    var hasChanges = ChangesDetector(req, getModel);

                    var args       = req.ParseArgs(addMethod.GetParameters());
                    var collection = getInstance(req);
                    var result     = add(collection, args);

                    req.Json(hasChanges() ? ModelPayload(req, getModel) : result);
                });
            }

            var remove = DynamicMethods.CompileRemoveAt(type);

            if (remove != null)
            {
                app.Delete(indexUrl, req =>
                {
                    req.SetContext();
                    var hasChanges = ChangesDetector(req, getModel);
                    var index      = req.Param <int>(indexName);
                    var collection = getInstance(req);
                    var result     = remove(collection, index);
                    req.Json(hasChanges() ? ModelPayload(req, getModel) : result);
                });
            }

            var countProperty = type.GetProperty("Count", BindingFlags.Instance | BindingFlags.Public);

            if (countProperty != null && countProperty.GetIndexParameters().Length == 0)
            {
                var count = DynamicMethods.CompileGetter(type, countProperty);

                app.Get(Combine(url, "Count"), req =>
                {
                    var collection = getInstance(req);
                    req.Json(count(collection));
                });
            }

            var itemType = GetItemType(type);

            if (IsObject(itemType))
            {
                RestImpl(app, indexUrl, itemType, nextIndex, getItem, getModel);
            }
        }
Beispiel #14
0
 public static ExpressApplication Get <TResult>(this ExpressApplication app, string url, Func <TResult> func)
 {
     return(app.Get(url, req => Send(req, func())));
 }