python-2.7corscherrypycross-domain-policy

Cherrypy handling "no 'Access-Control-Allow-Origin' header is present" error


Over the weekend chrome seems to have updated and now blocks my cross-domain requests:

I have one server, two domains, and a shared web icon font on one that needs to load on the other. I'd rather not force cherrypy to be aware of which domain it is serving (the mirror or the main one), because for that effort I might as well clone all the code.

My chrome console.log error message is:

Font from origin 'http://djotjog.com' has been blocked from loading by Cross-Origin Resource Sharing policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin 'http://storylearning.org' is therefore not allowed access. 

In cherrypy I tried to enable this but the docs are sketchy. Here is what I tried:

class root:
def stest(self, **kw):
    cherrypy.response.headers['Content-Type'] = 'text/html'
    cherrypy.response.headers["Access-Control-Allow-Origin"] = "*"
    html = some_function()
    return html

def CORS():
    cherrypy.response.headers["Access-Control-Allow-Origin"] = "*" 
if __name__=="__main__":
    cherrypy.tools.CORS = cherrypy.Tool('before_handler', CORS)  

cherrypy.config.update({
'environment': 'production',
'log.screen': False,
'log.error_file':'cperror.log',
'server.socket_host': '127.0.0.1',
'server.socket_port': 15722,
'server.thread_pool': 2,
'server.thread_pool_max': 2

So what is the right way to handle cross-domain requests on cherrypy?


Solution

  • First, it's quite unclear why do have the issue if you say it's a mirror. If it's really a mirror then you would just need to refer to your font file with a relative URL (/path/to/your/font.otf).

    Second, web fonts were subject to CORS since 2010 at least in FF and IE (see bugreport). And the behaviour is actually by design (see spec). So if you ever tested your site in these browsers you should be seeing the same thing.

    Third, if you're talking of partial mirrors, then the following should serve your need.

    app.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import os
    
    import cherrypy
    from cherrypy.lib import static
    
    
    path   = os.path.abspath(os.path.dirname(__file__))
    config = {
      'global' : {
        'server.socket_host' : '127.0.0.1',
        'server.socket_port' : 8080,
        'server.thread_pool' : 8
      },
      '/font' : {
        'tools.corsstaticdir.on'  : True,
        'tools.corsstaticdir.dir' : os.path.join(path, 'font'),
        # This is a workaround for CherryPy flaw  where they set ``section`` 
        # tool config variable in ``cherrypy._cpdispatch.Dispatcher.set_conf`` 
        # exclusivety for ``staticdir`` tool (http://goo.gl/EGIIvA).
        'tools.corsstaticdir.section' : '/font',    
      }  
    }
    
    
    def corsstaticdir(section, dir, root = '', match = '', content_types = None, index = '', debug = False):
      cherrypy.response.headers['Access-Control-Allow-Origin'] = '*'
      return static.staticdir(section, dir, root, match, content_types, index, debug)
    
    cherrypy.tools.corsstaticdir = cherrypy._cptools.HandlerTool(corsstaticdir)
    
    
    class App:
    
      @cherrypy.expose
      def index(self):
        return static.serve_file(os.path.join(path, 'index.html')) 
    
    
    if __name__ == '__main__':
      cherrypy.quickstart(App(), '/', config)
    

    index.html

    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv='content-type' content='text/html; charset=utf-8'/>
    <title>CORS font</title>
    <style type='text/css'>
      @font-face {
        font-family : YourFontRegular;
        font-weight : normal;
        font-style  : normal;      
        src         : url('http://anotherdomain/font/Quicksand-Regular.otf');
      }
      p {
        font-family : YourFontRegular;
      }
    </style>
    </head>
    <body>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam placerat lacinia tortor. Nulla viverra, dolor nec malesuada congue, lectus quam dictum tellus, at malesuada nisl tortor quis ligula. Donec aliquam id arcu quis consectetur. Sed vitae turpis quis metus consequat vulputate.</p>
    </body>
    </html>