summaryrefslogtreecommitdiff
path: root/src/mod_http_upload.erl
diff options
context:
space:
mode:
authorHolger Weiss <holger@zedat.fu-berlin.de>2016-05-08 15:36:51 +0200
committerHolger Weiss <holger@zedat.fu-berlin.de>2016-05-08 15:36:51 +0200
commitf7f40cf9a6b2599a8246a2282a0e49df4c7ebeca (patch)
tree454e88a62f74c702fa8463d2d750f0006d279c8b /src/mod_http_upload.erl
parentAvoid error bounces when testing stream management (diff)
Let client retry HTTP upload on file size mismatch
Let the main mod_http_upload process look at the size of an HTTP upload rather than performing this check in the ejabberd_http handler. This way, the upload slot won't be invalidated if the size of the uploaded file doesn't match the size requested for the slot. The PUT request is still rejected, but the client now has a chance to retry the upload.
Diffstat (limited to 'src/mod_http_upload.erl')
-rw-r--r--src/mod_http_upload.erl35
1 files changed, 18 insertions, 17 deletions
diff --git a/src/mod_http_upload.erl b/src/mod_http_upload.erl
index b01ca9d2..0bb38370 100644
--- a/src/mod_http_upload.erl
+++ b/src/mod_http_upload.erl
@@ -321,22 +321,24 @@ init({ServerHost, Opts}) ->
-> {reply, {ok, pos_integer(), binary(),
pos_integer() | undefined,
pos_integer() | undefined}, state()} |
- {reply, {error, binary()}, state()} | {noreply, state()}.
+ {reply, {error, atom()}, state()} | {noreply, state()}.
-handle_call({use_slot, Slot}, _From, #state{file_mode = FileMode,
- dir_mode = DirMode,
- get_url = GetPrefix,
- thumbnail = Thumbnail,
- docroot = DocRoot} = State) ->
+handle_call({use_slot, Slot, Size}, _From, #state{file_mode = FileMode,
+ dir_mode = DirMode,
+ get_url = GetPrefix,
+ thumbnail = Thumbnail,
+ docroot = DocRoot} = State) ->
case get_slot(Slot, State) of
{ok, {Size, Timer}} ->
timer:cancel(Timer),
NewState = del_slot(Slot, State),
Path = str:join([DocRoot | Slot], <<$/>>),
- {reply, {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail},
+ {reply, {ok, Path, FileMode, DirMode, GetPrefix, Thumbnail},
NewState};
+ {ok, {_WrongSize, _Timer}} ->
+ {reply, {error, size_mismatch}, State};
error ->
- {reply, {error, <<"Invalid slot">>}, State}
+ {reply, {error, invalid_slot}, State}
end;
handle_call(get_docroot, _From, #state{docroot = DocRoot} = State) ->
{reply, {ok, DocRoot}, State};
@@ -406,9 +408,8 @@ process(LocalPath, #request{method = Method, host = Host, ip = IP})
process(_LocalPath, #request{method = 'PUT', host = Host, ip = IP,
data = Data} = Request) ->
{Proc, Slot} = parse_http_request(Request),
- case catch gen_server:call(Proc, {use_slot, Slot}) of
- {ok, Size, Path, FileMode, DirMode, GetPrefix, Thumbnail}
- when byte_size(Data) == Size ->
+ case catch gen_server:call(Proc, {use_slot, Slot, byte_size(Data)}) of
+ {ok, Path, FileMode, DirMode, GetPrefix, Thumbnail} ->
?DEBUG("Storing file from ~s for ~s: ~s",
[?ADDR_TO_STR(IP), Host, Path]),
case store_file(Path, Data, FileMode, DirMode,
@@ -422,13 +423,13 @@ process(_LocalPath, #request{method = 'PUT', host = Host, ip = IP,
[Path, ?ADDR_TO_STR(IP), Host, ?FORMAT(Error)]),
http_response(Host, 500)
end;
- {ok, Size, Path, _FileMode, _DirMode, _GetPrefix, _Thumbnail} ->
- ?INFO_MSG("Rejecting file ~s from ~s for ~s: Size is ~B, not ~B",
- [Path, ?ADDR_TO_STR(IP), Host, byte_size(Data), Size]),
+ {error, size_mismatch} ->
+ ?INFO_MSG("Rejecting file from ~s for ~s: Unexpected size (~B)",
+ [?ADDR_TO_STR(IP), Host, byte_size(Data)]),
http_response(Host, 413);
- {error, Error} ->
- ?INFO_MSG("Rejecting file from ~s for ~s: ~p",
- [?ADDR_TO_STR(IP), Host, Error]),
+ {error, invalid_slot} ->
+ ?INFO_MSG("Rejecting file from ~s for ~s: Invalid slot",
+ [?ADDR_TO_STR(IP), Host]),
http_response(Host, 403);
Error ->
?ERROR_MSG("Cannot handle PUT request from ~s for ~s: ~p",