Наследование: ILightNodeOptions
 public LightNodeServerMiddleware(AppFunc next, LightNodeOptions options, Assembly[] hostAssemblies)
 {
     this.next = next;
     this.useOtherMiddleware = options.UseOtherMiddleware;
     this.engine = new LightNodeServer(options);
     this.engine.RegisterHandler(hostAssemblies);
 }
Пример #2
0
 public LightNodeServerMiddleware(AppFunc next, LightNodeOptions options, Assembly[] hostAssemblies)
 {
     this.next = next;
     this.useOtherMiddleware = options.UseOtherMiddleware;
     this.engine             = new LightNodeServer(options);
     this.engine.RegisterHandler(hostAssemblies);
 }
Пример #3
0
        public Task Execute(LightNodeOptions options, OperationContext context)
        {
            int         index           = -1;
            Func <Task> invokeRecursive = null;

            invokeRecursive = () =>
            {
                index += 1;
                if (filters.Length != index)
                {
                    // chain next filter
                    return(filters[index].Invoke(context, invokeRecursive));
                }
                else
                {
                    // execute operation
                    return(ExecuteOperation(options, context));
                }
            };
            return(invokeRecursive());
        }
Пример #4
0
        /// <summary>
        /// Owin よみこみ
        /// </summary>
        /// <param name="app"></param>
        public void Configuration(IAppBuilder app)
        {
            // 各種有効化
            app.UseRequestScopeContext(); // Context の取得
            app.UseFileServer(); // FileServer 用の読み込みだよ (Owin からFileアクセス許可を許容するために必要)

            // api 処理
            app.Map("/api", builder =>
            {
                var option = new LightNodeOptions(AcceptVerbs.Get | AcceptVerbs.Post, new JsonNetContentFormatter())
                {
                    ParameterEnumAllowsFieldNameParse = true, // If you want to use enums human readable display on Swagger, set to true
                    ErrorHandlingPolicy = ErrorHandlingPolicy.ReturnInternalServerErrorIncludeErrorDetails,
                    OperationMissingHandlingPolicy = OperationMissingHandlingPolicy.ReturnErrorStatusCodeIncludeErrorDetails,
                };

                // LightNode つかうよ
                builder.UseLightNode(option);
            });

            // page 処理
            app.Map("/pages", builder =>
            {
                // LightNode つかうにゃ
                builder.UseLightNode(new LightNodeOptions(AcceptVerbs.Get, new JsonNetContentFormatter()));
            });

            // Swagger くみこむにゃん
            app.Map("/swagger", builder =>
            {
                var xmlName = "LightNodeSelfHost.xml";
                var xmlPath = AppDomain.CurrentDomain.BaseDirectory + @"bin\" + xmlName;

                builder.UseLightNodeSwagger(new SwaggerOptions("LightNodeSelfHost", "/api")
                {
                    XmlDocumentPath = xmlPath,
                    IsEmitEnumAsString = true // Enumを文字列で並べたいならtrueに
                });
            });
        }
Пример #5
0
 public LightNodeServer(LightNodeOptions options)
 {
     this.options = options;
 }
 public static IAppBuilder UseLightNode(this IAppBuilder app, LightNodeOptions options)
 {
     return app.Use(typeof(LightNodeServerMiddleware), options);
 }
 public static IAppBuilder UseLightNode(this IAppBuilder app, LightNodeOptions options, params Assembly[] hostAssemblies)
 {
     return app.Use(typeof(LightNodeServerMiddleware), options, hostAssemblies);
 }
 public LightNodeServerMiddleware(AppFunc next, LightNodeOptions options)
     : this(next, options, AppDomain.CurrentDomain.GetAssemblies())
 {
 }
Пример #9
0
 public static void RegisterOptions(LightNodeOptions options)
 {
     LightNodeServer.options = options;
 }
