Can't get Twisted to return application/json content-type

Viewed 31

I have a server which is supposed to return JSON, I set the request response 'Content-Type' to 'application/json', yet from client side I always get text/html

this is the server printing response headers:

b'Server' = [b'TwistedWeb/22.4.0']
b'Date' = [b'Fri, 08 Jul 2022 18:35:59 GMT']
b'Content-Type' = [b'application/json']

this is the client printing the reply headers:

b'Transfer-Encoding' = b'chunked'
b'Server' = b'TwistedWeb/22.4.0'
b'Date' = b'Fri, 08 Jul 2022 18:35:59 GMT'
b'Content-Type' = b'text/html'

I print headers in the server just before calling request.finish(), is there something happening after that that I should know about ?

this is the server code (simplified):

import json
from twisted.web import server, resource
from twisted.internet import reactor


class Resource(resource.Resource):

    def render(self, request):

        def return_json(data):
            request.write(json.dumps(data, separators=(',', ':')).encode())
            request.setHeader(b'content-type', b'application/json')
            request.finish()
        
        deferred = someFunctionReturningDeferred()
        deferred.addCallback(return_json)

        return server.NOT_DONE_YET

site = server.Site(Resource())
reactor.listenTCP(PORT, site)
reactor.run()

What am I doing wrong ?

Many thanks, Paul

1 Answers
  • "Hey me, have you tried to put request.setHeader() before request.write()?"
  • "Why would I do that ? Why would headers data and actual body data depends on each other ? ok, let's try..."
  • "so ?"
  • "it works -__-"

so, the working solution :

class Resource(resource.Resource):

    isLeaf = True

    def render(self, request):

        def return_json(data):
            # FIRST, set content-type
            request.setHeader(b'content-type', b'application/json')
            # THEN, write data
            request.write(data)
            request.finish()

        # makes defer and adds callback in single function, for the example
        task.deferLater(reactor, 2, return_json, b'{"hello": "dummy"}')

        return server.NOT_DONE_YET
Related