Repository: encode/django-rest-framework

Issue:
Response Content-Type potentially malformed
## Checklist
- [x] I have verified that that issue exists against the `master` branch of Django REST framework.
- [x] I have searched for similar issues in both open and closed tickets and cannot find a duplicate.
- [x] This is not a usage question. (Those should be directed to the [discussion group](https://groups.google.com/forum/#!forum/django-rest-framework) instead.)
- [ ] This cannot be dealt with as a third party library. (We prefer new functionality to be [in the form of third party libraries](http://www.django-rest-framework.org/topics/third-party-resources/#about-third-party-packages) where possible.)
- [x] I have reduced the issue to the simplest possible case.
- [ ] I have included a failing test as a pull request. (If you are unable to do so we can still accept the issue.)
## Problem description

The default request header 'Accept' on many browsers is something like `Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`.  This means that currently, if the response is not `text/html`, then the response `Content-Type` incorrectly contains the `q=` parameter.  (According to [this](http://stackoverflow.com/a/10496722/3108853), the `q` parameter specifies which content-types the browser prefers).

It looks like it is occurring because:
1. [DefaultContentNegotiation.select_renderer](https://github.com/tomchristie/django-rest-framework/blob/10a080d395b8f1fc5cef0778cd2a40c3d81dfe19/rest_framework/negotiation.py#L67-L72) returns the `full_media_type` (which includes the extra `Accept` "parameters" like `q`)
2. [ApiView.perform_content_negotiation](https://github.com/tomchristie/django-rest-framework/blob/10a080d395b8f1fc5cef0778cd2a40c3d81dfe19/rest_framework/views.py#L296) returns the `renderer, full_media_type` tuple
3. [ApiView.initial](https://github.com/tomchristie/django-rest-framework/blob/10a080d395b8f1fc5cef0778cd2a40c3d81dfe19/rest_framework/views.py#L376-L377) sets `request.accepted_media_type` equal to that `full_media_type`
4. [ApiView.finalize_response](https://github.com/tomchristie/django-rest-framework/blob/10a080d395b8f1fc5cef0778cd2a40c3d81dfe19/rest_framework/views.py#L405) sets `response.accepted_media_type` equal to `request.accepted_media_type`
5. [Response.rendered_content](https://github.com/tomchristie/django-rest-framework/blob/bb56ca46ed6c07db0146dbdc61c672ff25f127de/rest_framework/response.py#L65-L69) is setting the response `Content-Type` to the value of `response.accepted_media_type`.

This only came to light because I'm running nginx in front of django, and it was not recognizing the content-type (as `application/json` is different from `application/json;q=0.9`).  As far as I can tell, this is actually an invalid Content-Type (https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17).
## Steps to reproduce

curl --verbose http://example.com/api/model?format=json  --H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,_/_;q=0.8' > /dev/null
## Expected behavior

`Content-Type: application/json; charset=utf-8`
## Actual behavior

`Content-Type: application/json;q=0.9; charset=utf-8`



Discussion:
Closing this as I couldn't replicate the described behavior...

```
$ curl --verbose http://restframework.herokuapp.com/?format=json -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8'
```

   --> 406 {"detail":"Could not satisfy the request Accept header."}

Or this, without the `format=json`...

```
$ curl --verbose http://restframework.herokuapp.com/ -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8'
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
...
```

More than happy to reopen this if you can demo an example against `http://restframework.herokuapp.com/` that I can replicate, _or_ if you can demo that the behavior has changed, and that the latest version of REST framework running the tutorial _does_ demonstrate the issue, _or_ if you can provide an example pull request that demonstrates that we do have an issue.

They are different.

In [`master`](https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/negotiation.py#L72), the return value is the `full_media_type` (e.g. includes `q` and `indent`).

In [`3.1`](https://github.com/tomchristie/django-rest-framework/blob/3.1.0/rest_framework/negotiation.py#L63), the return value is `renderer.media_type`, which does not include the extra parameters passed in by the `Accept` header.

Thanks for confirming.


Resolving patch:
diff --git a/rest_framework/response.py b/rest_framework/response.py
--- a/rest_framework/response.py
+++ b/rest_framework/response.py
@@ -51,14 +51,13 @@ def __init__(self, data=None, status=None,
     @property
     def rendered_content(self):
         renderer = getattr(self, 'accepted_renderer', None)
-        media_type = getattr(self, 'accepted_media_type', None)
         context = getattr(self, 'renderer_context', None)
 
         assert renderer, ".accepted_renderer not set on Response"
-        assert media_type, ".accepted_media_type not set on Response"
         assert context, ".renderer_context not set on Response"
         context['response'] = self
 
+        media_type = renderer.media_type
         charset = renderer.charset
         content_type = self.content_type
 


Test patch: