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
Opened this issue · 1 comments
RiteshVarpe commented
- I have a cornice-based pyramid webserver running in Python 3.8(Alpine Linux) and a client calling one of its APIs using python requests without any request headers.
- Cornice+Pyramid webserver has msgpack(custom renderer added by me) and simplejson(default renderer of cornice) as renderers.
- Currently, I am getting inconsistent content-type(sometimes 'application/x-msgpack' and sometimes 'application/json') in the response headers.
- As per cornice documentation, the default renderer is simplejson thus I am expecting it should always convert the response object into json using json renderer factory of pyramid/cornice and send the response to the client with content-type as 'application/json'.
- Earlier, I used to have the same webserver running on python 2.7 version, where it was always sending response in json format with consistent content-type as 'application/json'.
- When I am passing request headers as {'Accept': 'application/json'} or {'Accept': 'application/x-msgpack'} then I am getting response as expected with the response been rendered with the appropriate renderer.
- I want to know the exact reason, why the default renderer being considered by the webserver is changing between msgpack and simplejson.
- Below are the files/configuration been used:
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
- I tried upgrading the packages mentioned in the requirements.txt but was not able to resolve the issue I am facing.
- Also, debugged the package code locally but was not able to find the root cause.
- Early reply to the issue will be appreciable.
leplatrem commented
The code that adds an internal view when no content type is passed is:
cornice/cornice/pyramidhook.py
Lines 246 to 256 in 511f04c
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)