SlideShare una empresa de Scribd logo
INTERFACES REST
Filosofando sobre sentido de REST, el
universo, y todo lo demás…
… Y sí, esta charla durará 42 minutos 
Eduard Tomàs i Avellana
@eiximenis
etomas@pasiona.com
http://geeks.ms/blogs/etomas
?QUIEN SOY?
 Orgulloso poseedor de un Spectrum 48K
 Friki estándar: Amante de los videojuegos, la
música heavy, los juegos de rol de papel con
dados raros, la literatura fantástica y la ciencia
ficción
 Reconocido experto mundial en cervezas
 Trabajo en pasiona consulting
 Voy por ahí hablando de varias cosas gracias a
la fundación Techdencias
 Microsoft MVP en ASP.NET/IIS
¿CÓMO VA A SER ESA CHARLA¿
Pura filosofía 
ANTES DE EMPEZAR…
 … unas sabias palabras
¡¡¡AL LORO!!!!!
¡Que no os embauquen!
¡Que algunos dicen que son REST y NO lo son!
¿QUE ES REST?
 REST es un estilo arquitectónico que persigue la construcción de
sistemas altamente escalables basándose en 6 premisas
 Cliente / Servidor
 Sin estado
 Cacheable
 Sistema basado en capas
 Interfaz unificada
 Code on demand
DE VERDAD… ¿QUÉ ES REST?
Una forma de pensar
PIRÁMIDE DE MADUREZ DE REST
PIRÁMIDE DE MADUREZ REST – NIVEL 0
 Usar HTTP como protocolo de transporte
POST /appointmentService HTTP/1.1
<openSlotRequest date = "2010-01-04" doctor =
"mjones"/>
HTTP/1.1 200 OK
<openSlotList>
<slot start = "1400" end = "1450">
<doctor id = "mjones"/>
</slot>
</openSlotList>
PIRÁMIDE DE MADUREZ REST – NIVEL 1
 Usar recursos
POST /doctors/mjones HTTP/1.1
<openSlotRequest date = "2010-01-04"/>
HTTP/1.1 200 OK
<openSlotList>
<slot id = "1234" doctor = "mjones" start =
"1400" end = "1450"/>
</openSlotList>
POST slots/1234 HTTP/1.1
<appointmentRequest>
<patient name=“jsmith” />
</appointmentRequest>
PIRÁMIDE DE MADUREZ REST – NIVEL 2
 Usar verbos http
GET /doctors/mjones?date=20100104&status=open HTTP/1.1
HTTP/1.1 200 OK
<openSlotList>
<slot id = "1234" doctor = "mjones" start = "1400"
end = "1450"/>
</openSlotList>
POST slots/1234 HTTP/1.1
<appointmentRequest>
<patient name=“jsmith” />
</appointmentRequest>
PIRÁMIDE DE MADUREZ REST – NIVEL 3
 Usar códigos de respuesta HTTP
POST slots/1234 HTTP/1.1
<appointmentRequest>
<patient name=“jsmith” />
</appointmentRequest>
HTTP/1.1 201 Created
Location: /slots/1234/appointment
POST slots/1234 HTTP/1.1
<appointmentRequest>
<patient name=“jsmith” />
</appointmentRequest>
HTTP/1.1 409 Conflict
PIRÁMIDE DE MADUREZ REST – NIVEL
DIOS
 Usar hiperenlaces
GET /doctors/mjones/slots?date=20100104&status=open
HTTP/1.1 200 OK
<openSlotList>
<slot id = "1234" doctor = "mjones" start = "1400"
end = "1450">
<link rel = "/linkrels/slot/book"
uri = "/slots/1234"/>
</slot>
</openSlotList>
DISEÑANDO TU API REST
DECIDE DE QUE PARTE ESTÁS
RESTafari Pragmatico
NOMBRES DE LOS RECURSOS
 URLs representan recursos.
 Recursos son cosas.
 Las cosas tienen nombres
 Usa nombres en las URLs, NO verbos
 /doctors/1234 
 /getDoctor/1234 
NOMBRES DE LOS RECURSOS
 ¿Nombres en plural o en singular?
 GET /doctors/1234 (acceso a un doctor por id)
 GET /doctor/1234 (acceso a un doctor por id)
 Suele usarse más el plural, ya que por norma general
