5252 req ,
5353 code ,
5454 headers ,
55- first_chunk ,
56- resp = nil
55+ chunks ,
56+ resp = nil ,
57+ buffer_response = false
5758}).
5859
5960start_link () ->
@@ -780,40 +781,54 @@ start_json_response(Req, Code, Headers0) ->
780781end_json_response (Resp ) ->
781782 couch_httpd :end_json_response (Resp ).
782783
784+
783785start_delayed_json_response (Req , Code ) ->
784786 start_delayed_json_response (Req , Code , []).
785787
788+
786789start_delayed_json_response (Req , Code , Headers ) ->
787790 start_delayed_json_response (Req , Code , Headers , " " ).
788791
792+
789793start_delayed_json_response (Req , Code , Headers , FirstChunk ) ->
790794 {ok , # delayed_resp {
791795 start_fun = fun start_json_response /3 ,
792796 req = Req ,
793797 code = Code ,
794798 headers = Headers ,
795- first_chunk = FirstChunk }}.
799+ chunks = [FirstChunk ],
800+ buffer_response = buffer_response (Req )}}.
801+
796802
797803start_delayed_chunked_response (Req , Code , Headers ) ->
798804 start_delayed_chunked_response (Req , Code , Headers , " " ).
799805
806+
800807start_delayed_chunked_response (Req , Code , Headers , FirstChunk ) ->
801808 {ok , # delayed_resp {
802809 start_fun = fun start_chunked_response /3 ,
803810 req = Req ,
804811 code = Code ,
805812 headers = Headers ,
806- first_chunk = FirstChunk }}.
813+ chunks = [FirstChunk ],
814+ buffer_response = buffer_response (Req )}}.
815+
807816
808- send_delayed_chunk (# delayed_resp {}= DelayedResp , Chunk ) ->
817+ send_delayed_chunk (# delayed_resp {buffer_response = false }= DelayedResp , Chunk ) ->
809818 {ok , # delayed_resp {resp = Resp }= DelayedResp1 } =
810819 start_delayed_response (DelayedResp ),
811820 {ok , Resp } = send_chunk (Resp , Chunk ),
812- {ok , DelayedResp1 }.
821+ {ok , DelayedResp1 };
822+
823+ send_delayed_chunk (# delayed_resp {buffer_response = true }= DelayedResp , Chunk ) ->
824+ # delayed_resp {chunks = Chunks } = DelayedResp ,
825+ {ok , DelayedResp # delayed_resp {chunks = [Chunk | Chunks ]}}.
826+
813827
814828send_delayed_last_chunk (Req ) ->
815829 send_delayed_chunk (Req , []).
816830
831+
817832send_delayed_error (# delayed_resp {req = Req ,resp = nil }= DelayedResp , Reason ) ->
818833 {Code , ErrorStr , ReasonStr } = error_info (Reason ),
819834 {ok , Resp } = send_error (Req , Code , ErrorStr , ReasonStr ),
@@ -823,6 +838,7 @@ send_delayed_error(#delayed_resp{resp=Resp, req=Req}, Reason) ->
823838 log_error_with_stack_trace (Reason ),
824839 throw ({http_abort , Resp , Reason }).
825840
841+
826842close_delayed_json_object (Resp , Buffer , Terminator , 0 ) ->
827843 % Use a separate chunk to close the streamed array to maintain strict
828844 % compatibility with earlier versions. See COUCHDB-2724
@@ -831,10 +847,22 @@ close_delayed_json_object(Resp, Buffer, Terminator, 0) ->
831847close_delayed_json_object (Resp , Buffer , Terminator , _Threshold ) ->
832848 send_delayed_chunk (Resp , [Buffer | Terminator ]).
833849
834- end_delayed_json_response (# delayed_resp {}= DelayedResp ) ->
850+
851+ end_delayed_json_response (# delayed_resp {buffer_response = false }= DelayedResp ) ->
835852 {ok , # delayed_resp {resp = Resp }} =
836853 start_delayed_response (DelayedResp ),
837- end_json_response (Resp ).
854+ end_json_response (Resp );
855+
856+ end_delayed_json_response (# delayed_resp {buffer_response = true }= DelayedResp ) ->
857+ # delayed_resp {
858+ req = Req ,
859+ code = Code ,
860+ headers = Headers ,
861+ chunks = Chunks
862+ } = DelayedResp ,
863+ {ok , Resp } = start_response_length (Req , Code , Headers , iolist_size (Chunks )),
864+ send (Resp , lists :reverse (Chunks )).
865+
838866
839867get_delayed_req (# delayed_resp {req = # httpd {mochi_req = MochiReq }}) ->
840868 MochiReq ;
@@ -847,7 +875,7 @@ start_delayed_response(#delayed_resp{resp=nil}=DelayedResp) ->
847875 req = Req ,
848876 code = Code ,
849877 headers = Headers ,
850- first_chunk = FirstChunk
878+ chunks = [ FirstChunk ]
851879 }= DelayedResp ,
852880 {ok , Resp } = StartFun (Req , Code , Headers ),
853881 case FirstChunk of
@@ -858,6 +886,18 @@ start_delayed_response(#delayed_resp{resp=nil}=DelayedResp) ->
858886start_delayed_response (# delayed_resp {}= DelayedResp ) ->
859887 {ok , DelayedResp }.
860888
889+
890+ buffer_response (Req ) ->
891+ case chttpd :qs_value (Req , " buffer_response" ) of
892+ " false" ->
893+ false ;
894+ " true" ->
895+ true ;
896+ _ ->
897+ config :get_boolean (" chttpd" , " buffer_response" , false )
898+ end .
899+
900+
861901error_info ({Error , Reason }) when is_list (Reason ) ->
862902 error_info ({Error , couch_util :to_binary (Reason )});
863903error_info (bad_request ) ->
0 commit comments