From 9d0a0a52379f019deb2e479d9d5d87fe72cc98f5 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Thu, 8 Sep 2011 11:13:21 +0000 Subject: COUCHDB-1274 - Use text/javascript content-type for jsonp responses. Backported from trunk @1166618 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1166627 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 1 + NEWS | 1 + share/www/script/test/jsonp.js | 2 ++ src/couchdb/couch_httpd.erl | 35 ++++++++++++++++++++++------------- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGES b/CHANGES index 12efc0b3..64b4f3c1 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Version 1.1.1 This version has not been released yet. * ETags for views include current sequence if include_docs=true. +* JSONP responses now send "text/javascript" for Content-Type. Version 1.1.0 ------------- diff --git a/NEWS b/NEWS index 4803ba24..d7dc7cf1 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,7 @@ Version 1.1.1 This version has not been released yet. * ETags for views include current sequence if include_docs=true. +* JSONP responses now send "text/javascript" for Content-Type. Version 1.1.0 ------------- diff --git a/share/www/script/test/jsonp.js b/share/www/script/test/jsonp.js index 9aba7189..d1bca94a 100644 --- a/share/www/script/test/jsonp.js +++ b/share/www/script/test/jsonp.js @@ -48,6 +48,7 @@ couchTests.jsonp = function(debug) { // Test unchunked callbacks. var xhr = CouchDB.request("GET", "/test_suite_db/0?callback=jsonp_no_chunk"); + TEquals("text/javascript", xhr.getResponseHeader("Content-Type")); T(xhr.status == 200); jsonp_flag = 0; eval(xhr.responseText); @@ -70,6 +71,7 @@ couchTests.jsonp = function(debug) { var url = "/test_suite_db/_design/test/_view/all_docs?callback=jsonp_chunk"; xhr = CouchDB.request("GET", url); + TEquals("text/javascript", xhr.getResponseHeader("Content-Type")); T(xhr.status == 200); jsonp_flag = 0; eval(xhr.responseText); diff --git a/src/couchdb/couch_httpd.erl b/src/couchdb/couch_httpd.erl index e472d094..15b85df8 100644 --- a/src/couchdb/couch_httpd.erl +++ b/src/couchdb/couch_httpd.erl @@ -627,25 +627,25 @@ send_json(Req, Code, Value) -> send_json(Req, Code, [], Value). send_json(Req, Code, Headers, Value) -> + initialize_jsonp(Req), DefaultHeaders = [ {"Content-Type", negotiate_content_type(Req)}, {"Cache-Control", "must-revalidate"} ], - Body = [start_jsonp(Req), ?JSON_ENCODE(Value), end_jsonp(), $\n], + Body = [start_jsonp(), ?JSON_ENCODE(Value), end_jsonp(), $\n], send_response(Req, Code, DefaultHeaders ++ Headers, Body). start_json_response(Req, Code) -> start_json_response(Req, Code, []). start_json_response(Req, Code, Headers) -> + initialize_jsonp(Req), DefaultHeaders = [ {"Content-Type", negotiate_content_type(Req)}, {"Cache-Control", "must-revalidate"} ], - start_jsonp(Req), % Validate before starting chunked. - %start_chunked_response(Req, Code, DefaultHeaders ++ Headers). {ok, Resp} = start_chunked_response(Req, Code, DefaultHeaders ++ Headers), - case start_jsonp(Req) of + case start_jsonp() of [] -> ok; Start -> send_chunk(Resp, Start) end, @@ -655,7 +655,7 @@ end_json_response(Resp) -> send_chunk(Resp, end_jsonp() ++ [$\n]), last_chunk(Resp). -start_jsonp(Req) -> +initialize_jsonp(Req) -> case get(jsonp) of undefined -> put(jsonp, qs_value(Req, "callback", no_jsonp)); _ -> ok @@ -668,14 +668,9 @@ start_jsonp(Req) -> % make sure jsonp is configured on (default off) case couch_config:get("httpd", "allow_jsonp", "false") of "true" -> - validate_callback(CallBack), - CallBack ++ "("; + validate_callback(CallBack); _Else -> - % this could throw an error message, but instead we just ignore the - % jsonp parameter - % throw({bad_request, <<"JSONP must be configured before using.">>}) - put(jsonp, no_jsonp), - [] + put(jsonp, no_jsonp) end catch Error -> @@ -684,6 +679,13 @@ start_jsonp(Req) -> end end. +start_jsonp() -> + case get(jsonp) of + no_jsonp -> []; + [] -> []; + CallBack -> CallBack ++ "(" + end. + end_jsonp() -> Resp = case get(jsonp) of no_jsonp -> []; @@ -844,7 +846,14 @@ send_redirect(Req, Path) -> Headers = [{"Location", couch_httpd:absolute_uri(Req, Path)}], send_response(Req, 301, Headers, <<>>). -negotiate_content_type(#httpd{mochi_req=MochiReq}) -> +negotiate_content_type(Req) -> + case get(jsonp) of + no_jsonp -> negotiate_content_type1(Req); + [] -> negotiate_content_type1(Req); + _Callback -> "text/javascript" + end. + +negotiate_content_type1(#httpd{mochi_req=MochiReq}) -> %% Determine the appropriate Content-Type header for a JSON response %% depending on the Accept header in the request. A request that explicitly %% lists the correct JSON MIME type will get that type, otherwise the -- cgit v1.2.3