tenemos colecciones de recursos.
 En todo caso evita mezclas
VERBOS HTTP
 Usa los verbos HTTP.
 GET para consultas
 DELETE para eliminar
 PUT (y POST) para editar o añadir
 /GET doctors/1234
 /DELETE doctors/1234
 PUT doctors/1234
VERBOS HTTP: PUT VS POST
 PUT para añadir y POST para modificar.
 POST para añadir y PUT para modificar.
 PUT para añadir y modificar
 POST para añadir y modificar
 Entonces… ¿Cuando usar PUT y POST?
 Respuesta: PUT debe ser idempotente. POST no tiene por qué.
¡NOOOO!
¡NOOOO!
SIMPLIFICA LAS ASOCIACIONES
 Limita la longitud de tu URL
 Intenta evitar URLs más largas que /recurso/identificador/recurso
 Oculta toda la complejidad en la QueryString
 GET /doctors/1245/appointments/20130706/refused
 GET /doctors/1245/appointments?date=20130706&status=refused
 GET /doctors/1235/patients/2341/appointments
 GET /patients/2341/appointments
GESTIÓN DE ERRORES
 Usar códigos HTTP (y opcionalmente devolver info en el payload)
 Usar siempre HTTP 200 y devolver información en el payload
 La primera es más REST, pero la segunda es más compatible con
ciertos clientes que pueden no tratar bien ciertos códigos de error
(¿alguien dijo Flash?)
 Recomendación: Usa los códigos HTTP, pero ofrece una
alternativa para no usarlos y devolver el error en el paylaod.
CÓDIGOS HTTP
 3 grandes grupos de códigos
 2xx: Todo ha ido bien.
 4xx: Algo en la petición del cliente hace que haya habido un error. El
cliente debe modificar su petición
 5xx: Algo en el servidor hace que haya habido un error. El cliente NO
tiene por que modificar su petición
CÓDIGOS HTTP
 200 (OK)
 Úsalo como genérico de que todo ha ido bien
 201 (Created)
 Devuélvelo para notificar que se ha creado un elemento (insert)
 204 (No Content)
 Úsalo para indicar que todo ha ido bien y NO quieres enviar
respuesta alguna al cliente. Suele usarse en modificaciones o
borrados para indicar que han ido bien.
CÓDIGOS HTTP
 400 (Bad Request)
 Úsalo para indicar al cliente que debe modificar la petición. Añade
info en el payload.
 401 (Unauthorized)
 Úsalo para indicar que el cliente NO está autenticado y que el
recurso requiere de clientes autenticados. Que se autentique y lo
pruebe de nuevo.
 403 (Forbidden)
 Úsalo para indicar que aunque el cliente está autenticado, no
puede acceder al recurso. ¡Que no lo intente de nuevo!
CÓDIGOS HTTP
 404 (Not Found)
 Úsalo para informar que no se ha encontrado el recurso
especificado. Puede que la URL sea correcta y el recurso no se
encuentre.
 409 (Conflict)
 Úsalo para indicar casos de concurrencia en modificaciones o
borrados.
 410 (Gone)
 Úsalo para informar al cliente que aunque antes había un recurso
en esta URL ya no está (ni estará).
CÓDIGOS HTTP
 500 (Internal server Error)
 Úsalo para indicar que el servidor ha encontrado un error. Añade
info en el payload.
VERSIONAJE
 GET /doctors/123
 Qué versión de la API usa esta URL? ¿La primera? ¿La última más
actul?
 Si haces la versión opcional
 Y es la primera, los clientes antiguos no se benefician de
correcciones o mejoras de las nuevas versiones
 Y es la última, los clientes antiguos pueden dejar de funcionar
 Y alguna vez decides que deje de ser opcional, los clientes antiguos
dejarán de funcionar
VERSIONAJE
 No hagas la versión opcional
 Especificada en URL
 GET /v1/doctors/1234
 GET /2013-04-01/doctors/1234
 GET /doctors/1234?v=1
 …
 Especificada en header HTTP
 Evita demasiadas versiones
 GET /v1.2.1/doctors/1234
