Perl en Windows Azure con la plantilla FastCGI

Uno de los retos con el que he estado lidiando 煤ltimamente es con la posibilidad de ejecutar c贸digo Perl en Windows Azure 馃榾 Para ello voy a mostrar c贸mo es posible, haciendo uso de la plantilla pensada para Fast CGI con algunas modificaciones.

Descarga de Strawberry for Perl

El primer paso que debemos dar antes de introducirnos en Visual Studio es descargar el int茅rprete de Perl. En este caso voy a utilizar Strawberry for Perl, el cual podemos obtener del siguiente enlace. Una vez descargado, ejecutamos el msi para generar el directorio strawberry en nuestro disco local. El mismo contendr谩 las librer铆as necesarias para interpretar c贸digo Perl.

Creaci贸n del proyecto de Windows Azure

Abrimos Visual Studio en modo administrador y creamos un nuevo proyecto del tipo Windows Azure Project. Como rol eligiremos CGI Web Role.
Pulsamos en el bot贸n OK para que genere la soluci贸n y conseguir de este modo la siguiente estructura:

Cuando tenemos un proyecto de este tipo, lo m谩s importante es adjuntar y configurar el interprete que vamos a utilizar para nuestro c贸digo. En este caso, vamos a a帽adir el directorio de strawberry para que el mismo sea subido a Azure junto con nuestra aplicaci贸n. La forma m谩s f谩cil de realizar este paso ser铆a ubicar una copia de la carpeta strawberry en el directorio del proyecto WebCgiRole para posteriormente poder incluirlo.

Modificaci贸n de los archivos de configuraci贸n

En este tipo de proyectos existen dos archivos de configuraci贸n: Web.roleconfig y Web.config. En el primero de ellos debemos establecer cu谩l es el int茅rprete que vamos a utilizar.
<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <fastCgi>
      <!-- Set the "Enable Full Trust" property to true on the corresponding
           Web Role in the Cloud Service project.
      -->
      <!-- Define the fastCgi application here. The application must be located
           under the role root folder or subfolder. The handler is defined in
           the Web.config file.
           Ensure that all of the handler binaries have their "Build Action" Solution
           Explorer file property set to "Content".
      <application fullPath="%RoleRoot%approotcgi-handler.exe" arguments="arg1 arg2 ..." />
      -->
      <application fullPath="E:approotstrawberryperlbinperl.exe"/>
    </fastCgi>
  </system.webServer>
</configuration>
Por otro lado, en el archivo Web.config debemos especificar el handler o handlers que vamos聽a utilizar cuando nuestra aplicaci贸n reciba peticiones con extensiones .cgi y .pl
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true" />
    <handlers>
      <!-- Define your fastCgi handler here. The scriptProcessor value should map to the
             application's fullpath and arguments values in the Web.roleconfig file.
        <add name="FastGGI Handler"
             verb="*"
             path="{file or extension, ex: *.php}"
             scriptProcessor="%RoleRoot%approotcgi-handler.exe|arg1 arg2 ..."
             modules="FastCgiModule"
             resourceType="Unspecified" />
           -->
      <add name="CGI Handler" verb="*" path="*.cgi"
           scriptProcessor="E:approotstrawberryperlbinperl.exe % s %s"
           modules="CgiModule"
           resourceType="Unspecified" />
      <add name="PL Handler" verb="*" path="*.pl"
           scriptProcessor="E:approotstrawberryperlbinperl.exe % s %s"
           modules="CgiModule"
           resourceType="Unspecified" />
    </handlers>
    <defaultDocument>
      <files>
        <add value="pruebaperl.cgi" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>
Lo que conseguimos con ello es crear handlers de la misma forma que si lo hici茅ramos desde el apartado Mapping Handlers de la interfaz de Internet Information Services.

ISAPI and CGI Restrictions

Para que todo el proceso tenga 茅xito, a煤n queda un asunto pendiente. Para poder ejecutar el proceso perl.exe es necesario a帽adir el mismo a la lista de ISAPI and CGI Restrictions.
Esta operaci贸n podemos realizarla a trav茅s de la consola de comandos, haciendo uso de la secci贸n Startup del archivo de Definici贸n de Windows Azure. En el vamos a definir un ejecutable llamado EnableIsapi.bat donde vamos a registrar lo necesario para poder hacer uso de nuestro interprete sin que el mismo sea bloqueado por IIS.
<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="PerlFastCGI" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="WebCgiRole" enableNativeCodeExecution="true">
    <Startup>
      <Task commandLine="EnableIsapi.bat" executionContext="elevated" taskType="simple"></Task>
    </Startup>
    <Sites>
      <Site name="Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="Endpoint1" />
        </Bindings>
      </Site>
    </Sites>
    <Endpoints>
      <InputEndpoint name="Endpoint1" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics" />
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
    </Imports>
  </WebRole>
</ServiceDefinition>
El contenido del .bat ser谩 el que sigue:
setlocal enableextensions enabledelayedexpansion
set appcmd="%windir%system32inetsrvappcmd"
%appcmd% set config -section:isapiCgiRestriction /-[path='"e:approotstrawberryperlbinperl.exe %% s %%s"'] /commit:apphost
%appcmd% set config -section:isapiCgiRestriction /+[path='"e:approotstrawberryperlbinperl.exe %% s %%s"'] /commit:apphost
%appcmd% set config -section:isapiCgiRestriction /[path='"e:approotstrawberryperlbinperl.exe %% s %%s"'].allowed:true /commit:apphost
exit /b 0

Subiendo nuestro proyecto a Windows Azure

Para comprobar que la configuraci贸n del proyecto de Windows Azure est谩 definida correctamente, vamos a crear dos nuevos archivos: El primero de ellos se llamar谩 pruebaperl.cgi el cual ser谩 ejecutado por defecto cuando entremos en nuestro sitio ra铆z.

#!/perl
print "Content-type: text/htmlrnrn";
for ($i=1; $i<=10; $i++)
{
  print "
	<li> - Prueba de ejecucion Iteracion: $i n";
}

El segundo se llamar谩 prueba.pl donde a帽adiremos el siguiente contenido:

#!/perl
print "Content-type: text/htmlrnrn";
for ($i=1; $i<=10; $i++)
{
  print "
	<li> - Prueba de ejecucion en pl Iteracion: $i n";
}

Subimos la aplicaci贸n al portal de Windows Azure de la forma habitual y esperamos hasta que el estado de la misma se torne a Ready.

Si accedemos al DNS seleccionado deber铆amos obtener el siguiente resultado:

Por otro lado, si a帽adimos a la ruta http://myDNS.cloudapp.net/prueba.pl el resultado esperado ser铆a:

Espero que haya sido de utilidad 馃榾

隆Saludos!