Пример #10
0
        async Task ExecuteOperation(LightNodeOptions options, OperationContext context)
        {
            // prepare
            var handler          = this;
            var environment      = context.Environment;
            var methodParameters = context.Parameters;

            bool   isVoid = true;
            object result = null;

            switch (handler.handlerBodyType)
            {
            case HandlerBodyType.Action:
                handler.methodActionBody(environment, methodParameters);
                break;

            case HandlerBodyType.Func:
                isVoid = false;
                result = handler.methodFuncBody(environment, methodParameters);
                break;

            case HandlerBodyType.AsyncAction:
                var actionTask = handler.methodAsyncActionBody(environment, methodParameters);
                await actionTask.ConfigureAwait(false);

                break;

            case HandlerBodyType.AsyncFunc:
                isVoid = false;
                var funcTask = handler.methodAsyncFuncBody(environment, methodParameters);
                await funcTask.ConfigureAwait(false);

                var extractor = taskResultExtractors[funcTask.GetType()];
                result = extractor(funcTask);
                break;

            default:
                throw new InvalidOperationException("critical:register code is broken");
            }

            if (!isVoid)
            {
                // append header
                var responseHeader = environment["owin.ResponseHeaders"] as IDictionary <string, string[]>;
                var encoding       = context.ContentFormatter.Encoding;
                responseHeader["Content-Type"] = new[] { context.ContentFormatter.MediaType + ((encoding == null) ? "" : "; charset=" + encoding.WebName) };
                environment.EmitOK();

                var responseStream = environment["owin.ResponseBody"] as Stream;
                if (options.StreamWriteOption == StreamWriteOption.DirectWrite)
                {
                    context.ContentFormatter.Serialize(new UnclosableStream(responseStream), result);
                }
                else
                {
                    using (var buffer = new MemoryStream())
                    {
                        context.ContentFormatter.Serialize(new UnclosableStream(buffer), result);
                        responseHeader["Content-Length"] = new[] { buffer.Position.ToString() };
                        buffer.Position = 0;
                        if (options.StreamWriteOption == StreamWriteOption.BufferAndWrite)
                        {
                            buffer.CopyTo(responseStream); // not CopyToAsync
                        }
                        else
                        {
                            await buffer.CopyToAsync(responseStream).ConfigureAwait(false);
                        }
                    }
                }

                return;
            }
            else
            {
                environment.EmitNoContent();
                return;
            }
        }
Пример #11
0
        public OperationHandler(LightNodeOptions options, Type classType, MethodInfo methodInfo)
        {
            this.ClassName  = classType.Name;
            this.MethodName = methodInfo.Name;
            this.Arguments  = methodInfo.GetParameters()
                              .Select(x => new ParameterInfoSlim(x))
                              .ToArray();
            this.ReturnType = methodInfo.ReturnType;

            this.filters = options.Filters
                           .Concat(classType.GetCustomAttributes <LightNodeFilterAttribute>(true))
                           .Concat(methodInfo.GetCustomAttributes <LightNodeFilterAttribute>(true))
                           .OrderBy(x => x.Order)
                           .ToArray();

            this.AttributeLookup = classType.GetCustomAttributes(true)
                                   .Concat(methodInfo.GetCustomAttributes(true))
                                   .Cast <Attribute>()
                                   .ToLookup(x => x.GetType());

            foreach (var argument in this.Arguments)
            {
                if (!TypeBinder.IsAllowType(argument.ParameterType))
                {
                    throw new InvalidOperationException(string.Format("parameter is not allowed, class:{0} method:{1} paramName:{2} paramType:{3}",
                                                                      classType.Name, methodInfo.Name, argument.Name, argument.ParameterType.FullName));
                }
            }

            // prepare lambda parameters
            var envArg     = Expression.Parameter(typeof(IDictionary <string, object>), "environment");
            var envBind    = Expression.Bind(typeof(LightNodeContract).GetProperty("Environment"), envArg);
            var args       = Expression.Parameter(typeof(object[]), "args");
            var parameters = methodInfo.GetParameters()
                             .Select((x, i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), x.ParameterType))
                             .ToArray();

            // Task or Task<T>
            if (typeof(Task).IsAssignableFrom(this.ReturnType))
            {
                // (object[] args) => new X().M((T1)args[0], (T2)args[1])...
                var lambda = Expression.Lambda <Func <IDictionary <string, object>, object[], Task> >(
                    Expression.Call(
                        Expression.MemberInit(Expression.New(classType), envBind),
                        methodInfo,
                        parameters),
                    envArg, args);

                if (this.ReturnType.IsGenericType && this.ReturnType.GetGenericTypeDefinition() == typeof(Task <>))
                {
                    this.handlerBodyType     = HandlerBodyType.AsyncFunc;
                    this.methodAsyncFuncBody = lambda.Compile();

                    lock (taskResultExtractors)
                    {
                        if (!taskResultExtractors.ContainsKey(this.ReturnType))
                        {
                            // (object task) => (object)((Task<>).Result)
                            var taskParameter = Expression.Parameter(typeof(object), "task");
                            var resultLambda  = Expression.Lambda <Func <object, object> >(
                                Expression.Convert(
                                    Expression.Property(
                                        Expression.Convert(taskParameter, this.ReturnType),
                                        "Result"),
                                    typeof(object)),
                                taskParameter);

                            var compiledResultLambda = resultLambda.Compile();

                            taskResultExtractors[this.ReturnType] = compiledResultLambda;
                        }
                    }
                }
                else
                {
                    this.handlerBodyType       = HandlerBodyType.AsyncAction;
                    this.methodAsyncActionBody = lambda.Compile();
                }
            }
            else if (this.ReturnType == typeof(void)) // of course void
            {
                // (object[] args) => { new X().M((T1)args[0], (T2)args[1])... }
                var lambda = Expression.Lambda <Action <IDictionary <string, object>, object[]> >(
                    Expression.Call(
                        Expression.MemberInit(Expression.New(classType), envBind),
                        methodInfo,
                        parameters),
                    envArg, args);

                this.handlerBodyType  = HandlerBodyType.Action;
                this.methodActionBody = lambda.Compile();
            }
            else // return T
            {
                // (object[] args) => (object)new X().M((T1)args[0], (T2)args[1])...
                var lambda = Expression.Lambda <Func <IDictionary <string, object>, object[], object> >(
                    Expression.Convert(
                        Expression.Call(
                            Expression.MemberInit(Expression.New(classType), envBind),
                            methodInfo,
                            parameters)
                        , typeof(object)),
                    envArg, args);

                this.handlerBodyType = HandlerBodyType.Func;
                this.methodFuncBody  = lambda.Compile();
            }
        }
