[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: varnish y cookies... [Casi solución]



El Sun, 01 de Jun de 2014, a las 07:36:37PM +0200, José Miguel (sio2) dijo:

> Supongo que habrá forma de hacerlo escribiendo el código en C, pero soy
> incapaz: apenas recuerdo nada de C y, además, no sé cuáles son las tripas de
> esto. Si a eso le sumamos que cualquier error en C, tiene consecuencias
> catastróficas, tenemos montada la fiesta.

Bueno, tengo una solución cutrecilla, porque no trabaja a muy bajo
nivel, pero necesitaría una pequeña mejora, a ver si alguien que sepa de
C da con la tecla. Al que le aburra el código que se salte al final, que
la expongo.

Resulta que varnish tiene una función std.collect() que reúne en una
sola cabecera todas las cabeceras con el mismo nombre, y separa los
valores con ", ". Creo que en el antiguo RFC esta era la forma de enviar
varias cookies.

Pues bien, la estrategia consiste en reunir todas las cookies en una
sola cabecera, sustituir todos los separados ", ", por otro que sea de
un carácter (precisamente en este carácter viene mi duda), y hacer con
expresiones regulares todos los cambios pertinentes en el path, De paso,
se elimina el dominio, por si alguna aplicación le da por incluirlo.

Cuando se tiene todo esto preparado, con un par de líneas en "inline C",
es fácil trocear de nuevo para volver a formar cabeceras separadas.
Haciendo lo dicho:

http://www.dominio1.com/ruta_dominio1

y

http://www.dominio2.com/ruta_dominio2/www.dominio1.com/ruta_dominio1

serven exactamente la misma aplicación, pero de modo que el servidor web
sólo se ha configurado para recibir peticiones de la primera forma.

Esto es lo que he escrito:

#v+

C{
  #define _GNU_SOURCE
  #include <string.h>
  #include <stddef.h>

}C

import header;

[...]

sub vcl_recv {

[...]

   if ( req.url ~ "/ruta_dominio2/([^\.]+\.)?dominio1.com/?" ) {
      set req.http.X-Interface = req.http.host;
      set req.http.host = regsub(req.url,"^/ruta_doominio2/([^/]+).*$","\1");
      set req.url = regsub(req.url,"^/ruta_dominio2/[^/]+/?","/");
   }

[...]

}

sub vcl_fetch {

[...]

   # X-Interface se añade en vcl_recv
   # cuando se alteran host y url
   if ( req.http.X-Interface ) {
      # Corrige redirecciones 
      if ( beresp.status == 301 || beresp.status == 302  && beresp.http.location !~ "^https:" ) {
           set beresp.http.location = regsub(beresp.http.location,"http://(.+)","http://"+req.http.host+"/\1";);
      }
      if( beresp.http.Set-Cookie ) {
          std.collect(beresp.http.Set-Cookie);
          set beresp.http.X-Set-Cookie = regsuball(beresp.http.Set-Cookie,"[Dd]omain=[^,;]+(; )?","");
          unset beresp.http.Set-Cookie;
          set beresp.http.X-Set-Cookie = regsuball(beresp.http.X-Set-Cookie,", ([A-Za-z0-9]+=)","#\1");
          set beresp.http.X-Set-Cookie = regsuball(beresp.http.X-Set-Cookie,"([Pp]ath=)","\1/otra/ruta/"+ req.http.host);

          C{
            const char *delim="#";
            char *cookies;

            cookies=strdupa(VRT_GetHdr(sp,HDR_BERESP,"\015X-Set-Cookie:"));

            while(cookies)
              Vmod_Func_header.append(sp,HDR_BERESP,"\013Set-Cookie:",strsep(&cookies,delim),vrt_magic_string_end);
          }C

          unset beresp.http.X-Set-Cookie;
      }
   }
[...]

}

[...]

#v-

Para separar una cookie de la otra he usado el carácter "#", pero
quizás en alguna cookie de alguna aplicación aparezca ese carácter y se
me fastidie el invento. Así que he pensado que era más seguro usar "\n".
Sin embargo, no funciona esto:

#v+
set beresp.http.X-Set-Cookie = regsuball(beresp.http.X-Set-Cookie,", ([A-Za-z0-9]+=)","\n\1");

[...]

const char *delim="\n";
#v-

¿Se le ocurre a alguno la causa? En C se puede escribir así el retorno
de carro, ¿no? Hice un prueba de troceo en un .c aparte y me troceó sin
problema una cadena cuyos delimitadores era "\n", así que creo que el
problema está en el último parámetro de la primero línea.

-- 
   Lee si puedes y enmienda si sabes.
                  --- Lope de Vega ---


Reply to: