summaryrefslogtreecommitdiff
path: root/pecan/core.py
diff options
context:
space:
mode:
authorRyan Petrello <lists@ryanpetrello.com>2012-11-02 17:25:34 -0400
committerRyan Petrello <lists@ryanpetrello.com>2012-11-03 07:17:11 -0400
commiteccc1eff14b39c9758ea3865d62865890130cc1c (patch)
tree1ffb0ea9a19036fe1315e58e87a9de605e75ef35 /pecan/core.py
parentd8e53a2c8318d97952e6b13a19d2f5c44cbbb55a (diff)
downloadpecan-eccc1eff14b39c9758ea3865d62865890130cc1c.tar.gz
Add support for content type detection via Accept headers.
Diffstat (limited to 'pecan/core.py')
-rw-r--r--pecan/core.py36
1 files changed, 31 insertions, 5 deletions
diff --git a/pecan/core.py b/pecan/core.py
index 1ff1663..20576e1 100644
--- a/pecan/core.py
+++ b/pecan/core.py
@@ -3,7 +3,7 @@ from routing import lookup_controller, NonCanonicalPath
from util import _cfg, encode_if_needed
from middleware.recursive import ForwardRequestException
-from webob import Request, Response, exc
+from webob import Request, Response, exc, acceptparse
from threading import local
from itertools import chain
from mimetypes import guess_type, add_type
@@ -367,6 +367,7 @@ class Pecan(object):
# by the file extension on the URI
path = request.pecan['routing_path']
+ # attempt to guess the content type based on the file extension
if not request.pecan['content_type'] and '.' in path.split('/')[-1]:
path, extension = splitext(path)
request.pecan['extension'] = extension
@@ -392,10 +393,35 @@ class Pecan(object):
# if unsure ask the controller for the default content type
if not request.pecan['content_type']:
- request.pecan['content_type'] = cfg.get(
- 'content_type',
- 'text/html'
- )
+ # attempt to find a best match based on accept headers (if they
+ # exist)
+ if 'Accept' in request.headers:
+ best_default = acceptparse.MIMEAccept(
+ request.headers['Accept']
+ ).best_match(
+ cfg.get('content_types', {}).keys()
+ )
+
+ if best_default is None:
+ import warnings
+ msg = "Controller '%s' defined does not support " + \
+ "content_type '%s'. Supported type(s): %s"
+ warnings.warn(
+ msg % (
+ controller.__name__,
+ request.pecan['content_type'],
+ cfg.get('content_types', {}).keys()
+ ),
+ RuntimeWarning
+ )
+ raise exc.HTTPNotFound
+
+ request.pecan['content_type'] = best_default
+ else:
+ request.pecan['content_type'] = cfg.get(
+ 'content_type',
+ 'text/html'
+ )
elif cfg.get('content_type') is not None and \
request.pecan['content_type'] not in \
cfg.get('content_types', {}):