コード例 #1
0
 public IMOwinServerMiddleware(Func<IDictionary<string, object>, Task> next, IIMOwinOptions options, Assembly[] hostAssemblies)
 {
     this._next = next;
     this._useOtherMiddleware = options.UseOtherMiddleware;
     this._engine = new IMOwinServer(options);
     this._engine.RegisterHandlers(options, hostAssemblies);
 }
コード例 #2
0
        public void RegisterHandlers(IIMOwinOptions options, Assembly[] hostAssemblies)
        {
            // memoized
            if (Interlocked.Increment(ref _alreadyRegistered) != 0) return;

            var contractTypes = hostAssemblies
                .SelectMany(x =>
                {
                    try
                    {
                        return x.GetTypes();
                    }
                    catch (ReflectionTypeLoadException ex)
                    {
                        return ex.Types.Where(t => t != null);
                    }
                })
                .Where(x => typeof (IMOwinBehaviorContract).IsAssignableFrom(x))
                .Where(x => !x.IsAbstract);

            Parallel.ForEach(contractTypes, classType =>
            {
                var className = classType.Name;
                if (classType.GetConstructors().All(x => x.GetParameters().Length != 0))
                {
                    throw new InvalidOperationException(string.Format("Type needs parameterless constructor, class:{0}", classType.FullName));
                }
                // ignore
                if (classType.GetCustomAttribute<IgnoreOperationAttribute>(true) != null) return;

                foreach (var methodInfo in classType.GetMethods(BindingFlags.Public | BindingFlags.Instance))
                {
                    // property
                    if (methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_") || methodInfo.Name.StartsWith("get_")))
                        continue;

                    // ignore
                    if (methodInfo.GetCustomAttribute<IgnoreOperationAttribute>(true) != null) 
                        continue;

                    var methodName = methodInfo.Name;
                    // ignore default methods
                    if (methodName == "Equals" || methodName == "GetHashCode" || methodName == "GetType" || methodName == "ToString") 
                        continue;

                    // create handler
                    var handler = new OperationHandler(classType, methodInfo);
                    lock (_handlers)
                    {
                        var path = new RequestPath(className, methodName);
                        // 簡単化のため duplicate entry ⇒ fail
                        if (_handlers.ContainsKey(path))
                        {
                            throw new InvalidOperationException(string.Format("same class and method is not allowed, class:{0} method:{1}", className, methodName));
                        }
                        _handlers.Add(path, handler);
                    }
                }
            });
        }
コード例 #3
0
        internal void EmitCode(IIMOwinOptions options, IDictionary<string, object> environment)
        {
            environment[OwinConstants.ResponseStatusCode] = (int)StatusCode;
            if (ReasonPhrase != null)
            {
                environment[OwinConstants.ResponseReasonPhrase] = ReasonPhrase;
            }
            if (Content != null)
            {
                _contentFormatter = _contentFormatter ?? options.ContentFormatter;
                var encoding = _contentFormatter.Encoding;
                var responseHeader = environment.AsResponseHeaders();
                responseHeader["Content-Type"] = new[] { _contentFormatter.MediaType + ((encoding == null) ? "" : "; charset=" + encoding.WebName) };

                var responseStream = environment.AsResponseBody();
                if (options.StreamWriteOption == StreamWriteOption.DirectWrite)
                {
                    _contentFormatter.Serialize(new UnclosableStream(responseStream), Content);
                }
                else
                {
                    using (var buffer = new MemoryStream())
                    {
                        _contentFormatter.Serialize(new UnclosableStream(buffer), Content);
                        responseHeader["Content-Length"] = new[] { buffer.Position.ToString(CultureInfo.InvariantCulture) };
                        buffer.Position = 0;
                        if (options.StreamWriteOption == StreamWriteOption.BufferAndWrite)
                        {
                            buffer.CopyTo(responseStream); // not CopyToAsync
                        }
                        else
                        {
                            // can't await in catch clouse..
                            // return buffer.CopyToAsync(responseStream);
                            buffer.CopyTo(responseStream);
                        }
                    }
                }
            }
        }
コード例 #4
0
        internal static object[] BindParameter(IDictionary<string, object> environment, IIMOwinOptions options, ValueProvider valueProvider, ParameterInfoSlim[] arguments)
        {
            var methodParameters = new object[arguments.Length];
            for (var 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;
                    }
                    if (!item.ParameterTypeIsString && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }
                    environment.EmitBadRequest();
                    return null;
                }

                if (!item.ParameterTypeIsArray)
                {
                    var conv = TypeBinder.GetConverter(item.ParameterType);
                    if (conv == null) throw new InvalidOperationException("critical:register code is broken");

                    object pValue;
                    if (value != null && conv(value, out pValue))
                    {
                        methodParameters[i] = pValue;
                        continue;
                    }
                    if (item.IsOptional)
                    {
                        methodParameters[i] = item.DefaultValue;
                        continue;
                    }
                    if (!item.ParameterTypeIsString && (item.ParameterTypeIsClass || item.ParameterTypeIsNullable))
                    {
                        methodParameters[i] = null;
                        continue;
                    }

                    environment.EmitBadRequest();
                    return null;
                }

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

                methodParameters[i] = arrayConv(values ?? ((value != null) ? new[] { value } : (IList<string>)new string[0]));

            }
            return methodParameters;
        }
