[ASP.NET Web API] Autenticación basada en tokens y líos con el CORS

No era la primera vez que implementaba este tipo de autenticación en un proyecto de ASP.NET Web Api + ASP.NET MVC + OWIN y ya sabía (o al menos creo saber) los retos de trabajar con estos pipelines, digo, líneas como config.SuppressDefaultHostAuthentication(); en el  WebApiConfig hacen su magia, conocí la clase OAuthAuthorizationServerProvider y en su momento dejé en mis favoritos entradas como esta como fuente de consulta. Con el tema de CORS creí que todo estaba resuelto con el uso del atributo EnableCors que hizo esto más sencillo.

La semana pasada este requerimiento surgió de nuevo pero con un componente adicional: El token es solicitado en un cliente desde otro dominio. De entrada parece que nada cambia, pero si que lo hace, o al menos si hay que agregar unas cuantas líneas. Sabía que en mis favoritos aún estaban los enlaces a las fuentes que había usado como referencia en implementaciones anteriores, así que volví a consultar una serie de tutoriales muy, muy completos de este blog. Y por primera vez me percaté que existen dos “enable cors”! (o algo así) uno a nivel del pipeline de OWIN y el que siempre uso en Web API. El que siempre uso, el de Web API, viene en el paquete Microsoft.AspNet.WebApi.Cors y el que no conocía, el de Katana, viene en el paquete Microsoft.Owin.Cors.

¿Qué diferencia tienen WebApi.Cors y Owin.Cors?

No encontré nada en la documentación oficial, pero viendo el nombre, entendiendo algo de OWIN y habiendo usado Katana, se puede suponer que el primero es solo para el Framework Web API y lo que hay en el, es decir, los ApiControllers. El segundo es un middleware que agrega soporte para el resto del pipeline, como el middleware para generar los tokens! Igual apliqué un poco de GOD (google oriented development) y encontré una explicación similar en Stack Overflow.

¿Y cómo se usan los dos?

Lo primero que hice, desde el desconocimiento, fue agregar en el Startup la línea app.UseCors(CorsOptions.AllowAll); y en el momento de probar surgió el primer error, error que rompe la parte que ya funcionaba (mensaje en la consola de Chrome):
Control-Allow-Origin' header contains multiple values 'https://foo.com, https://foo.com', but only one is allowed. Origin 'https://foo.com' is therefore not allowed access. ¡Y tiene todo el sentido! pues en dos puntos del pipeline estamos agregando estas cabeceras.

Una solución puede ser quitar la configuración del CORS en el WebAPIConfig, es decir, la línea config.EnableCors(); y dejar que el OWIN se configure global con con Katana. ¡Pero no me gusta! no me gusta por el AllowAll (least privilage), aunque parece claro que se puede cambiar (más sobre esto a continuación), y porque se supone que la configuración del CORS de Web API es para el Framework! digo, por algo existe, no?

Como el único  lugar donde necesito el CORS es en el endpoint que genera el token, pensé que era más fácil y mejor quitar el UseCors() del Startup y agregar las cabeceras directamente en el response, sabía que no podía ser el primero que hacía esto y así fue, la segunda solución la encontré en Stack Overflow y pasa por sobrescribir el método MatchEndpoint del OAuthAuthorizationServerProvider, yo terminé con una implementación como la siguiente:

        private static void SetOriginHeaders(IOwinContext context)
        {
            if (!context.Response.Headers.Keys.Contains("Access-Control-Allow-Origin"))
                context.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Origin", "https://localhost:44369");
            if (!context.Response.Headers.Keys.Contains("Access-Control-Allow-Headers"))
                context.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Headers", "Accept", "Content-Type", "Authorization", "Cache-Control", "Pragma", "Origin");
            if (!context.Response.Headers.Keys.Contains("Access-Control-Allow-Methods"))
                context.Response.Headers.AppendCommaSeparatedValues("Access-Control-Allow-Methods", "GET", "POST", "PUT", "DELETE", "OPTIONS");
        }

        public override Task MatchEndpoint(OAuthMatchEndpointContext context)
        {
            if (context.IsTokenEndpoint &&
                (context.Request.Method.Equals("OPTIONS", StringComparison.InvariantCultureIgnoreCase)
                || context.Request.Method.Equals("POST", StringComparison.InvariantCultureIgnoreCase)))
            {
                SetOriginHeaders(context.OwinContext);
                context.MatchesTokenEndpoint();
                //context.RequestCompleted();
                return Task.CompletedTask;
            }

            return base.MatchEndpoint(context);
        }

        public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            context.Validated();
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {		
            //Se valida el usuario...

            SetOriginHeaders(context.OwinContext);
        }

Con el código anterior funciona sin problemas, pero nuevamente pensé: ¡Esto debe poderse hacer desde el middleware!

Configurar el Owin.Cors

