1
votes

I am trying to catch invalid json while parsing it with jiffy in cowboy websocket handler. If the json is valid/invalid I want to forward an appropriate message to websocket_info which will reply to the client. Here is my code.

websocket_handle({text, Msg}, Req, State) ->

lager:info("Got message ~p",[Msg]),

try  jiffy:decode(Msg) of 

    {[{A,B}]}->{{[{A,B}]},Req,State};

    _->{{invalid,Msg},Req,State}

catch
    _:_->
        {{invalid,Msg},Req,State}
end;

websocket_handle(_Data, Req, State) ->

                 {ok, Req, State}.

websocket_info({[{A,B}]},Req,State) ->

               {reply,{text,jiffy:encode({registered,B})},Req,State};

websocket_info({invalid,Msg},Req,State)->

              {reply,{text,jiffy:encode({error,<<"invalid json">>})},Req,State};

This causes a runtime exception.

12:07:48.406 [error] Ranch listener http had connection process <0.523.0> exit with reason: {{try_clause,{{[{<<"register">>,<<"my-channel">>}]},{http_req,#Port<0.1337>,ranch_tcp,keepalive,<0.523.0>,<<"GET">>,'HTTP/1.1',{{127,0,0,1},34869},<<"127.0.0.1">>,undefined,3000,<<"/websocket/">>,undefined,<<>>,undefined,[],[{<<"upgrade">>,<<"websocket">>},{<<"connection">>,<<"Upgrade">>},{<<"host">>,<<"127.0.0.1:3000">>},{<<"origin">>,<<"http://localhost:4000">>},{<<"pragma">>,<<"no-cache">>},{<<"cache-control">>,<<"no-cache">>},{<<"sec-websocket-key">>,<<"ueSRxsIc4wM7KdGnyhJOhw==">>},{<<"sec-websocket-version">>,<<"13">>},{<<"sec-websocket-extensions">>,<<"x-webkit-deflate-frame">>},{<<"user-agent">>,<<"Mozilla/5.0 (X11; Linux i686 (x86_64)) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.114 Safari/537.36">>}],[{<<"sec-websocket-extensions">>,[{<<"x-webkit-deflate-frame">>,[]}]},{<<"upgrade">>,[<<"websocket">>]},{<<"connection">>,[<<"upgrade">>]}],undefined,[{websocket_compress,false},{websocket_version,13}],waiting,undefined,<<>>,false,done,[],<<>>,undefined},undefined_state}},[{cowboy_websocket,handler_call,7,[{file,"src/cowboy_websocket.erl"},{line,598}]},{cowboy_protocol,execute,4,[{file,"src/cowboy_protocol.erl"},{line,529}]}]}

So how can I do this?

1

1 Answers

1
votes

Reply should be returned from websocket_handle:

websocket_handle({text, Msg}, Req, State) ->
    lager:info("Got message ~p", [Msg]),
    try jiffy:decode(Msg) of 
        {[{A, B}]}->
            {reply, {text, jiffy:encode({[{registered,B}]})}, Req, State};
        _ -> 
            {reply, {text, jiffy:encode({[{error,<<"invalid json">>}]})}, Req, State} 
    catch
        _:_ ->
            {reply, {text, jiffy:encode({[{error,<<"invalid json">>}]})}, Req, State};
    end;

websocket_handle(_Data, Req, State) ->
    {ok, Req, State}.

websocket_info(_Info, Req, State) ->
    {ok, Req, State}.