RESPUESTAS PARCIALES
 GET /doctors/1234
 Toda la información del doctor
 GET /doctors:(name, appointments)/1234
 GET /doctors/1234&fields=name,appointments
 Solo nombre, citas del doctor
 Ofrece un mecanismo para devolver parte de la respuesta y/o
añadir campos adicionales opcionales
MÚLTIPLES FORMATOS
 Hazle caso a “Accept”…
 … pero ofrece un mecanismo para “sobreescribir” accept
 GET /doctors.json/12345
 GET /doctors/12345?type=json
 GET /doctors/12345.json
AUTORIZACIÓN Y SEGURIDAD
 Usa OAuth para autorizar las llamadas a tu api.
 No reinventes la rueda
 Si además de la API tienes una aplicación web que la consume
considera:
 Poner ambas en el mismo origen web
 Usar JSONP
 Usar CORS
¿PREGUNTAS, DUDAS, CERVEZAS?
Eduard Tomàs i Avellana
@eiximenis
etomas@pasiona.com
http://geeks.ms/blogs/etomas

Más contenido relacionado

PDF
LAB Paso a paso: Migración GMAIL a Office 365 (AD FS 2.0 - DirSync)
PDF
Crear Usuarios Masivamente, Rápido y Sencillo - Active Directory
DOCX
Instalacion de joombla
DOC
Manual Asterisk
DOC
Manual asterisk-inst
DOCX
Instalar php en debian
PDF
Manual firebirdsql
PDF
Manual de phpsuexec
LAB Paso a paso: Migración GMAIL a Office 365 (AD FS 2.0 - DirSync)
Crear Usuarios Masivamente, Rápido y Sencillo - Active Directory
Instalacion de joombla
Manual Asterisk
Manual asterisk-inst
Instalar php en debian
Manual firebirdsql
Manual de phpsuexec

Similar a Interfaces rest (20)

PPTX
Desarrollando con APIs
PPT
Seguridad en web
PPTX
Introducción a REST - SymfonyVLC
ODP
Desarrollando un API con REST
PPTX
Integración de Tecnologías y Plataformas.pptx
PDF
Introducció a les Aplicació Web
PPTX
10-Unidad 3: Diseños de Vista-3.2 Usos Web Services
PDF
APACHE MYSQL SAMBA
PDF
PDF
Open Source Modern Web Development
PPTX
trabajo de informatica
PPTX
REST, JERSEY & SOAP
PPTX
Presentacion HTTP/HTTPS/DNS
ODP
Introducción a PHP5
DOC
PPTX
Protocolos de internet
ODP
[Flisol2011] Seguridad en el Desarrollo de Aplicaciones Web PHP
Desarrollando con APIs
Seguridad en web
Introducción a REST - SymfonyVLC
Desarrollando un API con REST
Integración de Tecnologías y Plataformas.pptx
Introducció a les Aplicació Web
10-Unidad 3: Diseños de Vista-3.2 Usos Web Services
APACHE MYSQL SAMBA
Open Source Modern Web Development
trabajo de informatica
REST, JERSEY & SOAP
Presentacion HTTP/HTTPS/DNS
Introducción a PHP5
Protocolos de internet
[Flisol2011] Seguridad en el Desarrollo de Aplicaciones Web PHP
Publicidad

Más de Eduard Tomàs (20)

