Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Ruby

Cantando con Sinatra - La repeticion

by
Read Time:11 minsLanguages:
This post is part of a series called Singing with Sinatra.
Singing With Sinatra: The Recall App

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

¡Bienvenido de nuevo a Cantando con Sinatra! En esta tercera y última parte, ampliaremos la aplicación "Recall" que creamos en la lección anterior. Vamos a agregar un feed RSS a la aplicación con la gema Builder increíblemente útil, lo que hace que la creación de archivos XML en Ruby sea pan comido. Aprenderemos lo fácil que es Sinatra para evitar el escape de HTML de los datos del usuario para evitar ataques XSS, y mejoraremos algunos de los códigos de manejo de errores.


Los usuarios son malos

La regla general al construir aplicaciones web es ser paranoico. Paranoico que cada uno de tus usuarios intenta atraparte destruyendo tu sitio o atacando a otros usuarios a través de él. En su aplicación, intente agregar una nueva Nota con el siguiente contenido:

Actualmente nuestros usuarios son libres de ingresar el HTML que quieran. Esto deja la aplicación abierta a ataques XSS donde un usuario puede ingresar malico JavaScript para atacar o desviar a otros usuarios del sitio. Entonces, lo primero que tenemos que hacer es eliminar todo el contenido enviado por el usuario para que el código anterior se convierta en entidades HTML, así:

Para ello, agregue el siguiente bloque de código a su archivo recall.rb, por ejemplo, bajo DataMapper.auto_upgrade! línea: alerta ("haha") Eche un vistazo a su página de edición, y puede ver que hemos cerrado el área de texto y para que se ejecute la alerta de JavaScript. Así que claramente tenemos que escapar del contenido de la nota en cada página donde se muestra.Dentro de su archivo de vista views / edit.erb, escape el contenido dentro del área de texto ejecutándolo a través del método h (línea 4):

Esto incluye un conjunto de métodos proporcionados por Rack. Ahora tenemos acceso a un método h() para escapar de HTML.

Para escapar de HTML en la página de inicio, abra el archivo de vistas views/home.erb y cambie la línea <%= note.content %> (alrededor de la línea 11) a:

Alternativamente, podríamos haber escrito esto como <%= h(note.content) %>, pero el estilo anterior es mucho más común en la comunidad de Ruby. Actualice la página y el código HTML enviado ahora debe ser escapado y no ejecutado por el navegador:

XSS en otras páginas

Haga clic en el enlace "editar" para la nota con el código XSS, y puede pensar que es seguro, está todo dentro de un área de texto, y por lo tanto no se está ejecutando. Pero, ¿y si agregamos una nueva nota con el siguiente contenido?

Eche un vistazo a su página de edición, y puede ver que hemos cerrado el área de texto y para que se ejecute la alerta de JavaScript. Así que claramente tenemos que escapar del contenido de la nota en cada página donde se muestra.

Dentro de su archivo de vista views/edit.erb, escape el contenido dentro del textarea ejecutándolo a través del método h (línea 4):

Y haz lo mismo en tu archivo views/delete.erb en la línea 2:

Ahí lo tienes, ahora estamos a salvo de XSS. ¡Solo recuerde escapar de todos los datos enviados por el usuario cuando cree otras aplicaciones web en el futuro!

Usted se estará preguntando "¿qué pasa con las inyecciones de SQL?" Bueno, DataMapper maneja eso para nosotros siempre que usemos los métodos de DataMapper para obtener datos de la base de datos (es decir, que no ejecute SQL sin formato).


RSS Alimenta a las masas

Una parte importante de cualquier sitio web dinámico es alguna forma de alimentación RSS, ¡y nuestra aplicación Recall no será la excepción! Afortunadamente, es increíblemente fácil crear feeds gracias a la gema de Builder. Se Instala con:

Dependiendo de cómo haya configurado RubyGems en su sistema, es posible que necesite prefijar la gem install con sudo.

Ahora agregue una nueva ruta a su archivo de solicitud recall.rb para una solicitud GET a /rss.xml:

Asegúrese de agregar esta ruta en algún lugar por encima de la ruta get '/:id', de lo contrario, una solicitud de rss.xml se confundiría con una ID de publicación.

En la ruta, simplemente solicitamos todas las notas de la base de datos y cargamos un archivo de vista de rss.builder. Tenga en cuenta que anteriormente estábamos usando el motor ERB para mostrar un archivo .erb, ahora estamos usando Builder para procesar un archivo. Un archivo de compilación es principalmente un archivo Ruby normal con un objeto xml especial para crear etiquetas XML.

Comience su archivo de vista views/rss.builder con lo siguiente:

Nota muy importante: en el primer segundo del bloque de código anterior, elimine el punto (.) En el texto::.xml. WordPress está interfiriendo con los fragmentos de código.

El constructor analizará esto para que sea:

Así que comenzamos creando la estructura para un archivo XML válido. Ahora agreguemos etiquetas para el título del feed, la descripción y un enlace al sitio principal. Agregue lo siguiente dentro del bloque xml.channel do: en la línea 5 a:

Observe cómo obtenemos la URL actual del objeto de solicitud request. Podríamos codificar esto de forma manual, pero la idea es que pueda cargar la aplicación en cualquier lugar sin tener que cambiar piezas de código poco claras.

Sin embargo, hay un problema, el enlace ahora está configurado a (por ejemplo) http://localhost:9393/rss.xml. Lo ideal sería que el enlace fuera a la página de inicio y no a la fuente. El objeto request también tiene un método path_info que se establece en la cadena de ruta actual; entonces en nuestro caso, /rss.xml.

