Jonathan Hernandez

Rails developer. Free (as in freedom) software enthusiast. Gamer.

Testing CORS Headers With RSpec and Rack in Rails

| Comments

I’ve not found any blog post or article about how to easily test CORS support implemented in a Rack middleware (e.g. using the rack-cors gem) with RSpec in Rails. So, after figured out I decided to write some small tips I learned from it.

I assume you have a fairly updated Rails app, I tested it with Rails 4.2.x, with RSpec tests support, and you want to add support for CORS headers.

Install rack-cors gem

it’s better to follow the gem instructions (you’ll find the most updated instructions there) than a blog post, but anyway here’s how I did it:

Add this to your Gemfile:

1
gem 'rack-cors', :require => 'rack/cors'

Add this to your config/application.rb:

1
2
3
4
5
6
config.middleware.insert_before(0, "Rack::Cors", logger: (-> { Rails.logger })) do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :patch, :options]
  end
end

These are the common options, tune it to your needs. Here we’re allowing requests from any domain for the get, post, patch and options methods. options is a special method used for preflight requests.

That’s it. CORS is now active in this Rails app. Every time we send a request with the CORS headers, we’ll receive the CORS response headers.

How to test it with cURL

With cURL, it’s easy to test CORS. Let’s see the most common scenarios:

Sending the Origin header:

  • -H: Header to include in the request.
  • -I: Fetch the HTTP header only.
1
curl -H "Origin:*" -I http://localhost:3000/people/1234

We should receive: Access-Control-Allow-Origin: *.

Sending the preflight options method:

Send a options request with Origin: *, Access-Control-Request-Method: get and Access-Control-Request-Headers: test. * -X: Specifies a custom request method

1
curl -X OPTIONS -I http://localhost:3000 -H 'Origin: *' -H 'Access-Control-Request-Method: GET' -H 'Access-Control-Request-Headers: test'

We should receive Access-Control-Allow-Origin: *, Access-Control-Allow-Methods: get, post, patch, options, and Access-Control-Allow-Headers: test.

How to test it with RSpec

Support CORS is a bit tricky to test with RSpec, because we don’t have a real server (like Webrick, Unicorn or Puma) between the code and the client. This usually is not a problem but it does affect in this particular case, and the rfc3875 explains why. The server translate the custom HTTP request headers in this way:

  • Convert to upper case.
  • Replace - with _
  • Prepend HTTP_.

Because we don’t have the server to do it for us, we must do it manually. For example, the Origin becomes HTTP_ORIGIN and Http-Access-Control-Request-Method becomes HTTP_ACCESS_CONTROL_REQUEST_METHOD. Let’s see some example tests:

Sending the Origin header:

1
2
3
4
5
6
7
RSpec.feature "the requests support CORS headers", type: :feature do
  scenario 'Returns the response CORS headers' do
    get '/people/1234', nil, 'HTTP_ORIGIN' => '*'

    expect(last_response.headers['Access-Control-Allow-Origin']).to eq('*')
  end
end

Sending the preflight options method:

1
2
3
4
5
6
7
8
9
10
RSpec.feature "the requests support CORS headers", type: :feature do
  scenario 'Send the CORS preflight OPTIONS request' do
    options '/', nil, 'HTTP_ORIGIN' => '*', 'HTTP_ACCESS_CONTROL_REQUEST_METHOD' => 'GET', 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' => 'test'

    expect(last_response.headers['Access-Control-Allow-Origin']).to eq('*')
    expect(last_response.headers['Access-Control-Allow-Methods']).to eq('GET, POST, PATCH, OPTIONS')
    expect(last_response.headers['Access-Control-Allow-Headers']).to eq('test')
    expect(last_response.headers).to have_key('Access-Control-Max-Age')
  end
end

Note: You must use integration tests to be able the test through rack. A controller test doesn’t trigger rack, it’s like an unit test for the controller.

Don’t forget to uppercase, replace - and prepend HTTP_ to all your custom HTTP headers when testing!

Relanzando El Blog

| Comments

En estos últimos 3 años no he escrito casi nada, creo que Twitter tiene gran parte de culpa. El hecho de ir poniendo por ahí comentarios cortos como que me hizo perder las ganas de invertir en más de 140 caracteres, quizás también pensando que la gente ya no invierte tanto tiempo en leer artículos como antes. No es nuevo que hemos ido hacia el consumo rápido, tiene lógica teniendo en cuenta la cantidad enorme de información a la que tenemos acceso diariamente. Un formato como Twitter, el formato “titular”, es más óptimo para el consumidor, que adquiere multitud de pequeñas gotas de información de las cuales unas pocas que filtrará las expandirá un poco más accediendo al enlace.

