diff options
Diffstat (limited to 'src/cowboy_rest.erl')
-rw-r--r-- | src/cowboy_rest.erl | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/src/cowboy_rest.erl b/src/cowboy_rest.erl index 914b273..55b4e22 100644 --- a/src/cowboy_rest.erl +++ b/src/cowboy_rest.erl @@ -198,7 +198,6 @@ %% End of REST callbacks. Whew! -record(state, { - env :: cowboy_middleware:env(), method = undefined :: binary(), %% Handler. @@ -235,10 +234,11 @@ -spec upgrade(Req, Env, module(), any(), infinity, run) -> {ok, Req, Env} when Req::cowboy_req:req(), Env::cowboy_middleware:env(). -upgrade(Req, Env, Handler, HandlerState, infinity, run) -> - Method = cowboy_req:method(Req), - service_available(Req, #state{env=Env, method=Method, - handler=Handler, handler_state=HandlerState}). +upgrade(Req0, Env, Handler, HandlerState, infinity, run) -> + Method = cowboy_req:method(Req0), + {ok, Req, Result} = service_available(Req0, #state{method=Method, + handler=Handler, handler_state=HandlerState}), + {ok, Req, [{result, Result}|Env]}. service_available(Req, State) -> expect(Req, State, service_available, true, fun known_methods/2, 503). @@ -683,9 +683,12 @@ if_match_exists(Req, State) -> if_match(Req, State, EtagsList) -> try generate_etag(Req, State) of + %% Strong Etag comparison: weak Etag never matches. + {{weak, _}, Req2, State2} -> + precondition_failed(Req2, State2); {Etag, Req2, State2} -> case lists:member(Etag, EtagsList) of - true -> if_unmodified_since_exists(Req2, State2); + true -> if_none_match_exists(Req2, State2); %% Etag may be `undefined' which cannot be a member. false -> precondition_failed(Req2, State2) end @@ -738,15 +741,23 @@ if_none_match(Req, State, EtagsList) -> undefined -> precondition_failed(Req2, State2); Etag -> - case lists:member(Etag, EtagsList) of + case is_weak_match(Etag, EtagsList) of true -> precondition_is_head_get(Req2, State2); - false -> if_modified_since_exists(Req2, State2) + false -> method(Req2, State2) end end catch Class:Reason -> error_terminate(Req, State, Class, Reason, generate_etag) end. +%% Weak Etag comparison: only check the opaque tag. +is_weak_match(_, []) -> + false; +is_weak_match({_, Tag}, [{_, Tag}|_]) -> + true; +is_weak_match(Etag, [_|Tail]) -> + is_weak_match(Etag, Tail). + precondition_is_head_get(Req, State=#state{method=Method}) when Method =:= <<"HEAD">>; Method =:= <<"GET">> -> not_modified(Req, State); @@ -1156,6 +1167,6 @@ error_terminate(Req, #state{handler=Handler, handler_state=HandlerState}, {state, HandlerState} ]}). -terminate(Req, #state{env=Env, handler=Handler, handler_state=HandlerState}) -> +terminate(Req, #state{handler=Handler, handler_state=HandlerState}) -> Result = cowboy_handler:terminate(normal, Req, HandlerState, Handler), - {ok, Req, [{result, Result}|Env]}. + {ok, Req, Result}. |