PPTX
Kubernetes: Do's, don'ts and why's
PPTX
KCDS 2021- Escalando workloads serverless en Kubernetes con KEDA
PPTX
Escalando workloads serverless en Kubernetes con Keda
PPTX
C#9 - Más C# que nunca
PPTX
CollabDays 2020 Barcelona - Serverless Kubernetes with KEDA
PPTX
Keda o como convertir Kubernetess en Serverless
PPTX
.NET Memoria y Rendimiento
PPTX
Containers en .NET (Dot Net 2018 - Spain)
PPTX
Esos contenedores, ¡a producción! (Commit Conf 2018)
PPTX
Codemotion 2015 - Bienvenido de nuevo c++
PPTX
El "peor" lenguaje del mundo
PPTX
Containerize a netcore application with aks
PPTX
Escenarios avanzados en AKS (Global Azure Bootcamp Barcelona 2019)
PPTX
Aplicaciones de consola fáciles? Más quisieramos
PPTX
Serverless with Azure Functions and CosmosDb
PPTX
Docker y todo eso... más o menos
PPTX
Microservices: Yes or not?
PPTX
ASP.NET MVC Core
PPTX
Azure functions
PPTX
React native - Unleash the power of your device
Kubernetes: Do's, don'ts and why's
KCDS 2021- Escalando workloads serverless en Kubernetes con KEDA
Escalando workloads serverless en Kubernetes con Keda
C#9 - Más C# que nunca
CollabDays 2020 Barcelona - Serverless Kubernetes with KEDA
Keda o como convertir Kubernetess en Serverless
.NET Memoria y Rendimiento
Containers en .NET (Dot Net 2018 - Spain)
Esos contenedores, ¡a producción! (Commit Conf 2018)
Codemotion 2015 - Bienvenido de nuevo c++
El "peor" lenguaje del mundo
Containerize a netcore application with aks
Escenarios avanzados en AKS (Global Azure Bootcamp Barcelona 2019)
Aplicaciones de consola fáciles? Más quisieramos
Serverless with Azure Functions and CosmosDb
Docker y todo eso... más o menos
Microservices: Yes or not?
ASP.NET MVC Core
Azure functions
React native - Unleash the power of your device
Publicidad

Último (20)

DOCX
Trabajo colaborativo Grupo #2.docxmmuhhlk
PDF
Calidad desde el Docente y la mejora continua .pdf
PDF
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
PDF
Plantilla para Diseño de Narrativas Transmedia.pdf
PPTX
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
PPTX
Presentación PASANTIAS AuditorioOO..pptx
DOCX
Zarate Quispe Alex aldayir aplicaciones de internet .docx
PPT
introduccion a las_web en el 2025_mejoras.ppt
PPTX
Administración se srevidores de apliaciones
PPTX
IA de Cine - Como MuleSoft y los Agentes estan redefiniendo la realidad
PPTX
Introduccion a servidores de Aplicaciones (1).pptx
PDF
Estrategia de apoyo tecnología miguel angel solis
PDF
ACTIVIDAD 2.pdf j
PDF
SAP Transportation Management para LSP, TM140 Col18
PPT
Que son las redes de computadores y sus partes
PDF
Liceo departamental MICRO BIT (1) 2.pdfbbbnn
PPTX
Yogurt de tocosh (1).pptx preparacion receta
PDF
taller de informática - LEY DE OHM
PDF
Influencia-del-uso-de-redes-sociales.pdf
DOCX
Trabajo colaborativo Grupo #2.docxmkkkkkkl
Trabajo colaborativo Grupo #2.docxmmuhhlk
Calidad desde el Docente y la mejora continua .pdf
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
Plantilla para Diseño de Narrativas Transmedia.pdf
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
Presentación PASANTIAS AuditorioOO..pptx
Zarate Quispe Alex aldayir aplicaciones de internet .docx
introduccion a las_web en el 2025_mejoras.ppt
Administración se srevidores de apliaciones
IA de Cine - Como MuleSoft y los Agentes estan redefiniendo la realidad
Introduccion a servidores de Aplicaciones (1).pptx
Estrategia de apoyo tecnología miguel angel solis
ACTIVIDAD 2.pdf j
SAP Transportation Management para LSP, TM140 Col18
Que son las redes de computadores y sus partes
Liceo departamental MICRO BIT (1) 2.pdfbbbnn
Yogurt de tocosh (1).pptx preparacion receta
taller de informática - LEY DE OHM
Influencia-del-uso-de-redes-sociales.pdf
Trabajo colaborativo Grupo #2.docxmkkkkkkl