Mientras Twitter sigue siendo una opción muy válida, creo que seguir poniendo pensamientos, tutoriales y demás en un blog es algo enriquecedor para el autor, y en ocasiones útil para el lector. Puede que nadie lo lea, o muy pocos, pero el propósito del músico no es que su canción tenga éxito (aunque eso está muy bien), sinó componer, tocar o cantar.

Una de las cosas que quiero también aprovechar con el blog para mejorar es mi escritura del inglés. Creo que los artículos técnicos es una buena manera de hacerlo, es un tipo de artículo que puede servir a nivel global y la audiencia a la que va dirigida es muy probable que entienda el inglés, como mínimo el escrito.

Pues eso es todo, por ahora el único cambio importante en el blog es la migración que he hecho de Blogger a Github usando Jekyll y Octopress.

MS SQLServer Numeric Primary Key Hibernate

| Comments

Related to this old hibernate problem: http://grails.1312388.n4.nabble.com/MS-SQLServer-numeric-primary-key-hibernate-td3565392.html

By default Gorm/hiberate is generating id columns as the numeric(19,0) on SQLServer.  I’d like those to be of type BIGINT instead.

The solution is to use the correct dialect for hibernate. In Grails, you can configure it like this:

grails-app/conf/DataSource.groovy:

        dataSource {
            driverClassName = “com.microsoft.sqlserver.jdbc.SQLServerDriver”
            username = “xxx”
            password = “xxx”
            dbCreate = “create-drop” // one of ‘create’, ‘create-drop’, ‘update’, ‘validate’, ”
            url = “jdbc:sqlserver://host\instance;databaseName=databaseName”
            dialect = “org.hibernate.dialect.SQLServer2008Dialect”
        }

Que Yo Tenga Que Defender a Steve Jobs Y Apple…

| Comments

Nota: A raíz de la muerte de Steve Jobs, no me gusta nada cómo se frivoliza por parte de algunos blogs/comentarios la aportación de Apple al mundo de la tecnología. Cabe decir que yo jamás he comprado para mi NADA de Apple, y además soy desarrollador de Android.

Quizás la crítica más frecuente a Apple tiene que ver con el fenómeno fanboy. En relación al fanboyismo o elitismo, es un problema que podemos encontrar en cualquier ámbito: Los videojuegos, (entre marcas como Nintendo, Sega, Sony o plataformas como Consolas vs PC), marcas de coche (Ferrari, Porsche…), deportes y un largo etc. Esta parte de Apple no me interesa nada, así que ni voy a entrar.

Lo importante: ¿Qué ha hecho Apple bien? Es muy sencillo y a la vez complicado, pero que se resume en: Impulsar mercados

Los smartphones empezaron después del iPhone. Por supuesto antes del iPhone habían smartphones pero el producto de apple fué el que impulsó el mercado de los smartphones. Con los mp3 y el iPod pasó igual pero me interesa más el mercado de los smartphones y las tablet (iPad, también lo mismo). Pero mi impulso de mercado preferido fué el de las apps, lo que considero ha generado una época dorada para el programador (sobretodo el indie, tanto de juegos como de aplicaciones de cualquier tipo), y que ha supuesto muchísimos puestos de trabajo.

Y qué ha hecho Steve Jobs en concreto:

Pues de todo esto él tiene mucha culpa, pero quizás lo que fascina a mucha gente de su figura es la capacidad de echarse a las espaldas a una empresa a punto de morir y ponerla en la número 1 mundial (la jodida número 1 del todo el planeta, que es muy fácil decirlo, por encima de: Microsoft, Google (en tecnología) y por encima incluso de petroleras que eran las número 1 indiscutibles hasta el momento).

¿Steve Jobs es un cabrón? He oído de gente que lo afirma. No lo sé, pero es un tema que puedo ni podré entrar a valorar porque no he trabajado con él. Lo que sí creo es que es un genio, en su campo de trabajo: Sabe lo que quiere la gente, sabe poner precio a las cosas sin perder dinero, sabe perfilar los detalles, sabe presentar las cosas, sabe hablar en público como pocos, un carisma inmenso, este tío SABE de su trabajo. No tiene porqué ser talentoso en todo lo que hace, a lo mejor sabe rodearse de otros que saben lo que hacen. En cualquier caso, la finalidad es conseguir el objetivo que te propones. Y eso, se le ha dado muy bien. ¿Las maneras? Sólo unos pocos las conocen. Quizás no sean éticas, no lo sé, eso es algo que jamás podré valorar y por tanto no entraré.

Desde la propia Google (por nombrar a su mayor competencia) también se le admira, por ej. mirad este post de Vic Gundotra (Senior vicepres. de Google), 25 de agosto: https://plus.google.com/107117483540235115863/posts/gcSStkKxXTw 

Woices Para Android

| Comments

Mi último proyecto (o subproyecto dentro del GRAN proyecto Woices) es la aplicación de esta plataforma para el sistema operativo libre de Google: Android.