Sabiendo esto, ahora podemos usar el método chomp de Ruby para eliminar la ruta desde el final de la URL. Cambie la línea xml.link request.url a:

El enlace en nuestro archivo XML ahora está configurado en http://localhost:9393. Ahora podemos recorrer cada nota y crear un nuevo elemento XML para eso:

Tenga en cuenta que en las líneas 3 y 7 escapamos del contenido de la nota usando h, tal como lo hicimos en las vistas principales. Es un poco extraño mostrar el mismo contenido tanto para el title como para las etiquetas de description, pero estamos siguiendo el ejemplo de Twitter aquí, y no hay otros datos que podamos poner allí.

En la línea 6 estamos convirtiendo la nota creada created_at en tiempo RFC822, el formato requerido para las horas en los canales RSS.

¡Pruébelo en un navegador! Vaya a /rss.xml y sus notas se deben mostrar correctamente.


NTR No te repitas

Hay un pequeño problema con nuestra implementación. En nuestra vista de RSS, tenemos el título y la descripción del sitio. También los tenemos en el archivo views/layout.erb para la parte principal del sitio. Pero ahora, si quisiéramos cambiar el nombre o la descripción del sitio, hay dos lugares diferentes que necesitamos actualizar. Una mejor solución sería establecer el título y la descripción en un solo lugar, luego hacer referencia a ellos desde allí.

Dentro del archivo de la aplicación recall.rb, agregue las siguientes dos líneas a la parte superior del archivo, directamente después de las instrucciones require, para definir dos constantes:

Ahora de vuelta dentro de views/rss.builder cambia las líneas 4 y 5 a:

Y en views/layout.erb, cambie la etiqueta <title> en la línea 5 a:

Y cambie las etiquetas de título h1 y h2 en las líneas 12 y 13 a:

También deberíamos incluir un enlace al feed RSS en el encabezado head de la página para que los navegadores puedan mostrar un botón RSS en la barra de direcciones. Agregue lo siguiente directamente antes de la etiqueta </head>


Mensajes Rapidos de Errores y éxitos

Necesitamos alguna manera de informar al usuario cuando algo salió mal, o bien, como un mensaje de confirmación cuando se agrega una nota nueva, una nota eliminada, etc.

La forma más común y lógica de lograr esto es a través de "mensajes instantáneos": un breve mensaje agregado a la sesión del navegador del usuario, que se muestra y borra en la página siguiente que ven. ¡Y resulta que hay un par de RubyGems para ayudar a lograr esto! Ingrese lo siguiente en la Terminal para instalar Rack Flash y Sinatra Redirect con gem Flash:

Dependiendo de cómo haya configurado RubyGems en su sistema, es posible que necesite prefijar la instalación de gem install con sudo.

Requiera las gemas y active su funcionalidad agregando lo siguiente cerca de la parte superior de su archivo de solicitud recall.rb:

Agregar un nuevo mensaje flash es tan simple como flash[:error] = "Something went wrong!". Vamos a mostrar un error en la página de inicio cuando no hay notas en la base de datos.

Cambie su ruta get '/' a:

Muy simple. Si la variable de instancia de @notes está vacía, crea un nuevo error de flash. Para visualizar estos mensajes flash en la página, agregue lo siguiente a su archivo views/layout.erb, antes de <%= yield %>:

Y agregue los siguientes estilos a su archivo public/style.css para mostrar los avisos en verde y los errores en rojo:

Ahora su página de inicio debe mostrar el mensaje "no se encontraron notas" cuando la base de datos está vacía:

Ahora visualicemos un mensaje de error o de éxito dependiendo de si se puede agregar una nueva nota a la base de datos. Cambie su ruta de post '/' a:

El código es bastante lógico. Si la nota se puede guardar, redirija a la página de inicio, con un mensaje flash 'aviso', de lo contrario redirigir a casa con un mensaje de error. Aquí puede ver la sintaxis alternativa para configurar un mensaje flash y redirigir la página ofrecida por la gema Sinatra-Redirect-With-Flash.

También sería ideal mostrar un error en la página 'editar nota' si la nota solicitada no existe. Cambie la ruta get '/:id' a:

Y también en la página de solicitud de PUT para actualizar una nota. Cambiar put '/:id' a:

Cambia la ruta get '/:id/delete' a:

Y su correspondiente solicitud DELETE, delete '/:id' a:

Finalmente, cambie la ruta get '/:id/complete' por la siguiente:


¡Y ahí lo tienes!

¡Una aplicación web que funciona, es segura y responde a errores escrita en una cantidad sorprendentemente pequeña de código! En esta breve mini serie, hemos aprendido a procesar varias solicitudes HTTP con una interfaz RESTful, manejar envíos de formularios, escapar de contenido potencialmente peligroso, conectarse con una base de datos, trabajar con Sesiones de usuarios para mostrar mensajes flash, generar un flujo RSS dinámico y cómo manejar con gracia los errores de la aplicación.

Si desea llevar la aplicación más allá, es posible que desee considerar la autenticación de usuarios, como con la gema Sinatra Authentication.

Si desea implementar la aplicación en un servidor web, como Sinatra está construido con Rake, puede instalar fácilmente sus aplicaciones Sinatra en servidores Apache y Nginx instalando Passenger.

Alternativamente, echa un vistazo a Heroku, una plataforma de alojamiento de Git que hace que la implementación de tus aplicaciones web de Ruby sea tan sencilla como git push heroku (¡las cuentas gratuitas están disponibles!)   

Si desea obtener más información sobre Sinatra, consulte el archivo Readme muy detallado, las páginas de documentación y el libro gratuito Sinatra.

Nota: los archivos fuente para cada parte de esta mini-serie están disponibles en GitHub, junto con la aplicación final.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.