Search code examples
pythoncharacter-encodingcherrypy

Forcing response charset in CherryPy


I want to specify the HTTP response charset by modifying the Content-Type header. However, it doesn't work.

Here is a short example:

#coding=utf-8
import cherrypy

class Website:
    @cherrypy.expose()
    def index(self):
        cherrypy.response.headers['Content-Type']='text/plain; charset=gbk'
        return '。。。'.encode('gbk')

cherrypy.quickstart(Website(),'/',{
    '/': {
        'tools.response_headers.on':True,
    }
})

And when I visit that page, the Content-Type is changed mysteriously to text/plain;charset=utf-8, causing mojibake in the browser.

C:\Users\Administrator>ncat 127.0.0.1 8080 -C
GET / HTTP/1.1
Host: 127.0.0.1:8080

HTTP/1.1 200 OK
Server: CherryPy/7.1.0
Content-Length: 6
Content-Type: text/plain;charset=utf-8
Date: Mon, 22 Aug 2016 01:08:13 GMT

。。。^C

It seems that CherryPy detect content encoding and override the charset automatically. If so, how can I disable this feature?


Solution

  • All right. Solved this problem by tampering cherrypy.response.header_list directly.

    #coding=utf-8
    import cherrypy
    
    def set_content_type():
        header=(b'Content-Type',cherrypy.response._content_type.encode())
    
        for ind,(key,_) in enumerate(cherrypy.response.header_list):
            if key.lower()==b'content-type':
                cherrypy.response.header_list[ind]=header
                break
        else:
            cherrypy.response.header_list.append(header)
    
    cherrypy.tools.set_content_type=cherrypy.Tool('on_end_resource',set_content_type)
    
    class Website:
        @cherrypy.expose()
        @cherrypy.tools.set_content_type()
        def index(self):
            cherrypy.response._content_type='text/plain; charset=gbk'
            return '。。。'.encode('gbk')
    
    cherrypy.quickstart(Website(),'/')