Después de dar muchas vueltas llegué a esta solución, que ahora me parece muy sencilla y obvia. Se puede crear una instancia de CorsOptions y usar un PoliciResolver, que no es más que una función que permite tener acceso a la información del request (IOwinRequest) y retornar un objeto que encapsula los Headers HTTP en cómodas propiedades. El código del Startup se así (el orden de los middlewares SI altera el resultado):

    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.UseCors(new CorsOptions
            {
                PolicyProvider = new CorsPolicyProvider
                {
                    PolicyResolver = PolicyResolver
                }
            });
            ConfigureAuth(app);
        }

        private static Task<CorsPolicy> PolicyResolver(IOwinRequest request)
        {
            if (request.Path.Value == "/api/token")
            {
                //Estos valores pueden ser recuperados de un archivo de configuracion
                var corsPolicy = new CorsPolicy
                {
                    Headers = { "Accept", "Content-Type", "Authorization", "Cache-Control", "Pragma", "Origin" },
                    Methods = { "POST", "OPTIONS" },
                    Origins = { "https://localhost:44369" }
                };
                return Task.FromResult(corsPolicy);
            }
            return Task.FromResult<CorsPolicy>(null);
        }
    }

Conclusiones

  • Existe un middleware de Katana que habilita CORS en todo el pipeline de OWIN, Microsoft.Owin.Cors
  • Owin.Cors y WebApi.Cors pueden existir en el mismo proyecto
  • El OAuthTokenProvider no hace parte de WebApi, por eso se necesita el Owin.Cors

Referencias y enlaces de interés

Espero les sea de utilidad.

Hasta el próximo post.

[ASP.NET Web API] Autenticación basada en tokens y líos con el CORS

ASP.NET 5, Owin y Katana

Con todo esto del ASP.NET5, ASP.NET 4.6, MVC6, DNX, DNX Core, etc. No queda muy claro donde encajan ciertos componentes que antes ya nos resultaban familiares. Como el caso de Owin y Katana que, con el anuncio de ASP.NET 5, no supe donde quedaron o qué iba a pasar con ellos.

Afortunadamente el equipo de ASP.NET documentó el tema y solo tenía que buscar un poco.

Con la información obtenida en el articulo me quedaron claras algunas cosas:

  • En el repositorio de Katana ya habían dicho que la siguiente versión sería parte de “vNext” y que el proyecto se movería de codeplex a GitHub, en el mismo repo de ASP.NET. Además renombraron todo para alinearlo con ASP.NET 5 y la versión sería de nuevo la 1.0.katanaroadmap
  • Con esta movida no solo cambiaron de nombre las cosas, también cambió el cómo funcionaban, es el caso del IAppBuilder, que ahora es IApplicationBuilder, y que usa un AppFunc diferente. O el IOwinContext, que ahora es HttpContext.
  • Si hay forma de usar los viejos (Katana 3.0) middlewares en ASPNET 5.

Algo de código

Hasta aquí he comentado lo que entendí de aquel articulo. Pero unas cuantas lineas de código nos mostrara que quiere decir esto y nos aportará nuevas dudas.

¿Cómo luce un middleware hoy?

Para crear un middleware compatible con el pipeline de Katana basta con definir una clase que use el AppFunc y tenga un método Invoke, algo de la forma:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;

namespace MisMiddelwares
{
    using AppFunc = Func<IDictionary<string, object>, Task>;

    public class DebugMiddleware
    {
        private readonly AppFunc _next;

        public DebugMiddleware(AppFunc next)
        {
            _next = next;
        }

        public async Task Invoke(IDictionary<string, object> enviroment)
        {
            var path = (string) enviroment["owin.RequestPath"];
            Debug.WriteLine("--Incoming request. Path: " + path);
            await _next(enviroment);
            Debug.WriteLine("--Outgoing request. Path: " + path);
        }
    }
}

¿Cómo se usa un middleware hoy?

El middleware anterior lo podemos integrar en el pipeline de Katana 3.0 de manera muy, muy sencilla:

    using Owin;
    using MisMiddlewares;
    public class Startup
    {        
        //... Configure Web API for self-host. 
        var config = new HttpConfiguration();
	appBuilder.Use<DebugMiddleware>();
        appBuilder.UseWebApi(config);      
    }

Si quisiéramos agregar nuestro middleware usando la forma app.UseXXX, deberíamos agregar una clase estática al ensamblado del middleware, agregar una dependencia a Katana (Microsoft.Owin) y usar el siguiente código

namespace MisMiddlewares
{
    using Owin;

    public static class DebugMiddlewareExtensions
    {
        public static void UseDebug(this IAppBuilder app)
        {
            app.Use<DebugMiddleware>();
        }
    }
}

Usar mi middleware en ASP.NET 5

Ahora viene lo nuevo, en un proyecto de ASP.NET 5 (DNX) vamos a intentar usar el middleware que acabamos de crear. Para ello lo primero que haré será remover el dnxcore50 de la sección frameworks del project.json, esto porque no lo usaré y necesito una referencia al middleware (cproj). Una vez hecho esto agrego una referencia al proyecto (con todo lo que hace por detrás), esto lo hago solo para ver que pasaría en el caso de querer reutilizar el componente sin tener que escribir nada más, además de ver que tiene el nuevo Katana que nos permita reutilizar lo anterior.

En el startup vemos que el nuevo IApplicationBuilder aún expone un método Use, pero con una firma muy diferente para el AppFunc que no nos sirve en nuestra anterior implementación. Podríamos intentar construir uno (AppFunc) a partir de este, o mejor aún, usar lo que ya tiene Katana vnext (el vnext se lo puse yo :P) para esto. En el articulo hay un enlace a un repo que contiene un ejemplo, algo engorroso, que muestra cómo hacerlo. Pero en ese mismo repositorio hay otro ejemplo un poco más claro. Partiendo de este ejemplo, si queremos usar de nuevo nuestro middleware empezaremos por instalar el paquete Microsoft.AspNet.Owin, que nos expone el método UseOwin, y, en la clase Startup ya podemos agregarlo al pipeline:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseOwin(addToPiepline =>
            {
                addToPiepline(next =>
                {
                    var middleware = new DebugMiddleware(next);
                    return middleware.Invoke;
                });
            });