コード例 #5
0
 public IMOwinServer(IIMOwinOptions options)
 {
     this._options = options;
 }
コード例 #6
0
 private static bool IsRethrowOrEmitException(IIMOwinOptions options, IDictionary<string, object> environment, Exception ex)
 {
     var exString = ex.ToString();
     switch (options.ErrorHandlingPolicy)
     {
         case ErrorHandlingPolicy.ParseReturnStatusCodeException:
             environment.ParseReturnStatusCodeException(ex);
             return false;
         case ErrorHandlingPolicy.ReturnInternalServerError:
             environment.EmitInternalServerError();
             environment.EmitStringMessage("500 InternalServerError");
             return false;
         case ErrorHandlingPolicy.ReturnInternalServerErrorIncludeErrorDetails:
             environment.EmitInternalServerError();
             environment.EmitStringMessage(exString);
             return false;
         default:
             environment.EmitInternalServerError();
             return true;
     }
 }
コード例 #7
0
 public static IAppBuilder UseIMOwin(this IAppBuilder app, IIMOwinOptions options, params Assembly[] hostAssemblies)
 {
     return app.Use(typeof(IMOwinServerMiddleware), options, hostAssemblies);
 }
コード例 #8
0
 public static IAppBuilder UseIMOwin(this IAppBuilder app, IIMOwinOptions options)
 {
     return app.Use(typeof(IMOwinServerMiddleware), options);
 }
コード例 #9
0
 public IMOwinServerMiddleware(Func<IDictionary<string, object>, Task> next, IIMOwinOptions options)
     : this(next, options, AppDomain.CurrentDomain.GetAssemblies())
 {
 }
コード例 #10
0
        private async Task<object> ExecuteOperation(IIMOwinOptions options, OperationContext context)
        {
            // prepare
            var handler = this;
            var environment = context.Environment;
            var methodParameters = (object[])context.Parameters;

            var 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;
                if (responseHeader == null) return result;

                responseHeader["Content-Type"] = new[] { context.ContentFormatter.MediaType + ((encoding == null) ? "" : "; charset=" + encoding.WebName) };
                if (!string.IsNullOrWhiteSpace(context.ContentFormatter.ContentEncoding))
                {
                    responseHeader["Content-Encoding"] = new[] { context.ContentFormatter.ContentEncoding };
                }
                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(CultureInfo.InvariantCulture) };
                        buffer.Position = 0;
                        if (options.StreamWriteOption == StreamWriteOption.BufferAndWrite)
                        {
                            if (responseStream != null) buffer.CopyTo(responseStream); // not CopyToAsync
                        }
                        else
                        {
                            await buffer.CopyToAsync(responseStream).ConfigureAwait(false);
                        }
                    }
                }

                return result;
            }

            environment.EmitNoContent();
            return null;
        }
コード例 #11
0
 private Task InvokeRecursive(int index, IOrderedEnumerable<IMOwinFilter> filters, IIMOwinOptions options, OperationContext context)
 {
     index += 1;
     return filters.Count() != index ? filters.Skip(index).First().Invoke(context, () => InvokeRecursive(index, filters, options, context)) : ExecuteOperation(options, context);
 }
コード例 #12
0
 public Task Execute(IIMOwinOptions options, OperationContext context)
 {
     var filters = options.Filters.OrderBy(f => f.Order);
     return InvokeRecursive(-1, filters, options, context);
 }