martes, 5 de noviembre de 2013
Hasta ahora, por simplificar, siempre hemos utilizado
Hoy vamos a ver
Pero antes, para lo que acabáis de llegar, este es un resumen de lo que llevamos de serie:
Otro escenario frecuente es que puedan necesitarse distintos pipelines también función de la URL de la petición. Esto puede ocurrir, por ejemplo, si en el mismo contexto OWIN conviven distintas aplicaciones, cada una implementada sobre un framework (compatible OWIN, por supuesto).
Gráficamente, el siguiente diagrama muestra un posible escenario de convivencia entre un servidor de archivos estáticos, un servicio en tiempo real de SignalR a escuchando en “/SignalR” y, por ejemplo, servicios REST expuestos con NancyFx a partir de la dirección “/API”. Aunque existe un tronco común, cada rama del pipeline incluye los middlewares que necesita para funcionar:
Un escenario como este no sería sencillo implementarlo añadiendo los módulos al pipeline directamente con
Su uso es conceptualmente muy sencillo. Basta con indicar la porción de URL para la cual vamos a crear el pipeline, y un delegado o lambda en la que recibiremos el
Así, el diagrama anterior podríamos implementarlo con el siguiente código (ojo, los nombres de módulos middleware no son reales, es sólo para que pilléis la idea):
También podemos llamar a
Se trata de nuevo de un extensor sobre
Bueno, y lo dejamos aquí de momento. Aunque creo que ya hemos visto lo principal para poder enfrentarnos a nuestros enemigos Katana en mano, aún nos faltan algunas cosillas por tratar en la serie para poder aspirar al cinturón negro. Seguiremos con ello en próximos posts.
Publicado en Variable not found.
Use()
para introducir módulos en el pipeline, aunque también vimos que existen middlewares que aportan sus propios extensores sobre IAppBuilder
para que resulte más sencilla su utilización.Hoy vamos a ver
Map()
y Run()
otros extensores que, al igual que Use()
, nos permiten insertar módulos en el pipeline, aunque en este caso están orientados a cubrir escenarios más específicos.Pero antes, para lo que acabáis de llegar, este es un resumen de lo que llevamos de serie:
- OWIN (I): Introducción fue un primer acercamiento a la conceptual especificación OWIN, sus objetivos y componentes.
- En OWIN (II)- Katana, cinturón blanco vimos qué era Katana, sus principales piezas, y su funcionamiento a alto nivel.
- Seguidamente, en OWIN y Katana (III)- Primeros combates creamos ya nuestras primeras aplicaciones basadas en Katana, una en entorno web y otra usando self-hosting sobre una aplicación de consola.
- OWIN y Katana (IV)- Startup y Configuration muestra el proceso de arranque de las aplicaciones OWIN, y dónde podemos implementar su código de inicialización.
- En el más reciente, OWIN y Katana (V): middlewares personalizados, aprendimos a crear nuestros middlewares personalizados y a comprender cómo funciona la cadena de ejecución del pipeline.
1. Selección por URL, un patrón habitual
Observad un middleware que creamos en la anterior entrega de la serie:public class Startup { public void Configuration(IAppBuilder app) { app.Use((context, nextModule) => { if (context.Request.Path.StartsWith("/hello") && !string.IsNullOrWhiteSpace(context.Request.Query.Get("name"))) { return context.Response.WriteAsync("Hello, " + context.Request.Query.Get("name") ); } return nextModule(); }); // Other modules } }Ese “if” que vemos ahí arriba es un patrón muy habitual, pues muy frecuentemente nos encontraremos con módulos que sólo deben realizar sus tareas para una serie de URLs predeterminadas, como ocurre en el ejemplo anterior, que procesábamos únicamente las peticiones dirigidas a la dirección “/hello”.
Otro escenario frecuente es que puedan necesitarse distintos pipelines también función de la URL de la petición. Esto puede ocurrir, por ejemplo, si en el mismo contexto OWIN conviven distintas aplicaciones, cada una implementada sobre un framework (compatible OWIN, por supuesto).
Gráficamente, el siguiente diagrama muestra un posible escenario de convivencia entre un servidor de archivos estáticos, un servicio en tiempo real de SignalR a escuchando en “/SignalR” y, por ejemplo, servicios REST expuestos con NancyFx a partir de la dirección “/API”. Aunque existe un tronco común, cada rama del pipeline incluye los middlewares que necesita para funcionar:
Un escenario como este no sería sencillo implementarlo añadiendo los módulos al pipeline directamente con
Use()
, como hemos hecho hasta ahora. Y por eso existe Map()
.2. El extensor Map()
Map()
es un extensor de IAppBuilder
aportado por Katana para facilitar la creación de “branches” o ramas en el pipeline OWIN a partir de una porción de URL. Su uso es conceptualmente muy sencillo. Basta con indicar la porción de URL para la cual vamos a crear el pipeline, y un delegado o lambda en la que recibiremos el
IAppBuilder
específico para esa rama y sobre la cual debemos añadir los módulos que deseamos sean ejecutados.Así, el diagrama anterior podríamos implementarlo con el siguiente código (ojo, los nombres de módulos middleware no son reales, es sólo para que pilléis la idea):
public void Configuration(IAppBuilder app) { // Main pipeline app.Use<ErrorHandlerMiddleware>(); // New branch app.Map("/Signalr", signalrBuilder => { // SignalR pipeline signalrBuilder.Use<CorsMiddleware>(); signalrBuilder.Use<SignalRMiddleware>(); }); // New branch app.Map("/API", apiBuilder => { // API pipeline apiBuilder.Use<CorsMiddleware>(); apiBuilder.Use<LoggingMiddleware>(); apiBuilder.Use<NancyFxMiddleware>(); }); // Main pipeline again app.Use<CompressionMiddleware>(); app.Use<StaticFilesMiddleware>(); }Internamente, el extensor
Map()
crea un nuevo pipeline (un objeto IAppBuilder
) para la rama y se lo envía a la lambda o delegado que hayamos especificado para que lo configure. Tras ello, añade un módulo de tipo MapMiddleware
al pipeline principal (o aquél donde lo hayamos definido), que es el que se encargará en tiempo de ejecución de analizar la URL de la petición y enviarla al primer middleware de la rama asociada a dicha dirección.También podemos llamar a
Map()
desde dentro de una rama, lo que crearía una subdivisión en ésta para procesar las peticiones dirigidas a direcciones específicas:app.Map("/API", apiBuilder => { apiBuilder.Map("/blob", apiBlobBuilder => { apiBlobBuilder.Use<CompressionMiddleware>(); apiBlobBuilder.Use<BlobManagementMiddleware>(); }); apiBuilder.Use<CorsMiddleware>(); apiBuilder.Use<LoggingMiddleware>(); apiBuilder.Use<NancyFxMiddleware>(); });A la hora de crear ramas, hay que tener en cuenta que:
- Las URL siempre deben comenzar con una barra “/”, pero son relativas a la dirección de inicio de la rama en la que nos encontramos. En el ejemplo anterior, se accedería al pipeline para tratar blobs a través de la dirección "/API/blob".
- Una vez la petición entra en una rama, ésta debe procesarla por completo, pues no se ejecutarán los módulos definidos en otras ramas, ni siquiera el tronco desde el que han partido.
MapWhen()
, que funciona exactamente igual que Map()
, salvo en que no utiliza la URL como criterio para determinar si la petición debe pasar a la rama o no. En este caso, la decisión se tomará evaluando un predicado que le habremos suministrado en la llamada:app.MapWhen(ctx => ctx.Request.User.Identity.IsAuthenticated, authenticatedUserBuilder => { // Pipeline for authenticated users authenticatedUserBuilder.Use<Middleware1>(); authenticatedUserBuilder.Use<Middleware2>(); ... });
3. Usar middlewares finales: Run()
Run()
es otro extensor que permite añadir middlewares al pipeline, aunque en este caso es bastante más limitado, por lo que vamos a despacharlo pronto ;-)Se trata de nuevo de un extensor sobre
IAppBuilder
, que sirve para añadir un middleware final en el pipeline, es decir, un módulo que procesará de forma completa las peticiones sin dar oportunidad a los siguientes módulos a ejecutarse. Su uso, igual de sencillo que el resto; debemos suministrar como argumento una lambda que recibe el contexto de la petición (IOwinContext
) y retorna la tarea que se encargará de procesarla:public void Configuration(IAppBuilder app) { app.Run(ctx=> ctx.Response.WriteAsync("Hello, world!" )); }En esta aplicación, todas las peticiones serán procesadas de la misma forma, retornando el clásico “hola, mundo” al cliente.
Bueno, y lo dejamos aquí de momento. Aunque creo que ya hemos visto lo principal para poder enfrentarnos a nuestros enemigos Katana en mano, aún nos faltan algunas cosillas por tratar en la serie para poder aspirar al cinturón negro. Seguiremos con ello en próximos posts.
Publicado en Variable not found.
Publicado por José M. Aguilar a las 9:05 a. m.
Etiquetas: katana, owin, tutorial, tutorial-owin-katana
Aún no hay comentarios, ¡sé el primero!
Enviar un nuevo comentario