Inquietudes

Con esta implementación me queda la inquietud de cómo harán las personas que mantienen este tipo de proyectos para dar soporte a las aplicaciones DNX y a las tradicionales, cómo será el tema del código compartido… o si será algo automático

Ejemplo

He dejado el código de este artículo aquí

Espero les sea de utilidad esta breve aclaración

Hasta el próximo post.

ASP.NET 5, Owin y Katana

[NancyFx] Vistas y contenido estático en diferente ensamblado

Gracias a OWIN (los componentes compatibles) podemos mover nuestra aplicación entre diferentes hosts y servidores sin mucho esfuerzo, por ésta razón, en ocasiones separamos físicamente la aplicación del host (en diferentes ensamblados).

Nancy tiene unas configuraciones predefinidas para localizar las vistas dentro del entrypoint, configuraciones que podemos sobrescribir para trabajar en la forma que deseemos, en este caso, localizar las vistas en un ensamblado distinto:

Lo primero que debemos hacer es cambiar las propiedades Build Action y Copy to Output Directory a Embedded Resource  y Do Not Copy respectivamente:

image 

Ahora necesitamos un Bootstrapper (o editar el que ya teníamos) para que Nancy pueda localizar las vistas dentro de nuestro ensamblado. Haremos uso del ResourceViewLocationProvider y su propiedad RootNamespaces para agregar el espacio de nombres que queremos. Finalmente sobrescribimos la InternalConfiguration:

    public class CustomNancyBootstraper : DefaultNancyBootstrapper
    {
        protected override void ConfigureApplicationContainer(TinyIoCContainer container)
        {
            var assembly = GetType().Assembly;
            ResourceViewLocationProvider.RootNamespaces.Clear();
            ResourceViewLocationProvider.RootNamespaces.Add(assembly, "Ensamblado.PathVistas"); // Donde se estan tus views
            base.ConfigureApplicationContainer(container);
        }
        protected override NancyInternalConfiguration InternalConfiguration
        {
            get
            {
                return NancyInternalConfiguration.WithOverrides(config => { config.ViewLocationProvider = typeof(ResourceViewLocationProvider); });
            }
        }
    }

¡Y listo! con estos pasos ya podemos tener las vistas en un ensamblado distinto.

¿Y el contenido estático?

El ResourceViewLocationProvider no nos sirve para el contenido estático dentro del sitio, así que debemos agregar las convenciones necesarias para localizar estos recursos (por ahora a pedal):

        protected override void ConfigureConventions(NancyConventions nancyConventions)
        {
            nancyConventions.StaticContentsConventions.Clear();            
            nancyConventions.StaticContentsConventions.Add(Css);
            base.ConfigureConventions(nancyConventions);
        }

        private Response Css(NancyContext context, string s)
        {
            const string resourcePath = @"/Content";
            var path = context.Request.Url.Path;
            if (!path.StartsWith(resourcePath, StringComparison.InvariantCultureIgnoreCase))
            {
                return null;
            }
            return new EmbeddedFileResponse(GetType().Assembly, "Ensamblado.PathContent", Path.GetFileName(context.Request.Url.Path));
        }

¡No sale mi Favicon!

Como vemos los contenidos deberán ser recursos embebidos y el favicon no es la excepción. Para que Nancy lo encuentre debemos sobrescribir la propiedad FavIcon, como dice la documentación:

        private byte[] _favicon;
        protected override byte[] FavIcon
        {
            get { return _favicon ?? (this._favicon = LoadFavIcon()); }
        }
        private byte[] LoadFavIcon()
        {
            using (var resourceStream = GetType().Assembly.GetManifestResourceStream("Ensamblado.favicon.ico"))
            {
                var tempFavicon = new byte[resourceStream.Length];
                resourceStream.Read(tempFavicon, 0, (int)resourceStream.Length);
                return tempFavicon;
            }
        }

El código completo de éste articulo se encuentra en este Gist.

Espero les sea de utilidad.

Hasta el próximo post.

[NancyFx] Vistas y contenido estático en diferente ensamblado

[OWIN] Corriendo WEB API en Nodejs con Connect-OWIN

Bien sabemos que iniciativas como la de OWIN llevan ya algún tiempo en otras comunidades, bien sabemos ya cuales son las ventajas y objetivos de OWIN y hasta ahora he escrito uno que otro ejemplo haciendo uso siempre de C# / .NET.

En este articulo veremos como conectar Microsoft ASP.NET Web API a Node JS haciendo uso del paquete Connect-OWIN, que en si, es una implementación de connect al estándar de OWIN.

Este paquete hace hacia parte de un proyecto más grande, nada más y nada menos que del Edge.js (específicamente del edge-connect) de Tomasz Janczuk, cuyo objetivo no es otro que el de conectar .NET y nodejs 🙂

El código de esta entrada esta en este repo, junto con un ejemplo con NancyFX y SignalR.

Echemos un vistazo, una vez instalamos los paquetes que necesitamos (realmente necesitamos dos, el paquete connect solo lo empleamos para usar el middleware logger) veremos la dependencia entre el connect-owin y edgejs

image

