diff options
-rw-r--r-- | src/plop_httputil.erl | 52 |
1 files changed, 47 insertions, 5 deletions
diff --git a/src/plop_httputil.erl b/src/plop_httputil.erl index 37e25c1..99d26de 100644 --- a/src/plop_httputil.erl +++ b/src/plop_httputil.erl @@ -76,11 +76,7 @@ request(DebugTag, URL, Headers, RequestBody) -> lager:debug("~s: connected to ~p", [DebugTag, URL]), {ok, StatusCode, RespHeaders, ClientRef} = - hackney:send_request(ConnRef, - {post, Path, - add_auth("POST", Path, Headers, - RequestBody), - RequestBody}), + make_request(ConnRef, Path, Headers, RequestBody), lager:debug("~s: received headers for ~p: ~p", [DebugTag, URL, RespHeaders]), {ok, Body} = hackney:body(ClientRef), @@ -96,3 +92,49 @@ request(DebugTag, URL, Headers, RequestBody) -> {error, Error} -> {error, Error} end. + +-define(CHUNKSIZE, 512*1024). +make_request(ConnRef, Path, Headers, RequestBody) -> + %% Large bodies are "streamed" (i.e. HTTP chunking, in chunks of + %% CHUNKSIZE octets) if they're more than CHUNKSIZE octets in + %% size. + case byte_size(RequestBody) of + N when N > ?CHUNKSIZE -> + Req = {post, Path, + add_auth("POST", Path, + Headers ++ [{<<"Transfer-Encoding">>, <<"chunked">>}], + RequestBody), + stream}, + {ok, ConnRef2} = hackney:send_request(ConnRef, Req), + ok = hackney:send_body(ConnRef2, body_sender_fun(RequestBody)), + hackney:start_response(ConnRef2); + _ -> + Req = {post, Path, + add_auth("POST", Path, Headers, RequestBody), + RequestBody}, + hackney:send_request(ConnRef, Req) + end. + +chunk_it(Data) when byte_size(Data) > ?CHUNKSIZE -> + split_binary(Data, ?CHUNKSIZE); +chunk_it(Data) -> + {Data, <<>>}. + +send_some_body(Table) -> + [{body, Data}] = ets:lookup(Table, body), + case byte_size(Data) of + N when N =:= 0 -> + true = ets:delete(Table), + eof; + _ -> + {ToSend, TheRest} = chunk_it(Data), + true = ets:insert(Table, {body, TheRest}), + {ok, ToSend} + end. + +body_sender_fun(Body) -> + Table = ets:new(bodytable, []), + true = ets:insert(Table, {body, Body}), + fun() -> + send_some_body(Table) + end. |