diff options
author | Linus Nordberg <linus@nordu.net> | 2016-02-20 20:45:06 +0100 |
---|---|---|
committer | Linus Nordberg <linus@nordu.net> | 2016-02-20 20:45:06 +0100 |
commit | 908ad4b1f94d9bbf3706a42106859e751565b01e (patch) | |
tree | c772e84224b96eef5b84325c94e750fca4b89306 | |
parent | 7f15cd5a881d2d14f80ddf5219577561d3d91eeb (diff) |
Chunk HTTP requests if larger than 512 kB.http-chunking
-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. |