Cornices / cornice

Build Web Services with Pyramid.
https://cornice.readthedocs.io
Other
384 stars 149 forks source link

Inconsistent content-type received in the response headers for request headers (Accept: */* or No Accept headers) in cornice+pyramid webserver running on python 3.8 alpine linux version #578

Open RiteshVarpe opened 9 months ago

RiteshVarpe commented 9 months ago

A. requirements.txt

simplejson==3.10.0
pyramid==1.5.7
chardet==3.0.4
colander==1.0b1
cornice==1.0
msgpack==1.0.4
lz4==4.0.2
lz4tools==1.3.1.2
PyYAML==3.11
SQLAlchemy==1.4.0
psycopg2-binary==2.9.5
enum34==1.1.6
python-dateutil==2.2
pytz==2014.10
requests==2.7.0
waitress==0.8.9
Paste==3.5.2
jsonschema==2.3.0

B. webserver/init.py

# -*- coding: utf-8 -*-

"""Main entry point
"""

import os

from pyramid.config import Configurator
from pyramid.events import NewResponse
from sdk.pyramid.viewutils import MsgpackRendererFactory, notfound, lz4_compress_response

class MsgpackRendererFactory(object):

    def __init__(self, info):
        pass

    def __call__(self, value, system):
        request = system.get('request')
        if request is not None:
            response = request.response
            response.content_type = 'application/x-msgpack'
        return msgpack.dumps(value)

def main(global_config, **settings):
    route_prefix = settings.get('reports.route_prefix')
    config = Configurator(settings=settings, route_prefix=route_prefix)

    config.add_settings(handle_exceptions=False)
    config.add_notfound_view(notfound, append_slash=True)

    config.add_renderer(name='msgpack', factory=MsgpackRendererFactory)

    config.include('cornice')

    return config.make_wsgi_app()

C. webserver/views.py

@resource(path='path_to_the_api')
class ResourceView():

    @view(accept='application/x-msgpack', renderer='msgpack')
    @view(accept='application/json', renderer='simplejson')
    def get(self):
            # Data fetched from DB stored in 'resource' variable
        resource = .......... # Calling DB to get data
            return {'resources': resource}

D. Client code

url = 'https://X.X.X.X/path_to_webserver_api'
response = requests.get(url)

body = response.json() # works only if the content-type received is 'application/json' else code                 
                       # breaks at this point 
leplatrem commented 9 months ago

The code that adds an internal view when no content type is passed is:

https://github.com/Cornices/cornice/blob/511f04c6cb4d262515efbb698fc366cc1d67bace/cornice/pyramidhook.py#L246-L256

I don't know what would cause this inconsistent behavior, and have limited time to investigate.

If you are in a hurry, as a workaround, you could try to add a default request header?

from pyramid.events import NewRequest

def set_default_header(event):
    request = event.request
    request.headers.setdefault("Accept", "application/json")

config.add_subscriber(set_default_header, NewRequest)