Hay una gran lista de dispositivos que usan Android, sobretodo teléfonos móviles, algunos de los más populares son los HTC Magic, Hero, Desire, Evo 4G, Nexus One… o el Motorola Droid/Milestone.


Después de estar más de 2 meses empapándome de documentación, APIs, conferencias, código fuente de ejemplo y búsquedas en google, google groups, stackoverflow y en mis notas de Tomboy y papeles con dibujitos o esquemas en Google Docs… por fin ha salido a la luz la primera versión de woices para android.


La idea es que lleves la aplicación “a cuestas” y puedas beneficiarte in-situ de la información (audioguías) que los usuarios dejan en los diferentes puntos del planeta en forma de audio. Puedes encontrate ecos, rutas o guías patrocinadas según el sitio donde estés. También esta disponible la función de búsqueda (por título, lugar, ciudad o e-code).

Si tienes un teléfono Android pruébala y dime qué te parece. Mientras, sigo trabajando en la siguiente versión.

II Jornadas De GPLTarragona

| Comments

Mañana son las II Jornadas de GPLTarragona:

Per celebrar el 7e aniversari de l’associació GPL Tarragona i continuar demostrant el compromís per promocionar les tecnologies de la informació i el programari lliure a la província de Tarragona, el dijous 6 de maig de 2010 tindran lloc les II Jornades GPL Tarragona a la Sala de Graus del campus Sescelades (ETSE – Universitat Rovira i Virgili).

Les jornades són completament gratuïtes i es troben destinades a professionals, aficionats, professors i estudiants en general.

Xerrades:

16:00 – Desevolupament amb iPhone – Oleguer Huguet de Woices
16:45 – La Singularitat: una perspectiva OpenSource – Joan Baz de Adaptiva
Sistemas
17:30 – KISS IT – Joan Puig
18:15 – Auditories de Sistemes, l’inici d’una carrera professional apassionant – Sergi Blanco Cuaresma
19:00 – Clausura

Les xerrades tindran una duració de 30 min. + 15 min. per preguntes/debat. No es necessari fer reserva, és un esdeveniment obert i gratuït. Es pot assistir a aquelles xerrades que més interessin lliurement.


Programa Completo (PDF)

Actualizando a Ubuntu 10.04 Lucid Lynx

| Comments

Ya esta disponible la última versión de Ubuntu, 10.04 llamada Lucid Lynx desde la misma web de Ubuntu o desde vuestro “Gestor de actualizaciones”.
Esta vez no he tenido que cambiar el mirror, el español iba a tope:

Nexus One Datos 3G Movistar/Telefonica

| Comments

Tengo unos datos que funcionan para conectarte al 3G de Movistar (Telefónica) en España con el Nexus One de Google (supongo que funcionarían en cualquier teléfono Android).

Los que no tienen valor dejarlo vacío o por defecto.

Nombre: Movistar 3G
APN: movistar.es
Proxy:
Puerto:
Nombre de usuario: MOVISTAR
Contraseña: MOVISTAR
Servidor: 194.179.1.100
MMSC:
Proxy MMS:
Puerto MMS:
MCC: 214
MNC: 07
Tipo de APN:

Lo que no he encontrado son los datos del MMS, pero bueno tampoco lo uso.

PD: No pongais datos de 3G a no ser que tengais un plan de datos con vuestra operadora, sinó luego la factura se resentirá…

De Vuelta… En Blogger

| Comments

Después de varios días off i’m back. El blog anterior estaba alojado en el servidor de GPLTarragona, que le dió por petar el disco duro (no entiendo por qué, era de estos nuevos IDE de 8Gb….. oh wait). Nada que hacer, fallo de hardware con ruido muy feo.
De GPLTarragona no hay problema porque hacíamos 1 backup diario al día, pero de mi pobre blog… bueno… como que no lo cuidaba mucho y me despreocupé de él… y resulta que no tenía ningún backup por ahí. Bueno tenía un backup por ahí del 2005 y el resto es como un puzzle :D Pero no hay problema, ya iré reestableciendo los posts poco a poco… que me da pena (ahora) perderlos, por ahora sólo estan hasta el 2005 (quedan unos cuantos :P).

Ahora como veis he migrado a blogger, básicamente para tener dominio propio en un blog y no preocuparme por su mantenimiento. Mirando sobre cómo migrar de Wordpress a Blogger me he encontrado con un par de recursos útiles:

Exportar Xml de todo el blog en Wordpress
Convertir Xml de Wordpress en Xml de Blogger
Importar desde Blogger un Xml

Articulo Random en Rails

| Comments

Queremos obtener un registro aleatorio de la BD en Rails:

def random
@articulo = Articulo.find(:first, :order => ‘RAND()’)
end