diff --git a/apps/iot/src/http/http_protocol.erl b/apps/iot/src/http/http_protocol.erl deleted file mode 100644 index fb3ed4b..0000000 --- a/apps/iot/src/http/http_protocol.erl +++ /dev/null @@ -1,82 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @author licheng5 -%%% @copyright (C) 2020, -%%% @doc -%%% -%%% @end -%%% Created : 26. 4月 2020 3:36 下午 -%%%------------------------------------------------------------------- --module(http_protocol). --author("licheng5"). - -%% API --export([init/2]). - -init(Req0, Opts = [Mod|_]) -> - Method = binary_to_list(cowboy_req:method(Req0)), - Path = binary_to_list(cowboy_req:path(Req0)), - GetParams0 = cowboy_req:parse_qs(Req0), - GetParams = maps:from_list(GetParams0), - {ok, PostParams, Req1} = parse_body(Req0), - - try Mod:handle_request(Method, Path, GetParams, PostParams) of - {ok, StatusCode, Resp} -> - lager:debug("[http_protocol] request path: ~p, get_params: ~p, post_params: ~p, response: ~ts", - [Path, GetParams, PostParams, Resp]), - AcceptEncoding = cowboy_req:header(<<"accept-encoding">>, Req1, <<>>), - Req2 = case iolist_size(Resp) >= 1024 andalso supported_gzip(AcceptEncoding) of - true -> - Resp1 = zlib:gzip(Resp), - cowboy_req:reply(StatusCode, #{ - <<"Content-Type">> => <<"application/json;charset=utf-8">>, - <<"Content-Encoding">> => <<"gzip">> - }, Resp1, Req1); - false -> - cowboy_req:reply(StatusCode, #{ - <<"Content-Type">> => <<"application/json;charset=utf-8">> - }, Resp, Req1) - end, - {ok, Req2, Opts} - catch - throw:Error -> - ErrResp = iot_util:json_error(-1, Error), - Req2 = cowboy_req:reply(404, #{ - <<"Content-Type">> => <<"application/json;charset=utf-8">> - }, ErrResp, Req1), - {ok, Req2, Opts}; - _:Error:Stack -> - lager:warning("[http_handler] get error: ~p, stack: ~p", [Error, Stack]), - Req2 = cowboy_req:reply(500, #{ - <<"Content-Type">> => <<"text/html;charset=utf-8">> - }, <<"Internal Server Error">>, Req1), - {ok, Req2, Opts} - end. - -%% 判断是否支持gzip -supported_gzip(AcceptEncoding) when is_binary(AcceptEncoding) -> - binary:match(AcceptEncoding, <<"gzip">>) =/= nomatch. - -parse_body(Req0) -> - ContentType = cowboy_req:header(<<"content-type">>, Req0), - case ContentType of - <<"application/json", _/binary>> -> - {ok, Body, Req1} = read_body(Req0), - {ok, catch jiffy:decode(Body, [return_maps]), Req1}; - <<"application/x-www-form-urlencoded">> -> - {ok, PostParams0, Req1} = cowboy_req:read_urlencoded_body(Req0), - PostParams = maps:from_list(PostParams0), - {ok, PostParams, Req1}; - _ -> - {ok, #{}, Req0} - end. - -%% 读取请求体 -read_body(Req) -> - read_body(Req, <<>>). -read_body(Req, AccData) -> - case cowboy_req:read_body(Req) of - {ok, Data, Req1} -> - {ok, <>, Req1}; - {more, Data, Req1} -> - read_body(Req1, <>) - end. \ No newline at end of file diff --git a/apps/iot/src/http/http_server.erl b/apps/iot/src/http/http_server.erl index 00808bd..f45413e 100644 --- a/apps/iot/src/http/http_server.erl +++ b/apps/iot/src/http/http_server.erl @@ -11,6 +11,7 @@ %% API -export([start/0]). +-export([init/2]). %% 启动http服务 start() -> @@ -22,8 +23,8 @@ start() -> Dispatcher = cowboy_router:compile([ {'_', [ - {"/host/[...]", http_protocol, [host_handler]}, - {"/device/[...]", http_protocol, [device_handler]} + {"/host/[...]", ?MODULE, [host_handler]}, + {"/device/[...]", ?MODULE, [device_handler]} ]} ]), @@ -36,4 +37,73 @@ start() -> {ok, Pid} = cowboy:start_clear(http_listener, TransOpts, #{env => #{dispatch => Dispatcher}}), - lager:debug("[iot_app] the http server start at: ~p, pid is: ~p", [Port, Pid]). \ No newline at end of file + lager:debug("[iot_app] the http server start at: ~p, pid is: ~p", [Port, Pid]). + +init(Req0, Opts = [Mod|_]) -> + Method = binary_to_list(cowboy_req:method(Req0)), + Path = binary_to_list(cowboy_req:path(Req0)), + GetParams0 = cowboy_req:parse_qs(Req0), + GetParams = maps:from_list(GetParams0), + {ok, PostParams, Req1} = parse_body(Req0), + + try Mod:handle_request(Method, Path, GetParams, PostParams) of + {ok, StatusCode, Resp} -> + lager:debug("[http_protocol] request path: ~p, get_params: ~p, post_params: ~p, response: ~ts", + [Path, GetParams, PostParams, Resp]), + AcceptEncoding = cowboy_req:header(<<"accept-encoding">>, Req1, <<>>), + Req2 = case iolist_size(Resp) >= 1024 andalso supported_gzip(AcceptEncoding) of + true -> + Resp1 = zlib:gzip(Resp), + cowboy_req:reply(StatusCode, #{ + <<"Content-Type">> => <<"application/json;charset=utf-8">>, + <<"Content-Encoding">> => <<"gzip">> + }, Resp1, Req1); + false -> + cowboy_req:reply(StatusCode, #{ + <<"Content-Type">> => <<"application/json;charset=utf-8">> + }, Resp, Req1) + end, + {ok, Req2, Opts} + catch + throw:Error -> + ErrResp = iot_util:json_error(-1, Error), + Req2 = cowboy_req:reply(404, #{ + <<"Content-Type">> => <<"application/json;charset=utf-8">> + }, ErrResp, Req1), + {ok, Req2, Opts}; + _:Error:Stack -> + lager:warning("[http_handler] get error: ~p, stack: ~p", [Error, Stack]), + Req2 = cowboy_req:reply(500, #{ + <<"Content-Type">> => <<"text/html;charset=utf-8">> + }, <<"Internal Server Error">>, Req1), + {ok, Req2, Opts} + end. + +%% 判断是否支持gzip +supported_gzip(AcceptEncoding) when is_binary(AcceptEncoding) -> + binary:match(AcceptEncoding, <<"gzip">>) =/= nomatch. + +parse_body(Req0) -> + ContentType = cowboy_req:header(<<"content-type">>, Req0), + case ContentType of + <<"application/json", _/binary>> -> + {ok, Body, Req1} = read_body(Req0), + {ok, catch jiffy:decode(Body, [return_maps]), Req1}; + <<"application/x-www-form-urlencoded">> -> + {ok, PostParams0, Req1} = cowboy_req:read_urlencoded_body(Req0), + PostParams = maps:from_list(PostParams0), + {ok, PostParams, Req1}; + _ -> + {ok, #{}, Req0} + end. + +%% 读取请求体 +read_body(Req) -> + read_body(Req, <<>>). +read_body(Req, AccData) -> + case cowboy_req:read_body(Req) of + {ok, Data, Req1} -> + {ok, <>, Req1}; + {more, Data, Req1} -> + read_body(Req1, <>) + end. \ No newline at end of file