Пример #12
0
        internal static object[] BindParameter(IDictionary <string, object> environment, LightNodeOptions options, ValueProvider valueProvider, ParameterInfoSlim[] arguments)
        {
            var methodParameters = new object[arguments.Length];

            for (int i = 0; i < arguments.Length; i++)
            {
                var item = arguments[i];

                var _values = valueProvider.GetValue(item.Name);
                var value   = _values as string;
                var values  = _values as List <string>;
                var isEmpty = _values == null;

                if (isEmpty && !item.ParameterTypeIsArray)
                {
                    if (item.IsOptional)
                    {
                        methodParameters[i] = item.DefaultValue;
                        continue;
                    }
                    else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }
                    else
                    {
                        environment.EmitBadRequest();
                        environment.EmitStringMessage("Lack of Parameter:" + item.Name);
                        return(null);
                    }
                }
                else if (!item.ParameterTypeIsArray)
                {
                    var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse);
                    if (conv == null)
                    {
                        throw new InvalidOperationException("critical:register code is broken");
                    }

                    object pValue;
                    if (conv(value ?? values[0], out pValue))
                    {
                        methodParameters[i] = pValue;
                        continue;
                    }
                    else if (item.IsOptional)
                    {
                        methodParameters[i] = item.DefaultValue;
                        continue;
                    }
                    else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }
                    else
                    {
                        environment.EmitBadRequest();
                        environment.EmitStringMessage("Mismatch Parameter Type:" + item.Name);
                        return(null);
                    }
                }

                var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse);
                if (arrayConv == null)
                {
                    throw new InvalidOperationException("critical:register code is broken");
                }

                methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : Enumerable.Empty <string>());
                continue;
            }

            return(methodParameters);
        }
Пример #13
0
 public Task Execute(LightNodeOptions options, OperationContext context)
 {
     int index = -1;
     Func<Task> invokeRecursive = null;
     invokeRecursive = () =>
     {
         index += 1;
         if (filters.Length != index)
         {
             // chain next filter
             return filters[index].Invoke(context, invokeRecursive);
         }
         else
         {
             // execute operation
             return ExecuteOperation(options, context);
         }
     };
     return invokeRecursive();
 }
Пример #14
0
 public LightNodeServerMiddleware(AppFunc next, LightNodeOptions options)
     : this(next, options, AppDomain.CurrentDomain.GetAssemblies())
 {
 }
Пример #15
0
 public LightNodeServer(LightNodeOptions options)
 {
     this.options = options;
 }
