Thursday, May 28, 2009

CGI con Webrick en Windows

Hace una semana estuve tratando de ejecutar en Windows un script escrito en Ruby (ambos 1.8.6 y 1.9.1), como CGI, para que ejecutara en Webrick y poder ver el resultado en el browser.

El CGI era bien sencillo, algo mínimo como sigue:

#!/user/bin/ruby
print "Content-type: text/html\r\n\r\n"
print "<HTML><BODY>Saludos desde Ruby CGI.
#{Time.now}<br/>\r\n</BODY></HTML>\r\n"

Al principio me salía un error que decía:
"Premature End of Script Headers"


[En Linux el problema no ocurre]

Indagando un poco en el código fuente de Webrick, encontré la siguiente forma de corregir el problema:

Abrir el archivo siguiente con un editor:

c:\ruby\lib\ruby\1.9.1\webrick\httpservlet\cgi_runner.rb


Añadir el siguiente código al principio:


if "1.9.1" == RUBY_VERSION
require 'rbconfig'
end


Hacia el final del mismo archivo, en la última línea, localizar donde dice:

exec ENV["SCRIPT_FILENAME"]


Comentar esa última línea y añadir el siguiente código:

# --- desde aquí ---
if "1.9.1" == RUBY_VERSION
Ruby = File::join(RbConfig::CONFIG['bindir'],
RbConfig::CONFIG['ruby_install_name'])
Ruby << RbConfig::CONFIG['EXEEXT']
else
Ruby = File::join(::Config::CONFIG['bindir'],
::Config::CONFIG['ruby_install_name'])
Ruby << ::Config::CONFIG['EXEEXT']
end

if /mswin|bccwin|mingw/ =~ RUBY_PLATFORM
exec "#{Ruby}", ENV["SCRIPT_FILENAME"]
else
exec ENV["SCRIPT_FILENAME"]
end
# --- hasta aquí ---


Lo que hace este código es pasar el path completo de ruby.exe a la función exec() para que sepa cómo invocar el interpretador. En Linux no es problema porque la primera línea del script suple esa información "#!/user/bin/ruby".

Eso es todo. Guardé el archivo y re-inicié el servidor webrick.

Al abrir el browser en la siguiente dirección ...

http://localhost:2000/cgi-bin/rubycgi.cgi


... muestra el resultado esperado.

EngineYard mantiene Ruby 1.8.6

Acaban de anunciar que EngineYard va a tomar las riendas del mantenimiento de Ruby 1.8.6 para acelerar este aspecto tan necesario.

Referencia:
"Ruby 1.8.6 maintenance moved to EngineYard" desde la página oficial de Ruby