Como no mostrar la versión de CherryPy
Visitando webs me he cruzado con un error 500 del framework para aplicaciones web CherryPy, concretamente en spotify:
Como me ha llamado la atención ver la versión he mirado los headers HTTP:
# curl -I www.spotify.com HTTP/1.1 302 Moved Temporarily Date: Fri, 22 Jan 2010 21:44:25 GMT Server: Apache/2.2.9 (Debian) mod_ssl/2.2.9 OpenSSL/0.9.8g X-Powered-By: PHP/5.2.6-1+lenny4 Expires: Wed, 11 Jan 1984 05:00:00 GMT Cache-Control: no-cache, must-revalidate, max-age=0, x-always-cache Pragma: no-cache X-Pingback: http://www.spotify.com/xmlrpc.php Set-Cookie: spotify_language=en; expires=Sat, 26-Jun-2010 16:00:02 GMT; path=/ Last-Modified: Fri, 22 Jan 2010 21:44:25 GMT Location: /en/ Vary: Accept-Encoding Content-Type: text/html; charset=UTF-8
Resulta curioso ver el PHP combinado con una aplicación en python. La parte bajo SSL es la que es con CherryPy:
# curl -I https://www.spotify.com/en/invitation/ HTTP/1.1 200 OK Date: Fri, 22 Jan 2010 22:08:51 GMT Server: CherryPy/2.3.0 Cache-Control: no-cache, must-revalidate, max-age=0, x-always-cache Pragma: no-cache Content-Length: 8366 Content-Type: text/html; charset=utf-8 Expires: Wed, 11 Jan 1984 05:00:00 GMT Set-Cookie: spsess=249a66ea638cc27b7fb7249e1fba2329ce0268d0; expires=Fri, 22-Jan-2010 22:08:51 GMT; Path=/ Set-Cookie: tg-visit=0605c0228ab0c30032980dff91290c0e96f7a4ec; Path=/ Via: 1.1 www.spotify.com Vary: Accept-Encoding
Por el Via parece que tienen instalado un proxy inverso para hacer cache de las peticiones.
Como resulta sorprendente que permitan que se muestre la versión que usan de CherryPy me he dirigido a la página web de éste para ver si se puede deshabilitar. La sorpresa ha sido no encontrar ninguna opción de configuración referente a la eliminación de dicho banner o el server header. Para hacerlo deberemos modificar el código Python.
Nos bajamos el código en python y descomprimimos:
cd /usr/local/src wget http://download.cherrypy.org/cherrypy/2.3.0/CherryPy-2.3.0.tar.gz tar xzf CherryPy-2.3.0.tar.gz cd CherryPy-2.3.0
Editamos el fichero cherrypy/_cputil.py y nos encontraremos con:
_HTTPErrorTemplate = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
<title>%(status)s</title>
<style type="text/css">
#powered_by {
margin-top: 20px;
border-top: 2px solid black;
font-style: italic;
}
#traceback {
color: red;
}
</style>
</head>
<body>
<h2>%(status)s</h2>
<p>%(message)s</p>
<pre id="traceback">%(traceback)s</pre>
<div id="powered_by">
<span>Powered by <a href="http://www.cherrypy.org">CherryPy %(version)s</a></span>
</div>
</body>
</html>
'''
Podemos modificar la template a nuestro gusto para evitar proporcionar datos excesivos sobre nuestra aplicación. Simplemente podríamos eliminar el div con el id=”powered_by”.
Y ya no se mostrará la versión de CherryPy en HTML al ocurrir un error 500. Para eliminar también la versión del Server header deberemos editar la clase Response del fichero cherrypy/_cphttptools.py:
def __init__(self):
self.status = None
self.header_list = None
self.body = None
self.time = time.time()
self.headers = httptools.HeaderMap()
self.headerMap = self.headers # Backward compatibility
content_type = cherrypy.config.get('server.default_content_type', 'text/html')
self.headers.update({
"Content-Type": content_type,
"Server": "CherryPy/" + cherrypy.__version__,
"Date": httptools.HTTPDate(time.gmtime(self.time)),
"Set-Cookie": [],
"Content-Length": None
})
self.simple_cookie = Cookie.SimpleCookie()
self.simpleCookie = self.simple_cookie # Backward compatibility
Deberemos modificar el header por cualquier otro contendido como por ejemplo “unknown”:
"Server": "unknown",
Finalmente instalamos la versión modificada:
python setup.py install
Mediante código python es posible modificar estas dos características, pero de esta forma lo hacemos de una vez para toda aplicación que tengamos con CherryPy.
Relacionados
Imprimir

23. January 2010 at 8:43 pm :
Hola.
Una solución más elegante es extender la clase Response.
(abajo del todo)
Saludos.
24. January 2010 at 12:12 pm :
Al ser un framework permite esto, pero obliga a usar tu clase en lugar de la clase Response. Esto implica que para asegurar que no salga la versión se deberá revisar todo el código para usar la nueva clase.
Personalmente y para este caso en concreto, preferiría asegurarlo desde la base en lugar de tener que revisar todo el código.
Por otro lado, puedes mirarlo también como una cuestión de responsabilidades. En este caso que el framework instalado tenga una mínima configuración segura es responsabilidad del administrador del sistema, mientras que la programación les tocará a los desarrolladores de la aplicación. Por tu parte puedes aportar esto, independientemente que los programadores hagan una cosa o otra.