Interfaces rest

  • 1. INTERFACES REST Filosofando sobre sentido de REST, el universo, y todo lo demás… … Y sí, esta charla durará 42 minutos  Eduard Tomàs i Avellana @eiximenis etomas@pasiona.com http://geeks.ms/blogs/etomas
  • 2. ?QUIEN SOY?  Orgulloso poseedor de un Spectrum 48K  Friki estándar: Amante de los videojuegos, la música heavy, los juegos de rol de papel con dados raros, la literatura fantástica y la ciencia ficción  Reconocido experto mundial en cervezas  Trabajo en pasiona consulting  Voy por ahí hablando de varias cosas gracias a la fundación Techdencias  Microsoft MVP en ASP.NET/IIS
  • 3. ¿CÓMO VA A SER ESA CHARLA¿ Pura filosofía 
  • 4. ANTES DE EMPEZAR…  … unas sabias palabras ¡¡¡AL LORO!!!!! ¡Que no os embauquen! ¡Que algunos dicen que son REST y NO lo son!
  • 5. ¿QUE ES REST?  REST es un estilo arquitectónico que persigue la construcción de sistemas altamente escalables basándose en 6 premisas  Cliente / Servidor  Sin estado  Cacheable  Sistema basado en capas  Interfaz unificada  Code on demand
  • 6. DE VERDAD… ¿QUÉ ES REST? Una forma de pensar
  • 8. PIRÁMIDE DE MADUREZ REST – NIVEL 0  Usar HTTP como protocolo de transporte POST /appointmentService HTTP/1.1 <openSlotRequest date = "2010-01-04" doctor = "mjones"/> HTTP/1.1 200 OK <openSlotList> <slot start = "1400" end = "1450"> <doctor id = "mjones"/> </slot> </openSlotList>
  • 9. PIRÁMIDE DE MADUREZ REST – NIVEL 1  Usar recursos POST /doctors/mjones HTTP/1.1 <openSlotRequest date = "2010-01-04"/> HTTP/1.1 200 OK <openSlotList> <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/> </openSlotList> POST slots/1234 HTTP/1.1 <appointmentRequest> <patient name=“jsmith” /> </appointmentRequest>
  • 10. PIRÁMIDE DE MADUREZ REST – NIVEL 2  Usar verbos http GET /doctors/mjones?date=20100104&status=open HTTP/1.1 HTTP/1.1 200 OK <openSlotList> <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"/> </openSlotList> POST slots/1234 HTTP/1.1 <appointmentRequest> <patient name=“jsmith” /> </appointmentRequest>
  • 11. PIRÁMIDE DE MADUREZ REST – NIVEL 3  Usar códigos de respuesta HTTP POST slots/1234 HTTP/1.1 <appointmentRequest> <patient name=“jsmith” /> </appointmentRequest> HTTP/1.1 201 Created Location: /slots/1234/appointment POST slots/1234 HTTP/1.1 <appointmentRequest> <patient name=“jsmith” /> </appointmentRequest> HTTP/1.1 409 Conflict
  • 12. PIRÁMIDE DE MADUREZ REST – NIVEL DIOS  Usar hiperenlaces GET /doctors/mjones/slots?date=20100104&status=open HTTP/1.1 200 OK <openSlotList> <slot id = "1234" doctor = "mjones" start = "1400" end = "1450"> <link rel = "/linkrels/slot/book" uri = "/slots/1234"/> </slot> </openSlotList>
  • 14. DECIDE DE QUE PARTE ESTÁS RESTafari Pragmatico
  • 15. NOMBRES DE LOS RECURSOS  URLs representan recursos.  Recursos son cosas.  Las cosas tienen nombres  Usa nombres en las URLs, NO verbos  /doctors/1234   /getDoctor/1234 
  • 16. NOMBRES DE LOS RECURSOS  ¿Nombres en plural o en singular?  GET /doctors/1234 (acceso a un doctor por id)  GET /doctor/1234 (acceso a un doctor por id)  Suele usarse más el plural, ya que por norma general tenemos colecciones de recursos.  En todo caso evita mezclas
  • 17. VERBOS HTTP  Usa los verbos HTTP.  GET para consultas  DELETE para eliminar  PUT (y POST) para editar o añadir  /GET doctors/1234  /DELETE doctors/1234  PUT doctors/1234
  • 18. VERBOS HTTP: PUT VS POST  PUT para añadir y POST para modificar.  POST para añadir y PUT para modificar.  PUT para añadir y modificar  POST para añadir y modificar  Entonces… ¿Cuando usar PUT y POST?  Respuesta: PUT debe ser idempotente. POST no tiene por qué. ¡NOOOO! ¡NOOOO!
  • 19. SIMPLIFICA LAS ASOCIACIONES  Limita la longitud de tu URL  Intenta evitar URLs más largas que /recurso/identificador/recurso  Oculta toda la complejidad en la QueryString  GET /doctors/1245/appointments/20130706/refused  GET /doctors/1245/appointments?date=20130706&status=refused  GET /doctors/1235/patients/2341/appointments  GET /patients/2341/appointments
  • 20. GESTIÓN DE ERRORES  Usar códigos HTTP (y opcionalmente devolver info en el payload)  Usar siempre HTTP 200 y devolver información en el payload  La primera es más REST, pero la segunda es más compatible con ciertos clientes que pueden no tratar bien ciertos códigos de error (¿alguien dijo Flash?)  Recomendación: Usa los códigos HTTP, pero ofrece una alternativa para no usarlos y devolver el error en el paylaod.
  • 21. CÓDIGOS HTTP  3 grandes grupos de códigos  2xx: Todo ha ido bien.  4xx: Algo en la petición del cliente hace que haya habido un error. El cliente debe modificar su petición  5xx: Algo en el servidor hace que haya habido un error. El cliente NO tiene por que modificar su petición
  • 22. CÓDIGOS HTTP  200 (OK)  Úsalo como genérico de que todo ha ido bien  201 (Created)  Devuélvelo para notificar que se ha creado un elemento (insert)  204 (No Content)  Úsalo para indicar que todo ha ido bien y NO quieres enviar respuesta alguna al cliente. Suele usarse en modificaciones o borrados para indicar que han ido bien.
  • 23. CÓDIGOS HTTP  400 (Bad Request)  Úsalo para indicar al cliente que debe modificar la petición. Añade info en el payload.  401 (Unauthorized)  Úsalo para indicar que el cliente NO está autenticado y que el recurso requiere de clientes autenticados. Que se autentique y lo pruebe de nuevo.  403 (Forbidden)  Úsalo para indicar que aunque el cliente está autenticado, no puede acceder al recurso. ¡Que no lo intente de nuevo!
  • 24. CÓDIGOS HTTP  404 (Not Found)  Úsalo para informar que no se ha encontrado el recurso especificado. Puede que la URL sea correcta y el recurso no se encuentre.  409 (Conflict)  Úsalo para indicar casos de concurrencia en modificaciones o borrados.  410 (Gone)  Úsalo para informar al cliente que aunque antes había un recurso en esta URL ya no está (ni estará).
  • 25. CÓDIGOS HTTP  500 (Internal server Error)  Úsalo para indicar que el servidor ha encontrado un error. Añade info en el payload.
  • 26. VERSIONAJE  GET /doctors/123  Qué versión de la API usa esta URL? ¿La primera? ¿La última más actul?  Si haces la versión opcional  Y es la primera, los clientes antiguos no se benefician de correcciones o mejoras de las nuevas versiones  Y es la última, los clientes antiguos pueden dejar de funcionar  Y alguna vez decides que deje de ser opcional, los clientes antiguos dejarán de funcionar
  • 27. VERSIONAJE  No hagas la versión opcional  Especificada en URL  GET /v1/doctors/1234  GET /2013-04-01/doctors/1234  GET /doctors/1234?v=1  …  Especificada en header HTTP  Evita demasiadas versiones  GET /v1.2.1/doctors/1234
  • 28. RESPUESTAS PARCIALES  GET /doctors/1234  Toda la información del doctor  GET /doctors:(name, appointments)/1234  GET /doctors/1234&fields=name,appointments  Solo nombre, citas del doctor  Ofrece un mecanismo para devolver parte de la respuesta y/o añadir campos adicionales opcionales
  • 29. MÚLTIPLES FORMATOS  Hazle caso a “Accept”…  … pero ofrece un mecanismo para “sobreescribir” accept  GET /doctors.json/12345  GET /doctors/12345?type=json  GET /doctors/12345.json
  • 30. AUTORIZACIÓN Y SEGURIDAD  Usa OAuth para autorizar las llamadas a tu api.  No reinventes la rueda  Si además de la API tienes una aplicación web que la consume considera:  Poner ambas en el mismo origen web  Usar JSONP  Usar CORS
  • 31. ¿PREGUNTAS, DUDAS, CERVEZAS? Eduard Tomàs i Avellana @eiximenis etomas@pasiona.com http://geeks.ms/blogs/etomas