¿Y para que quiere hacer uso del Edgejs? pues basta con echar un vistazo a la carpeta lib/Clr ¡Oh sorpresa! un par de .dll’s entre ellas la querida Owin.dll. Y si vemos el código del connect-owin veremos lo que era de esperarse, el edge = require(‘edge’), y entre otras la construcción del enviaroment  y demás (No seas flojo! échale un ojo! que solo son 160 líneas).

El otro paquete es el de express, podemos pasar de este, pero la construcción será un poco engorrosa.

Todo el código que necesitamos entonces es este:

var owin = require('connect-owin'),
    connect = require('connect'),
    express = require('express');
var app = express();
app.use(connect.logger('dev'));
app.all('/api/*', owin(__dirname + '\\bin\\Debug\\Samples.WebApi.dll'));
app.use(express.static('Site'));
app.listen(3100);

Viendo el código un poco en detalle vemos mucho de express aquí, el app.use espera el middleware (un function) del logger de connect. El express.static hace parte de connect. Finalmente, la línea más gorda, el app.all(…), esta función mapeará todos los request hechos al path definido como primer parámetro al middleware devuelto por el connect-owin :o, y aquí esta la magia del edgejs… no es de gratis que el parámetro de la función owin sea el path del .dll de nuestro site 😉

Algo que me pareció hermoso es que no se dejaron cerradas las puertas solo al uso del IAppBuilder que KATANA resuelve tan fácil y mágico, sino que podemos hacer uso de la interfaz de interacción que tanto nos gusta… ¿Y como luce esto?

Conectando Simple.Web a Nodejs  con FIX

De seguro lo esperabas (me encanta FIX!) así que vamos a pegar Simple.Web al nodejs haciendo uso de FIX.

En un .dll que he llamado TestFix (tremenda creatividad) he agregado una clase con el nombre FixConfig con un único método llamado Invoke, así:

    public class FixConfig
    {
        public Task Invoke(IDictionary<string, object> env)
        {
            var app = new Fixer().Use(Application.Run).Build();
            return app(env);
        }
    }

Y una clasecita para que pinte algo en pantalla:

    [UriTemplate("/")]
    public class Index : IGet, IOutput<RawHtml>
    {
        public Status Get()
        {
            return 200;
        }

        public RawHtml Output
        {
            get { return "<h1>¡Hola mundo!</h1>"; }
        }
    }

Y finalmente, el JavaScript:

var owin = require('connect-owin'),
    express = require('express');
var app = express();
app.all('/node', function (req, res) {
    res.send(200, 'Hello from JavaScript! Time on server ' + new Date());
});
app.all('/', owin({
    assemblyFile: __dirname + '\\bin\\Debug\\FixTest.dll',
    typeName: 'FixTest.FixConfig',
    methodName: 'Invoke'
}));
app.listen(3200);

Como vemos aquí hice uso del custom type and method name que por fortuna incluyó el autor a la función y que me permite emplear clases y métodos con los nombres que yo desee. Luego será llamado mi Invoke al que se le pasará la información de entorno que llenó el connect-owin y empleará Fix para unirlos 🙂

Como resultado podemos ver los request:

image

Conclusión

Abstracción del servidor con OWIN… ¡¡rules!!!

Espero les sea de utilidad.

Hasta el próximo post.

[OWIN] Corriendo WEB API en Nodejs con Connect-OWIN

[OWIN] Uniéndolo todo sin KATANA IAppBuilder

Decía en una ocasión que no todo el OWIN es Katana y nombraba un par de proyectos que me llaman mucho la atención, escribí  transcribí un ejemplo con Nowin, Simple.Web y Fix y dejé el tema hasta ahí.

En esta entrada escribiré más código para demostrar un par de objetivos del estándar OWIN, el uso de pequeños módulos para el desarrollo de nuestras aplicaciones e impulsar el desarrollo de herramientas oss (Incluso por fuera de MSFT)

image

Como ya sabemos existen varios elementos que componen una aplicación OWIN (Host, server, Middleware, Fws), el punto de la interoperabilidad lo define el AppFunc y como se inicia la aplicación lo “define” la especificación.

El como pegamos los Middlewares/Frameworks al pipeline o como construimos unos que se ajusten es aún un tema discutido por la comunidad, pues bien sabemos, Microsoft hace uso del IAppBuilder del Owin.dll, paquete e interfaz que mucha gente ve como parte de la especificación, pero no lo es, por el contrario, la comunidad misma discute el futuro de esa Interfaz y del Owin.dll. Así mismo, Mark Rendle ha hecho una propuesta muy útil, algo que ya se usa en Fix, y que solo necesita una lambda, pero aun esta en discusión y no hace parte de la especificación.

Ya vimos en el anterior post a Nowin y Simple.Web, para ver lo sencillo que es conectar y desconectar, veamos lo mismo con Nancy!

NancyFx, Nowin y Fix

En este ejemplo conectaremos estos tres elementos en un self-hosting, corriendo sobre el Nowin Server. El código necesario:

    class Program
    {
        static void Main()
        {
            var nancyOptions = new NancyOptions { Bootstrapper = new DefaultNancyBootstrapper() };

            var app = new Fixer()
                .Use((env, next) => new NancyOwinHost(next, nancyOptions).Invoke(env))
                .Build();

            // Set up the Nowin server
            var builder = ServerBuilder.New()
                .SetPort(8888)
                .SetOwinApp(app);

            // Run
            using (builder.Start())
            {
                Console.WriteLine("Listening on port 1337. Enter to exit.");
                Console.ReadLine();
            }
        }
    }

    public class Home : NancyModule
    {
        public Home()
        {
            Get["/"] = _ => View["home"];
        }
    }

    public class CustomRootPathProvider : IRootPathProvider
    {
        public string GetRootPath()
        {
            return @"C:\PathDondeEstanLosHtml\";
        }
    }

