12

I want to be able to return something other than application/json i.e. kml.

I have the following:

@api.representation('application/vnd.google-earth.kml+xml')
def kml(data):
    return Response(data, mimetype='application/vnd.google-earth.kml+xml')

class mykml(restful.Resource):

    def get(self):
        r = requests.get("http://myurl/kml") # This retrieves a .kml file   
        response = make_response(r.content)
        response.headers['Content-Type'] = "application/vnd.google-earth.kml+xml"

        return response

Why is this still returning application/json? Also, if I have different formats, can I dynamically change the Content-Type of the respone within class mykml without the decorator?

Imports: from flask import Flask, request, Response, session,make_response

Rolando
  • 58,640
  • 98
  • 266
  • 407
  • Response content type depends on the *request headers*. – Martijn Pieters Sep 24 '14 at 18:15
  • 2
    possible duplicate of [Flask-RESTful - Return custom Response format](http://stackoverflow.com/questions/20243850/flask-restful-return-custom-response-format) – Martijn Pieters Sep 24 '14 at 18:16
  • `@api.representation()` is only used to register a representation conversion function. *If* the `Accept` header on the request has been set to `application/vnd.google-earth.kml+xml` then the `kml()` function will be used. – Martijn Pieters Sep 24 '14 at 18:17
  • How to set the Accept header on my mykml resource? – Rolando Sep 24 '14 at 20:39
  • 2
    You don't. You set it on the *request*. See the duplicated answer, you can return a `Response` object instead (create one with `flask.make_response()`). – Martijn Pieters Sep 24 '14 at 20:40
  • Could you provide a sample as to what you are referring to? I may be misunderstanding, but I just updated my handler to include Accept headers before the request, but it is still not working. The accepted answer above does not appear to make sense to me on how to use the flask.make_response. Does that occur in the mykml resource? – Rolando Sep 24 '14 at 20:47
  • I've updated the answer to make it explicit. – Martijn Pieters Sep 24 '14 at 20:49
  • I've just updated my code to return a response, as reflected above but am getting: TypeError: is not JSON serializable. I am trying to return the KML. – Rolando Sep 24 '14 at 20:51
  • The `@api.representation` decorator certainly needs to go. – Martijn Pieters Sep 24 '14 at 20:52
  • I've thrown out the decorator as reflected in the code above, yet the same error comes up. This may be due to how flask-restful works? Is there some way around it? – Rolando Sep 24 '14 at 20:55
  • How flask-restful works: [`dispatch_request` passes through `Response` objects](https://github.com/twilio/flask-restful/blob/master/flask_restful/__init__.py#L484). Make sure you return one; e.g. use `flask.make_response()`. Do *not* use `api.make_response()`. – Martijn Pieters Sep 24 '14 at 20:57

1 Answers1

2

If you need a specific response type from an API method, then you'll have to use flask.make_response() to return a 'pre-baked' response object:

def get(self):
    response = flask.make_response(something)
    response.headers['content-type'] = 'application/vnd.google-earth.kml'
    return response
Subir Verma
  • 393
  • 1
  • 3
  • 10
  • how about post method? if make POST request and expecting output should be customized with pre-defined response body schema, how would you approach with that? – beyond_inifinity May 05 '20 at 22:25
  • @beyond_inifinity Flask-RESTPlus Response marshalling provides an easy way to control what data you actually render in your response or expect as in input payload. With the fields module, you can use whatever objects (ORM models/custom classes/etc.) you want in your resource. fields also lets you format and filter the response so you don’t have to worry about exposing internal data structures. – Subir Verma May 06 '20 at 06:46