You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by jc...@apache.org on 2009/02/28 01:04:11 UTC

svn commit: r748754 - in /couchdb/trunk: share/www/script/test/list_views.js src/couchdb/couch_httpd_show.erl

Author: jchris
Date: Sat Feb 28 00:04:10 2009
New Revision: 748754

URL: http://svn.apache.org/viewvc?rev=748754&view=rev
Log:
supply etags for reduce view lists

Modified:
    couchdb/trunk/share/www/script/test/list_views.js
    couchdb/trunk/src/couchdb/couch_httpd_show.erl

Modified: couchdb/trunk/share/www/script/test/list_views.js
URL: http://svn.apache.org/viewvc/couchdb/trunk/share/www/script/test/list_views.js?rev=748754&r1=748753&r2=748754&view=diff
==============================================================================
--- couchdb/trunk/share/www/script/test/list_views.js (original)
+++ couchdb/trunk/share/www/script/test/list_views.js Sat Feb 28 00:04:10 2009
@@ -193,10 +193,28 @@
   T(/Key: 1/.test(xhr.responseText));
   
   // when there is a reduce present, and used
-  var xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true");
+  xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true");
   T(xhr.status == 200);
   T(/Key: 1/.test(xhr.responseText));
   
+  // there should be etags on reduce as well
+  var etag = xhr.getResponseHeader("etag");
+  T(etag, "Etags should be served with reduce lists");
+  xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true", {
+    headers: {"if-none-match": etag}
+  });
+  T(xhr.status == 304);
+  
+  // verify the etags expire correctly
+  var docs = makeDocs(11, 12);
+  var saveResult = db.bulkSave(docs);
+  T(saveResult.ok);
+  
+  xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/simpleForm/withReduce?group=true", {
+    headers: {"if-none-match": etag}
+  });
+  T(xhr.status == 200);
+  
   // with accept headers for HTML
   xhr = CouchDB.request("GET", "/test_suite_db/_list/lists/acceptSwitch/basicView", {
     headers: {

Modified: couchdb/trunk/src/couchdb/couch_httpd_show.erl
URL: http://svn.apache.org/viewvc/couchdb/trunk/src/couchdb/couch_httpd_show.erl?rev=748754&r1=748753&r2=748754&view=diff
==============================================================================
--- couchdb/trunk/src/couchdb/couch_httpd_show.erl (original)
+++ couchdb/trunk/src/couchdb/couch_httpd_show.erl Sat Feb 28 00:04:10 2009
@@ -56,6 +56,9 @@
     ListSrc = get_nested_json_value({Props}, [<<"lists">>, ListName]),
     send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db);
 
+handle_view_list_req(#httpd{method='GET'}=Req, _Db) ->
+    send_error(Req, 404, <<"list_error">>, <<"Invalid path.">>);
+
 handle_view_list_req(Req, _Db) ->
     send_method_not_allowed(Req, "GET,HEAD").
 
@@ -71,7 +74,6 @@
     throw({not_found, json_mismatch}).
 
 send_view_list_response(Lang, ListSrc, ViewName, DesignId, Req, Db) ->
-    % TODO add etags when we get view etags
     #view_query_args{
         stale = Stale,
         reduce = Reduce
@@ -124,7 +126,6 @@
                 headers = ExtHeaders
             } = couch_httpd_external:parse_external_response(JsonResp),
             JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
-            % TODO use the Etag
             {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
             {ok, Resp, binary_to_list(BeginBody)}
         end,
@@ -181,53 +182,56 @@
     Hlist = mochiweb_headers:to_list(Headers),
     Accept = proplists:get_value('Accept', Hlist),
     CurrentEtag = couch_httpd_view:view_group_etag(Group, {Lang, ListSrc, Accept}),
-
-    StartListRespFun = fun(Req2, _Etag, _, _) ->
-        JsonResp = couch_query_servers:render_reduce_head(QueryServer, 
-            Req2, Db),
-        #extern_resp_args{
-            code = Code,
-            data = BeginBody,
-            ctype = CType,
-            headers = ExtHeaders
-        } = couch_httpd_external:parse_external_response(JsonResp),
-        JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
-        {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
-        {ok, Resp, binary_to_list(BeginBody)}
-    end,
-    
-    SendListRowFun = fun(Resp, {Key, Value}, RowFront) ->
-        JsonResp = couch_query_servers:render_reduce_row(QueryServer, 
-            Req, Db, {Key, Value}),
-        #extern_resp_args{
-            stop = StopIter,
-            data = RowBody
-        } = couch_httpd_external:parse_external_response(JsonResp),
-        RowFront2 = case RowFront of
-        nil -> [];
-        _ -> RowFront
+    couch_httpd:etag_respond(Req, CurrentEtag, fun() ->
+        StartListRespFun = fun(Req2, _Etag, _, _) ->
+            JsonResp = couch_query_servers:render_reduce_head(QueryServer, 
+                Req2, Db),
+            JsonResp2 = apply_etag(JsonResp, CurrentEtag),
+            #extern_resp_args{
+                code = Code,
+                data = BeginBody,
+                ctype = CType,
+                headers = ExtHeaders
+            } = couch_httpd_external:parse_external_response(JsonResp2),
+            JsonHeaders = couch_httpd_external:default_or_content_type(CType, ExtHeaders),
+            {ok, Resp} = start_chunked_response(Req, Code, JsonHeaders),
+            {ok, Resp, binary_to_list(BeginBody)}
         end,
-        case StopIter of
-        true -> stop;
-        _ ->
-            Chunk = RowFront2 ++ binary_to_list(RowBody),
-            case Chunk of
-                [] -> {ok, Resp};
-                _ -> send_chunk(Resp, Chunk)
+    
+        SendListRowFun = fun(Resp, {Key, Value}, RowFront) ->
+            JsonResp = couch_query_servers:render_reduce_row(QueryServer, 
+                Req, Db, {Key, Value}),
+            #extern_resp_args{
+                stop = StopIter,
+                data = RowBody
+            } = couch_httpd_external:parse_external_response(JsonResp),
+            RowFront2 = case RowFront of
+            nil -> [];
+            _ -> RowFront
+            end,
+            case StopIter of
+            true -> stop;
+            _ ->
+                Chunk = RowFront2 ++ binary_to_list(RowBody),
+                case Chunk of
+                    [] -> {ok, Resp};
+                    _ -> send_chunk(Resp, Chunk)
+                end
             end
-        end
-    end,
+        end,
     
-    {ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req, GroupLevel, QueryArgs, CurrentEtag, 
-    #reduce_fold_helper_funs{
-        start_response = StartListRespFun,
-        send_row = SendListRowFun
-    }),
-    FoldAccInit = {Limit, SkipCount, undefined, []},
-    FoldResult = couch_view:fold_reduce(View, Dir, {StartKey, StartDocId},
-        {EndKey, EndDocId}, GroupRowsFun, RespFun,
-        FoldAccInit),
-    finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null).
+        {ok, GroupRowsFun, RespFun} = couch_httpd_view:make_reduce_fold_funs(Req, 
+            GroupLevel, QueryArgs, CurrentEtag, 
+            #reduce_fold_helper_funs{
+                start_response = StartListRespFun,
+                send_row = SendListRowFun
+            }),
+        FoldAccInit = {Limit, SkipCount, undefined, []},
+        FoldResult = couch_view:fold_reduce(View, Dir, {StartKey, StartDocId},
+            {EndKey, EndDocId}, GroupRowsFun, RespFun,
+            FoldAccInit),
+        finish_list(Req, Db, QueryServer, CurrentEtag, FoldResult, StartListRespFun, null)
+    end).
 
 finish_list(Req, Db, QueryServer, Etag, FoldResult, StartListRespFun, TotalRows) ->
     case FoldResult of
@@ -266,7 +270,8 @@
         couch_httpd_external:send_external_response(Req, JsonResp)
     end);
 
-send_doc_show_response(Lang, ShowSrc, #doc{revs=[DocRev|_]}=Doc, #httpd{mochi_req=MReq}=Req, Db) ->
+send_doc_show_response(Lang, ShowSrc, #doc{revs=[DocRev|_]}=Doc, 
+    #httpd{mochi_req=MReq}=Req, Db) ->
     % calculate the etag
     Headers = MReq:get(headers),
     Hlist = mochiweb_headers:to_list(Headers),