Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

18 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
miércoles, 18 de septiembre de 2013
Katana (imagen de http://www.real-sword.com)
Pues seguimos con esta serie de artículos sobre OWIN que comenzamos unos días atrás con una introducción conceptual de esta especificación, y hoy vamos a centrarnos en Katana, la implementación de Microsoft de este interesante estándar.

Primero explicaremos en qué consiste este proyecto, sus componentes principales, y después veremos la configuración y funcionamiento de este tipo de sistemas, acercándonos ya un poco al nivel que tanto nos gusta, el código fuente ;-)

Si es vuestro primer acercamiento al mundo de OWIN y Katana, os recomiendo que leáis previamente el primer artículo de la serie, Introducción a OWIN.

Conoce tu Katana, pequeño saltamontes

Katana (katanaproject.codeplex.com) es un proyecto open source liderado por Microsoft Open Tech que implementa un conjunto de componentes y herramientas destinadas a facilitar el alojamiento y desarrollo de aplicaciones web basadas en la especificación OWIN. Se distribuye bajo licencia Apache 2.0, e incluso se ha permitido expresamente el uso de los binarios en plataformas no Windows, algo que no estaba contemplado en las primeras versiones.

En Katana todos los componentes están diseñados teniendo en mente tres características básicas:
  • Portabilidad, que se consigue evitando el acoplamiento entre componentes. Esto hace que una pieza pueda ser sustituida por otra que cumpla su misma función, aunque se traten de implementaciones distintas, o incluso de plataformas distintas. Podremos ejecutar aplicaciones en cualquier tipo de host, servidor, o sistema operativo, siempre que el framework en el que estén desarrolladas sea compatible OWIN y se dispongan de los adaptadores apropiados.
  • Modularidad, que huye del enfoque tradicional del framework monolítico con decenas de opciones y funcionalidades (de las cuales al final sólo usábamos dos ;-)) y se concentra en crear componentes muy pequeños y especializados. El desarrollador será el que elija cuáles de ellos necesita para sus aplicaciones.
  • Escalabilidad, que se consigue aligerando peso de las aplicaciones al usarse sólo los módulos necesarios, muy especializados y eficientes, y el uso intensivo de asincronía.
Por cierto, me encanta el nombre Katana, al igual que todos los que tienen cierto aroma oriental como Ninject, Kendo, o Dojo. Debe ser cosa del Tao ;-D

El camino de la Katana

Diagrama conceptual de KatanaSu andadura comenzó en 2010 en GitHub, cuando todavía la especificación se encontraba en borradores muy preliminares.

La versión 1.0 no vio la luz hasta febrero de 2013,  y comenzó a ser utilizada para alojar aplicaciones Signalr, Nancy o FubuMVC, y sobre todo en escenarios self-hosting (hosting dentro de procesos no ASP.NET, como una aplicación de consola o un servicio Windows).

En la actualidad se encuentra en v2.0-RC. Es decir, queda poco para que esté disponible; previsiblemente acompañará al resto de productos cuyas nuevas versiones que llegarán este otoño, como WebAPI 2.0, SignalR 2.0, o Visual Studio 2013.

 Se puede, sin embargo, descargar las versiones prerelease a través de Nuget mientras la versión final aterriza activando este modo en el IDE, o añadiendo el switch –pre a las instrucciones de consola como install-package o get-package.

Piezas de la Katana

Katana components locationEl proyecto Katana está compuesto por un buen número de componentes independientes que podemos incluir en nuestros proyectos cuando sean necesarios. En general, incluye:
  • Hosts. Como recordaremos, básicamente los hosts eran los procesos que ejecutaban las aplicaciones. Katana viene acompañada componentes que permiten alojar servicios basados en OWIN sobre IIS/ASP.NET, en cual tipo de proceso mediante self-hosting, e incluso una aplicación de línea de comandos (OwinHost.exe) para lanzar servicios.
  • Servers, que sabemos que son los componentes que escuchan las peticiones. Actualmente hay servidores basados en HTTP listeners de .NET, ideales para escenarios self-hosting, así como adaptadores para “engancharse” a ASP.NET/IIS.
  • Módulos middleware de uso genérico, como módulos de compresión, seguridad (cookies, basic, Active Directory, OAuth, etc.), acceso a archivos estáticos, soporte CORS, y algunos más).
  • Adaptadores para frameworks existentes como SignalR o WebAPI.
  • Infraestructura para el arranque y configuración del pipeline OWIN que implementa el procedimiento de startup definido por el estándar y que vimos en el post anterior.
  • Infraestructura para la creación de nuevos middlewares o adaptadores de frameworks personalizados.
Todos estos componentes son publicados en Nuget, y salvo, algunas excepciones, tienen la denominación Microsoft.Owin.*. De nuevo, recordaros que, aunque por poco tiempo, todavía se encuentran en prerelease.

Aparte, en Nuget existen otros paquetes interesantes relacionados con OWIN, aunque no forman parte de Katana, y es interesante echar un ojo de vez en cuando.

