Luke Luke - 12 days ago 6
Python Question

Twisted server returning text with unexpected fonts

My current twisted server code. It is a simple experiment to take url encoded requests and convert them into a JSON like string to then return.

from twisted.web.server import Site
from twisted.web.resource import Resource
from twisted.internet import reactor
import urllib.parse

class FormPage(Resource):
isLeaf = True
def render_GET(self, request):
print(request.uri)
x = (request.uri).decode('ascii')
x = x[1:]
x = todi(x)
return x.encode('ascii')
def todi(st):
if len(st) == 0:
return '{}'
if st[len(st)-1] == '/':
st = st[:-1]
if len(st) == 0:
return '()'
if st[0] == '?':
st = st[1:]
st = urllib.parse.parse_qsl(st)
return str(dict(st))



factory = Site(FormPage())
reactor.listenTCP(80, factory)
reactor.run()


I've paid attention to the font my browser displays when I am receiving simple text. For example this site: http://icanhazip.com/ when you visit, the font looks like
consola
font (default font for MS notepad). However, when I visit my site, my browser displays a font that looks like
Times New Roman
.

I have done some debugging since, such as forcing the site to return a simple string of characters, but nothing can stop twisted from giving me ugly looking fonts.

Here, have an example.

Also note that I did the thing in Chrome where you right click and use the "View page source" button. Trust me, both my examples are simply raw text according to that.

Answer

Looking at the headers returned by your Twisted server and comparing them to those returned by the other web site, the latter specifies Content-Type: text/plain; charset=UTF-8, whereas the Twisted server does not specify the Content-Type at all.

Your browser (and I've found it to be the same with Firefox) uses a different font when the content type is specified as text/plain vs. an unspecified content type.

In Twisted you can set the Content-Type header with request.setHeader() like this:

def render_GET(self, request):
    print(request.uri)
    x = (request.uri).decode('ascii')
    x = x[1:]
    x = todi(x)
    request.setHeader('Content-Type', 'text/plain; charset=UTF-8')
    return x.encode('UTF-8')

As this sets the Content-Type it might as well specify the charset too. UTF-8 is (probably) preferred, and the response text is similarly encoded.