La parte interesante del ejemplo esta en las líneas:

            var nancyOptions = new NancyOptions { Bootstrapper = new DefaultNancyBootstrapper() };
            var app = new Fixer()
                .Use((env, next) => new NancyOwinHost(next, nancyOptions).Invoke(env))
                .Build();

El método Use de la clase Fixer hace uso de la firma propuesta por Mark y como el bien lo dice, no rompe nada! y finalmente una invocación al método Build que retornará el AppFunc valido y cuyo diccionario será poblado luego por el server y dará inicio al big bang 😛

Ya es cuestión de opinión, pero la firma de este delegado me parece una propuesta excelente.

Ahora habrá quien este pensando que no me gusta nada de Microsoft.Owin.* y crea que es malo o que no es cool. Pues todo lo contrario! si es OWIN es bienvenido. Veamos el siguiente ejemplo.

NOWIN, WEB API y Fix

Esto es de lo que habla una de las metas de OWIN, los pequeños componentes que podemos emplear para construir nuestra aplicación, y la facilidad que supondría reemplazarlos. pues bien, veamos como conectar a nuestro servidor Nowin un ASP.NET WE API con Fix:

    class Program
    {
        static void Main(string[] args)
        {
            var app = new Fixer().Use(Start).Build();

            var builder = ServerBuilder.New()
                .SetPort(1234)
                .SetOwinApp(app);

            using (builder.Start())
            {
                Console.WriteLine("Listening on port 8888. Enter to exit.");
                Console.ReadLine();
            }
        }

        private static Task Start(IDictionary<string, object> env, Func<IDictionary<string, object>, Task> next)
        {
            IAppBuilder app = new Microsoft.Owin.Hosting.Builder.AppBuilderFactory().Create();
            app.UseWebApi(ConfigureWebApi());
            var build = app.Build();
            return build(env);
        }

        private static HttpConfiguration ConfigureWebApi()
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}", new { id = RouteParameter.Optional }
                );
            return config;
        }
    }

    public class TestController : ApiController
    {
        public string Get()
        {
            return "Nicolas";
        }
    }

Aquí si no estoy seguro de que la implementación sea correcta, no estoy seguro si se pueda acceder directamente a ASP.NET WEB API OWIN sin la necesidad de emplear el IAppBuilder, aunque Fix también parece que incluirá el soporte para el AppBuilder empleado por MS Katana.

Y lo otro, es la dependencia entre todos los paquetes de katana, en serio, puede resultar contradictorio 😦 y claro, este si que necesita del nuevo System.web, me refiero a Owin.dll :P… ¡naaa, es exagerando!

*Si alguien tiene información o sugerencias sobre este ejemplo le agradezco me lo haga saber en los comentarios.

**NOTA: Si quieres ver una muestra de como conectar y desconectar componentes OWIN haciendo uso de Katana mira este excelente articulo de Eduard Tomas

¿Y todo esto para que si yo siempre lo subo a IIS? es uno de los interrogantes más frecuentes…

Hostear aplicaciones OWIN en Windows Azure Worker Role

Así como hemos estado hosteando todo esto en una aplicación de consola es muy sencillo llevarlo a un entorno “real” y ponerlo en un Windows Azure Worker Role. Ya se escribió sobre esto en el sitio oficial de ASP.NET, haciendo uso de Katana por supuesto.