Пример #16
0
        internal static object[] BindParameter(IDictionary<string, object> environment, LightNodeOptions options, ValueProvider valueProvider, ParameterInfoSlim[] arguments)
        {
            var methodParameters = new object[arguments.Length];
            for (int i = 0; i < arguments.Length; i++)
            {
                var item = arguments[i];

                var _values = valueProvider.GetValue(item.Name);
                var value = _values as string;
                var values = _values as List<string>;
                var isEmpty = _values == null;

                if (isEmpty && !item.ParameterTypeIsArray)
                {
                    if (item.IsOptional)
                    {
                        methodParameters[i] = item.DefaultValue;
                        continue;
                    }
                    else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }
                    else
                    {
                        environment.EmitBadRequest();
                        environment.EmitStringMessage("Lack of Parameter:" + item.Name);
                        return null;
                    }
                }
                else if (!item.ParameterTypeIsArray)
                {
                    var conv = TypeBinder.GetConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse);
                    if (conv == null) throw new InvalidOperationException("critical:register code is broken");

                    object pValue;
                    if (conv(value ?? values[0], out pValue))
                    {
                        methodParameters[i] = pValue;
                        continue;
                    }
                    else if (item.IsOptional)
                    {
                        methodParameters[i] = item.DefaultValue;
                        continue;
                    }
                    else if ((!item.ParameterTypeIsString || options.ParameterStringImplicitNullAsDefault) && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }
                    else
                    {
                        environment.EmitBadRequest();
                        environment.EmitStringMessage("Mismatch Parameter Type:" + item.Name);
                        return null;
                    }
                }

                var arrayConv = TypeBinder.GetArrayConverter(item.ParameterType, !options.ParameterEnumAllowsFieldNameParse);
                if (arrayConv == null) throw new InvalidOperationException("critical:register code is broken");

                methodParameters[i] = arrayConv((values != null) ? values : (value != null) ? new[] { value } : Enumerable.Empty<string>());
                continue;
            }

            return methodParameters;
        }
Пример #17
0
        public OperationHandler(LightNodeOptions options, Type classType, MethodInfo methodInfo)
        {
            this.ClassName = classType.Name;
            this.MethodName = methodInfo.Name;
            this.Arguments = methodInfo.GetParameters()
                .Select(x => new ParameterInfoSlim(x))
                .ToArray();
            this.ReturnType = methodInfo.ReturnType;

            this.filters = options.Filters
                .Concat(classType.GetCustomAttributes<LightNodeFilterAttribute>(true))
                .Concat(methodInfo.GetCustomAttributes<LightNodeFilterAttribute>(true))
                .OrderBy(x => x.Order)
                .ToArray();

            this.AttributeLookup = classType.GetCustomAttributes(true)
                .Concat(methodInfo.GetCustomAttributes(true))
                .Cast<Attribute>()
                .ToLookup(x => x.GetType());

            foreach (var argument in this.Arguments)
            {
                if (!TypeBinder.IsAllowType(argument.ParameterType))
                {
                    throw new InvalidOperationException(string.Format("parameter is not allowed, class:{0} method:{1} paramName:{2} paramType:{3}",
                        classType.Name, methodInfo.Name, argument.Name, argument.ParameterType.FullName));
                }
            }

            // prepare lambda parameters
            var envArg = Expression.Parameter(typeof(IDictionary<string, object>), "environment");
            var envBind = Expression.Bind(typeof(LightNodeContract).GetProperty("Environment"), envArg);
            var args = Expression.Parameter(typeof(object[]), "args");
            var parameters = methodInfo.GetParameters()
                .Select((x, i) => Expression.Convert(Expression.ArrayIndex(args, Expression.Constant(i)), x.ParameterType))
                .ToArray();

            // Task or Task<T>
            if (typeof(Task).IsAssignableFrom(this.ReturnType))
            {
                // (object[] args) => new X().M((T1)args[0], (T2)args[1])...
                var lambda = Expression.Lambda<Func<IDictionary<string, object>, object[], Task>>(
                    Expression.Call(
                        Expression.MemberInit(Expression.New(classType), envBind),
                        methodInfo,
                        parameters),
                    envArg, args);

                if (this.ReturnType.IsGenericType && this.ReturnType.GetGenericTypeDefinition() == typeof(Task<>))
                {
                    this.handlerBodyType = HandlerBodyType.AsyncFunc;
                    this.methodAsyncFuncBody = lambda.Compile();

                    lock (taskResultExtractors)
                    {
                        if (!taskResultExtractors.ContainsKey(this.ReturnType))
                        {
                            // (object task) => (object)((Task<>).Result)
                            var taskParameter = Expression.Parameter(typeof(object), "task");
                            var resultLambda = Expression.Lambda<Func<object, object>>(
                                Expression.Convert(
                                    Expression.Property(
                                        Expression.Convert(taskParameter, this.ReturnType),
                                        "Result"),
                                    typeof(object)),
                                taskParameter);

                            var compiledResultLambda = resultLambda.Compile();

                            taskResultExtractors[this.ReturnType] = compiledResultLambda;
                        }
                    }
                }
                else
                {
                    this.handlerBodyType = HandlerBodyType.AsyncAction;
                    this.methodAsyncActionBody = lambda.Compile();
                }
            }
            else if (this.ReturnType == typeof(void)) // of course void
            {
                // (object[] args) => { new X().M((T1)args[0], (T2)args[1])... }
                var lambda = Expression.Lambda<Action<IDictionary<string, object>, object[]>>(
                    Expression.Call(
                        Expression.MemberInit(Expression.New(classType), envBind),
                        methodInfo,
                        parameters),
                    envArg, args);

                this.handlerBodyType = HandlerBodyType.Action;
                this.methodActionBody = lambda.Compile();
            }
            else // return T
            {
                // (object[] args) => (object)new X().M((T1)args[0], (T2)args[1])...
                var lambda = Expression.Lambda<Func<IDictionary<string, object>, object[], object>>(
                    Expression.Convert(
                        Expression.Call(
                            Expression.MemberInit(Expression.New(classType), envBind),
                            methodInfo,
                            parameters)
                    , typeof(object)),
                    envArg, args);

                this.handlerBodyType = HandlerBodyType.Func;
                this.methodFuncBody = lambda.Compile();
            }
        }
