Commits

Bryan Fink  committed e97d77b

add some helpful error messages to 400 responses from mapred_resource

  • Participants
  • Parent commits 6c7a8fa

Comments (0)

Files changed (1)

File apps/riak/src/mapred_resource.erl

     end.
 
 allowed_methods(RD, State) ->
-    {['POST'], RD, State}.
+    {['GET','HEAD','POST'], RD, State}.
 
 malformed_request(RD, State) ->
-    {IsMalformed, NewState} = case wrq:req_body(RD) of
-                                  undefined ->
-                                      {true, State};
-                                  Body ->
-                                      {Verified, State1} = verify_body(Body, State),
-                                      {not(Verified), State1}
-                              end,
-    {IsMalformed, RD, NewState}.
+    {Verified, Message, NewState} =
+        case {wrq:method(RD), wrq:req_body(RD)} of
+            {'POST', Body} when Body /= undefined ->
+                verify_body(Body, State);
+            _ ->
+                {false, usage(), State}
+        end,
+    {not Verified,
+     if Verified -> RD;
+        true ->
+             wrq:set_resp_header(
+               "Content-Type", "text/plain",
+               wrq:set_resp_body(Message, RD))
+     end,
+     NewState}.
 
 content_types_provided(RD, State) ->
     {[{"application/json", nop}], RD, State}.
 
-%% This should never get called
-nop(_RD, _State) ->
-    ok.
+nop(RD, State) ->
+    {usage(), RD, State}.
 
 process_post(RD, #state{inputs=Inputs, mrquery=Query}=State) ->
     Me = self(),
     end.
 
 verify_body(Body, State) ->
-    case mochijson2:decode(Body) of
+    case catch mochijson2:decode(Body) of
         {struct, MapReduceDesc} ->
             Inputs = proplists:get_value(?INPUTS_TOKEN, MapReduceDesc),
             Query = proplists:get_value(?QUERY_TOKEN, MapReduceDesc),
                         {ok, ParsedInputs} ->
                             case riak_mapred_json:parse_query(Query) of
                                 {ok, ParsedQuery} ->
-                                    {true, State#state{inputs=ParsedInputs, mrquery=ParsedQuery}};
+                                    {true, [], State#state{inputs=ParsedInputs,
+                                                           mrquery=ParsedQuery}};
                                 error ->
-                                    {false, State}
+                                    {false,
+                                     "An error occurred parsing "
+                                     "the \"query\" field.\n",
+                                     State}
                             end;
                         error ->
-                            {false, State}
+                            {false,
+                             "An error occurred parsing the \"inputs\" field.\n",
+                             State}
                     end;
                 false ->
-                    {false, State}
-            end
+                    {false,
+                     "The post body was missing the "
+                     "\"inputs\" or \"query\" field.\n",
+                     State}
+            end;
+        {'EXIT', Message} ->
+            {false,
+             io_lib:format("The POST body was not valid JSON.~n"
+                           "The error from the parser was:~n~p~n",
+                           [Message]),
+             State};
+        _ ->
+            {false, "The POST body was not a JSON object.\n", State}
     end.
+
+usage() ->
+    "This resource accepts POSTs with bodies containing JSON of the form:\n"
+        "{\n"
+        " \"inputs\":[...list of inputs...],\n"
+        " \"query\":[...list of map/reduce phases...]\n"
+        "}\n".