aquí va mi código con Nowin, Simple.Web y Fix:

    public class WorkerRole : RoleEntryPoint
    {
        private IDisposable _server;

        public override void Run()
        {
            Trace.TraceInformation("WebApiRole entry point called", "Information");
            while (true)
            {
                Thread.Sleep(10000);
                Trace.TraceInformation("Working", "Information");
            }
        }

        public override bool OnStart()
        {
            // Set the maximum number of concurrent connections
            ServicePointManager.DefaultConnectionLimit = 12;

            // New code:
            var endpoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"];
            string baseUri = string.Format("{0}://{1}", endpoint.Protocol, endpoint.IPEndpoint);

            Func<IDictionary<string, object>, Task> app = new Fixer()
                .Use((env, next) => Application.Run(env, t => next(env)))
                .Build();

            ServerBuilder builder = ServerBuilder.New()
                .SetAddress(endpoint.IPEndpoint.Address)
                .SetPort(82)
                .SetOwinApp(app);
            _server = builder.Start();

            Trace.TraceInformation(String.Format("Starting OWIN at {0}", baseUri), "Information");

            return base.OnStart();
        }

        public override void OnStop()
        {
            if(_server != null)
                _server.Dispose();
            base.OnStop();
        }
    }

    [UriTemplate("/")]
    public class Index : IGet, IOutput
    {
        public Status Get()
        {
            return 200;
        }

        public RawHtml Output
        {
            get { return "</pre>
<h1>¡Hola Azure!</h1>
<pre>
"; }
        }
    }

La configuración del endpoint es escuchando tanto publico como privado por el puerto 80, pero si te fijas el servidor esta escuchando por el puerto 82, esto por el balanceador de cargas del compute emulator.

El resultado, pues simple 🙂

image

En conclusión, esperemos y participemos de estas decisiones, que como vemos, como comunidad de usuarios nos pueden llegar a afectar y no permitamos que la decisión se tome solo porque Microsoft uso esto o aquello en sus plantillas de Visual Studio.

Hasta el próximo post

[OWIN] Uniéndolo todo sin KATANA IAppBuilder

No todo el OWIN es Katana

En los últimos meses he visto una gran cantidad de artículos enfocados en definir que es OWIN y como este ha cambiado la forma de “pensar”  y “hacer” las cosas en el mundo Web Microsoft, artículos en inglés y español, grandes y chicos, buenos y malos, claros y complejos… pero en lo que todos concuerdan es en que ¡siempre se habla de Katana! 😦 Pareciera que la comunidad misma le esta cerrando las puertas a las iniciativas oss hechas por la comunidad.

Vale recordar aquí que OWIN NO fue ideado por Microsoft! esta es una especificación ideada y liderada por la comunidad que inició en una lista de correo,  Katana es la implementación hecha por Microsoft y que muchos, al parecer, consideran el “único OWIN” que existe.

Hace unos días veía esta entrada en el blog de  Jimmy Bogard, en el que intenta aclarar y dar su punto de vista sobre el tema del oss en el mundo .NET, y al discutir luego con algunos colegas sobre este tema, mi conclusión es que la comunidad misma debería como mínimo conocer (si no impulsar y apoyar) algún tool oss desarrollado por la comunidad como alternativa a las del fabricante (aka Microsoft), digo como mínimo conocer, porqué otro punto que concluimos es que no estarían dispuestos a cambiar las  herramientas hechas por el fabricante por unas desarrolladas por la comunidad. Es decir, opiniones como las de este tweet de Rob Ashton (hablando sobre scriptcs):

Pero como dice Jimmy Bogard en su entrada, muchas de las herramientas Microsoft fueron reinventadas, estas ya existían antes como productos desarrollados y dirigidos por comunidades, muchas de ellas oss. Además de aclarar que son otros tiempos en la compañía, solo hay que ver equipos de producto como Windows Azure o ASP.NET  por ejemplo.

No se necesita entonces que Microsoft adopte cada uno de los productos dirigidos por la comunidad para que sean buenos o estables, estos podrán ser buenos y madurar por si mismos siendo dirigidos y apoyados por nosotros, conociéndolos, trabajándolos, reportando bugs, codificando o documentando.

Esta introducción era para abrir paso a una de las herramientas de las que ya había en una entrada anterior, y de la que su autor ha anunciado nuevas características 🙂

Fix y OWIN

Mark Rendle, quien ya en una ocasión había hablado sobre el oss en .net, ha publicado en su blog un articulo en el que habla sobre algunas nuevas características incluidas en el proyecto Fix.

En este articulo se queja de la posible “súper” dependencia con Owin.dll (¿System.Web? :P) y la interfaz IAppBuilder, además de dejar en claro que no le gusta el tema de tener una compleja navaja suiza cuando muchas veces solo se necesita un simple cuchillo:

My other issue is that Katana is full-on Microsoft, enterprise-ready, all-things-to-all-consumers, and complicated in ways I don’t quite understand, such as in the way it’s interacting with IIS’s integrated pipeline. That’s what Microsoft do, and I’m not exactly criticising them for it, but sometimes you don’t need a Swiss Army knife. Sometimes you just need a knife.

Fix es ahora mas simple 🙂 ya no usa MEF! ahora hace uso un concepto mas simple de Setup, para configurar el pipeline[…] Como no quiero caer en el error de simplemente traducir la fuente original recomiendo leer el articulo de Mark con todo lo que pensó para la nueva versión de Fix.

Fix, Nowin y Simple.Web

Veamos ahora un pequeño fragmento de código, usando tres proyectos de código abierto que muestran la simplicidad de Fix y Simple.Web, otro proyecto de Mark Rendle, corriendo sobre Nowin… haciendo uso de la especificación de OWIN:

    using Fix;
    using Nowin;
    using Simple.Web;
    using Simple.Web.Behaviors;

    class Program
    {
        static void Main()
        {
            // Build the OWIN app
            var app = new Fixer()
                .Use(Application.Run)
                .Build();

            // Set up the Nowin server
            var builder = ServerBuilder.New()
                .SetPort(1337)
                .SetOwinApp(app);

            // Run
            using (builder.Start())
            {
                Console.WriteLine("Listening on port 1337. Enter to exit.");
                Console.ReadLine();
            }
        }
    }

    [UriTemplate("/")]
    public class Index : IGet, IOutput
    {
        public Status Get()
        {
            return 200;
        }

        public RawHtml Output
        {
            get { return "¡Hola mundo!"; }
        }
    }

NOTA: Este ejemplo esta en el proyecto Fix.

Y como resultado:

image

No quiero entrar en detalles sobre funcionalidad del ejemplo o el código pues no es el objetivo del post, lo que si es que vemos como es posible tener implementaciones muy limpias de OWIN por fuera de Katana, y si te preocupa el soporte… hay interacción directa con el equipo de producto! como se ve en este tweet donde Boris Letocha, el creador de Nowin, ayuda a un usuario con un problema con un certificado 🙂

Conclusión

Katana es muy, muy bueno! vendrá ya con Visual Studio 2013 y listo para trabajar… pero no hay que olvidar que hay mas OWIN fuera de Katana y así mismo hay muchos productos dirigidos por la comunidad que Microsoft no adopta pero no por ello no dejan de ser muy buenos! es responsabilidad nuestra no dejar morir estos proyectos antes de que vean la luz.

Algo de lo que no hablé es que Katana no tendrá restricción de plataforma! y sobre este tema si que hay un gran debate entre los equipos de producto, Phil Haack ha abierto esta petición para que la apoyen quienes lo deseen.

Hasta el próximo post.

No todo el OWIN es Katana

OWIN, Katana y open source projects

De seguro que al sol de hoy ya has oído hablar sobre la especificación OWIN — Open Web Server Interface for .NET y sobre la implementación de esta especificación por parte de Microsoft en el proyecto Katana, ya se ha escrito bastante sobre el tema y para los hispanohablantes ya el buen Eduard Tomas hizo una reseña de como ha venido evolucionando ASP.NET y su visión de una futura evolución no monolítica del Framework.

En pro de la flexibilidad y la portabilidad

En la actualidad en .net tenemos varios Frameworks para desarrollo web, unos de Microsoft (WebForms, MVC y Web API) y unas opciones open source como FubuMVC, OpenRasta, NancyFX, entre otros. Con estos Frameworks desarrollamos nuestras aplicaciones, y para que puedan “correr” empleamos hosts y servidores Web, como el poderoso IIS, el IIS Express o algún tipo de Self Hosting empleando un HttpListener/TCP Listener/Web Socket. Y aquí es donde surge la principal meta de la especificación OWIN, desacoplar servidor y aplicación.

OWIN describe como los componentes de un Http pipeline deben comunicarse, para esto emplea dos componentes principales, el primero es el entorno, este es un diccionario de la forma IDictionary que llenará el servidor compatible con OWIN con los datos de entorno, con las claves que se detallan en la especificación. Y la responsabilidad de actualizar este diccionario con nuevos valores y de escribir el response body será entonces del Framework o la aplicación.

El segundo componente es el Application Delegate, esta será la abstracción principal entre todos los componentes de una aplicación, tomando el diccionario de entorno y definiendo una tarea a realizar, su firma es de la forma Func, Task>. Como se puede notar, el que la tarea a realizar sea una Task ya nos hace ver una prometedora asincronia :D.

Con estas simples abstracciones podemos escribir componentes que cumplan la especificación y “encadenarlos”  con otros componentes, reemplazar nuestro web server por uno mas ligero o robusto, emplear el host que mejor se ajuste, tener componentes mas granulares para la autenticación p. ej. y así tener lo que necesito y como lo necesito, sin ninguna dependencia extra, dándonos no solo las ventajas de poder reemplazar los componentes mas fácilmente, sino una posible mejora en el performance, pues como digo, solo usas los componentes que necesitas. Además, como estos componentes no dependen el uno del otro podríamos fácilmente encontrar un host para Mono y movernos hacia allá sin tener que reemplazar/cambiar nada/ningún componente.

A diferencia de un todo, esta modularidad nos brinda la ventaja de poder evolucionar constantemente cualquiera de nuestros componente sin tener que realizar, me atrevería a decir que, ningún trabajo en los demás.

Katana

La especificación de OWIN es dirigida por la comunidad de desarrolladores de .net, un esfuerzo conjunto de la comunidad de usuarios para presentar una nueva forma de hacer las cosas. La implementación de esta especificación por parte de Microsoft lleva el nombre de KATANA, una serie de componentes de OWIN, el proyecto es open source,  e incluye componentes de infraestructura como servidores y hosts, componentes para autenticación, Frameworks como SignalR y Web API.

El como implementar Katana ya es un tema muy documentado, así que no profundizare en este aspecto.

Open source projects

Cuando leía esta fascinante iniciativa lo primero que se me vino a la mente fue… escribiré mi propio servidor con juegos de azar y mujerzuelas, es muy sencillo 😛

        static void Main(string[] args)
        {
            const string msg = "Hola, yo soy tu server";
            const int port = 1450;
            var server = new TcpListener(IPAddress.Any, port);
            server.Start();
            Console.WriteLine("Servidor en linea...");
            while (true)
            {
                var socket = server.AcceptSocket();
                byte[] responseMessage = Encoding.ASCII.GetBytes(msg.ToCharArray(), 0, msg.Length);
                socket.Send(responseMessage);
                socket.Disconnect(false);
            }
        }

image

Pero ok, mejor olviden mi propia implementación y los juegos de azar, mejor olvídenlo todo y veamos verdaderas implementaciones hechas por la comunidad.

NOWIN

El primer proyecto de código abierto que clone fue NOWIN, según el autor, su implementación es de dos a tres veces mas rápida que HttpListener (paff sencillo) y Node JS (esto son palaras mayores :P). Implementar una aplicación con Nowin es bastante sencillo (En el código fuente  esta el mismo ejemplo):

    class Program
    {
        static void Main(string[] args)
        {
            var builder = ServerBuilder.New().SetPort(1450).SetOwinApp(Sample.App);
            using (builder.Start())
            {
                Console.WriteLine("Listening on port 1450. Enter to exit.");
                Console.ReadLine();
            }
        }
    }
    public class Sample
    {
        public static Task App(IDictionary arg)
        {
            var req = new Owin.Types.OwinRequest(arg);
            var resp = new Owin.Types.OwinResponse(req);
            if (req.Path == "/")
            {
                resp.StatusCode = 200;
                resp.AddHeader("Content-Type", "text/plain");
                resp.Write("Hello World!");
                return Task.Delay(0);
            }
            var p = Path.Combine(@"c:\Aplicacion", req.Path.Substring(1));
            if (File.Exists(p))
            {
                resp.StatusCode = 200;
                resp.AddHeader("Content-Type", "text/html");
                return resp.WriteAsync(File.ReadAllBytes(p));
            }
            resp.StatusCode = 500;
            return Task.Delay(0);
        }
    }

Lo que necesité:

image

Como luce:

image

Empleando Katana – Microsoft Hosting

En el ejemplo anterior con nowin no había una clara distinción del host y el server, pues cumplía el mismo objetivo. Veamos ahora una implementación con un componente de Katana, Microsoft.Owin.Hostin, es decir, no estamos haciendo uso de todos los componentes de katana, solo de lo que necesito! porque yo ya tengo mi server!… no es genial?! empleemos además un Web Api como framework, simplemente buscamos el Web Api OWIN en nuget y lo instalamos. Los paquetes en este ejemplo:

image

El código:

    class Program
    {
        static void Main()
        {

            var options = new StartOptions();
            options.Port = 1450;
            options.ServerFactory = "NowinWebServer";
            using (WebApp.Start(options))
            {
                Console.Write("Server en linea, puerto : {0}", options.Port);
                Console.ReadKey();
            }
        }
    }
    public class HolaMundoController : ApiController
    {
        public string Get()
        {
            return "Hola!!";
        }
    }
    public class Startup
    {
        public void Configuration(IAppBuilder builder)
        {
            var config = new HttpConfiguration();
            config.Routes.MapHttpRoute("Default", "api/{controller}/{id}", new { id = RouteParameter.Optional });
            builder.UseWebApi(config);
        }
    }

El resultado:

image

Y la mejor parte de todas es que no hay espacio a resultados mágicos inesperados! te puedes descargar los fuentes de Katana y ver que pasa tras la cortina.

Como Nowin, he visto una implementación de  Mark Rendle llamada Flux un server para .net y mono que no usa HttpListener o Fleck una implementación de Web Socket server. Todas disponibles para jugar su uso.

Hay además implementaciones de Frameworks como el buen NancyFX y SignalR, tenemos componentes independientes de autenticación en el mismo proyecto Katana, que si al ver su código no te gustan, bien puedes mejorarlas y contribuir al proyecto o buscarte el que mejor se acomode a tus necesidades entre varias posibles opciones de la comunidad.

Opinión

Como yo lo veo con esto se marca un nuevo rumbo para el desarrollo Web (bueno me uno a Eduard y digo que no solo Web!) en .net, no solo por las ventajas que iniciativas como OWIN en si mismas proponen, sino por algo que ha ido evolucionando mucho en nuestra comunidad (.net) este tipo de cosas son muy normales en node js por ejemplo, donde hay varias opciones que puedes buscar en internet para resolver afrontar problemas, si pones npm “x cosa” en el buscador habrá al menos un loco en el mundo que ha subido un paquete que puedes descargarte y emplear para resolver tu problema. Para muchos desarrolladores de una plataforma tan robusta como lo es .NET esto también se ve como  un arma de doble filo, pues puede que ahora nos llenemos de millones de paquetes basura compatibles con OWIN que saber cual escoger se haga una tarea muy complicada (de hecho esto si pasa en node) o simplemente existan muchos paquetes con un mínimo de documentación… en fin, estos son skills que hacen que una comunidad sea fuerte, contribuir en proyectos open source no siempre es solo escribir código nuevo, se puede ayudar con implementaciones existentes, dando feedback o documentando.

Para quienes escribimos software corporativo y que aun no implementamos en producción nada fuera de un robusto IIS, pues repito, esto no supone el fin de IIS / System Web, para NADA! podemos tomar un IIS como nuestro hosting con KATANA, seleccionar los middlewares que necesitamos y los Frameworks a emplear con el mismo poder de siempre. De hecho en proyectos con VS2013 Preview ya vemos implementaciones con Katana 😀

El tema del licenciamiento es algo que me llama mucho la atención, si estas iniciativas buscan una mejora constante y hace énfasis en la portabilidad no emplees en tus aportes cosas como la que había hecho Microsoft con Katana! que había indicado (como en muchos otros paquetes de Nuget) una Windows-only Restriction, por fortuna anunció que en la versión 2, la que estará con VS2013 ya no tendrá esta restricción.

Entre colegas he visto muy parcializadas las opiniones frente a este tema, algunos alegan que nada es perfecto y querer hacer .net mas parecido a otros no es bueno… en fin, Microsoft parece no estar rompiendo nada hacía atrás y con iniciativas como esta, que repito, es de la misma comunidad de usuarios, se empiezan a dar mayores opciones, mas herramientas que podemos escoger para resolver nuestros problemas.

Si tienes alguna opinión sobre el tema no dudes en dejar tu comentario.

Bien, por ahora dejo el tema hasta aquí, ha sido un post teórico-practico-opinión, como para organizar un poco las ideas que esto trae y como lo veo yo, mas adelante espero escribir mas centrado en Katana, sus middlewares y la interacción con productos de la comunidad. 😀

Hasta el próximo post

OWIN, Katana y open source projects