Пример #18
0
        async Task ExecuteOperation(LightNodeOptions options, OperationContext context)
        {
            // prepare
            var handler = this;
            var environment = context.Environment;
            var methodParameters = context.Parameters;

            bool isVoid = true;
            object result = null;
            switch (handler.handlerBodyType)
            {
                case HandlerBodyType.Action:
                    handler.methodActionBody(environment, methodParameters);
                    break;
                case HandlerBodyType.Func:
                    isVoid = false;
                    result = handler.methodFuncBody(environment, methodParameters);
                    break;
                case HandlerBodyType.AsyncAction:
                    var actionTask = handler.methodAsyncActionBody(environment, methodParameters);
                    await actionTask.ConfigureAwait(false);
                    break;
                case HandlerBodyType.AsyncFunc:
                    isVoid = false;
                    var funcTask = handler.methodAsyncFuncBody(environment, methodParameters);
                    await funcTask.ConfigureAwait(false);
                    var extractor = taskResultExtractors[funcTask.GetType()];
                    result = extractor(funcTask);
                    break;
                default:
                    throw new InvalidOperationException("critical:register code is broken");
            }

            if (!isVoid)
            {
                // append header
                var responseHeader = environment["owin.ResponseHeaders"] as IDictionary<string, string[]>;
                var encoding = context.ContentFormatter.Encoding;
                responseHeader["Content-Type"] = new[] { context.ContentFormatter.MediaType + ((encoding == null) ? "" : "; charset=" + encoding.WebName) };
                environment.EmitOK();

                var responseStream = environment["owin.ResponseBody"] as Stream;
                if (options.StreamWriteOption == StreamWriteOption.DirectWrite)
                {
                    context.ContentFormatter.Serialize(new UnclosableStream(responseStream), result);
                }
                else
                {
                    using (var buffer = new MemoryStream())
                    {
                        context.ContentFormatter.Serialize(new UnclosableStream(buffer), result);
                        responseHeader["Content-Length"] = new[] { buffer.Position.ToString() };
                        buffer.Position = 0;
                        if (options.StreamWriteOption == StreamWriteOption.BufferAndWrite)
                        {
                            buffer.CopyTo(responseStream); // not CopyToAsync
                        }
                        else
                        {
                            await buffer.CopyToAsync(responseStream).ConfigureAwait(false);
                        }
                    }
                }

                return;
            }
            else
            {
                environment.EmitNoContent();
                return;
            }
        }