Empuñando la Katana

Hace unos días hablábamos de que OWIN define claramente cuál es el procedimiento de arranque de las aplicaciones que se basan en esta especificación. Por recordarlo rápidamente, poco más o menos es así:
  1. Host y Server cargan datos de entorno e inicialización en un diccionario.
  2. Se ejecuta el código de arranque de la Aplicación suministrándole dicho diccionario. La aplicación utiliza el diccionario para configurar su pipeline, es decir, la cadena de módulos que procesarán las peticiones.
  3. Se inicia el Server, quedando a la espera de peticiones. Cada petición será procesada a través del pipeline creado por la Aplicación.
Pues bien, Katana contiene la infraestructura para poder realizar de forma sencilla todos estos pasos, cuya implementación puede variar ligeramente dependiendo del tipo de aplicación de que se trate:
  • En aplicaciones web, utilizaremos el paquete Microsoft.Owin.Host.SystemWeb para adaptar ASP.NET/ISS a OWIN. No tendremos que encargarnos de iniciar el Host ni el  Server.
  • En otras aplicaciones .NET (apps de consola, forms, servicios windows…), usaremos self-hosting y el paquete Microsoft.Owin.Host.HttpListener. En este caso, tendremos que encargarnos manualmente de crear el Host e iniciar el Server para poder comenzar a prestar servicios.
Más adelante veremos ejemplos de uso de ambos escenarios.

En cualquier caso, como desarrolladores de aplicaciones, siempre tendremos que configurar el pipeline de proceso de peticiones.

Por seguir la convención propuesta por Katana, la configuración la realizaremos en el método Configuration() de una clase llamada Startup que se encontrará en el espacio de nombres raíz de la aplicación. En realidad, más adelante veremos que no es algo tan rígido, y podemos modificar a nuestro antojo esta ubicación.

Generalmente, una la clase de inicialización OWIN tiene la siguiente pinta:
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        // App & pipeline configuration
    }
}
El parámetro IAppBuilder que recibe este método es el punto central desde donde tendremos acceso al diccionario de entorno poblado por el Host y el Server, y configuraremos el pipeline. Su definición es la siguiente:
public interface IAppBuilder
{
    IDictionary<string, object> Properties { get; }
    IAppBuilder Use(object middleware, params object[] args);
    object Build(Type returnType);
    IAppBuilder New();
}
Los métodos Build() y New() son utilizados de forma interna, y también pueden ser útiles para cuando hayamos conseguido el cinturón negro, por lo que no los veremos ahora. Más interesantes y asequibles en este momento son Properties y Use().

Properties contiene el diccionario de entorno, donde podemos encontrar información interesante como el nombre de la aplicación, información sobre el host, factorías de logging y trazas, características del servidor y algunas cosas más. El aspecto que tiene en ejecución es el siguiente:

Aspecto del diccionario de contexto
El método Use(), definido también sobre el interfaz IAppBuilder, es el que permite añadir sucesivos middlewares al pipeline, que internamente se irán introduciendo en una lista que compone la cadena de módulos responsables de procesar las peticiones. Aunque se puede utilizar directamente el método definido en el interfaz, lo habitual es usar otras sobrecargas y métodos extensores que lo pongan más fácil. Por ejemplo, la configuración de una aplicación podría ser la mostrada a continuación; ojo, que los middlewares mostrados son ejemplos, no existen:
public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.Use<LogginMiddleware>();
        app.Use<IpFilterMiddleware>();
        app.Use<StaticFileMiddleware>();
    }
}
Pipeline simpleCon esta configuración estaríamos indicando que cuando llegue una petición, y tras poblar el diccionario con datos de la misma y su contexto, se invocará al módulo LogginMiddleware. Éste podría, por ejemplo, guardar determinados datos de la petición en un log, y una vez terminado su trabajo, él mismo invocaría al siguiente módulo en el pipeline, IpFilterMiddleware.

IpFilterMiddleware podría, por ejemplo, comprobar si la IP origen de la petición se encuentra en un rango determinado. En caso negativo, retornaría al cliente un error HTTP 403 y la petición no continuaría ascendiendo por el pipeline. En caso afirmativo, en cambio, invocaría al siguiente módulo del pipeline, StaticFileMiddleware, quien finalmente podría retornar el contenido del archivo estático solicitado por el cliente.

Observad que el proceso de una petición, en definitiva, se trata de una cadena de ejecución cooperativa de middlewares, es decir, es cada módulo el responsable de invocar al siguiente eslabón en el pipeline. Si algún módulo decide cortocircuitar el proceso, todos los que estén por arriba ni siquiera se enterarán de que la petición llegó al servidor. O si algún módulo realiza una acción sobre el entorno, otros que se ejecutan posteriormente podrían deshacerla o anularla.

Y como este artículo está extendiéndose ya demasiado, lo dejamos aquí. La próxima vez saltaremos al tatami y veremos un par de ejemplos prácticos, continuando así nuestro camino hacia el cinturón negro ;-)


Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!