diff --git a/config/dev_sys.config.src b/config/dev_sys.config.src index 19dbb77..b861542 100644 --- a/config/dev_sys.config.src +++ b/config/dev_sys.config.src @@ -23,6 +23,7 @@ {pre_request, nova_request_plugin, #{decode_json_body => true, read_urlencoded_body => true, parse_qs => true}}, + {pre_request, nova_json_schemas, #{render_errors => true}}, {pre_requeset, nova_request_old_plugin, #{}} ]}, {use_persistent_term, true}, diff --git a/priv/schemas/create_item.json b/priv/schemas/create_item.json new file mode 100644 index 0000000..9e59ae2 --- /dev/null +++ b/priv/schemas/create_item.json @@ -0,0 +1,12 @@ +{ + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "quantity": { + "type": "integer" + } + }, + "required": ["name", "quantity"] +} diff --git a/rebar.config b/rebar.config index d24d90d..efd350b 100644 --- a/rebar.config +++ b/rebar.config @@ -13,7 +13,8 @@ ]}. {deps, [ - {nova, ".*", {git, "https://github.com/novaframework/nova.git", {branch, "master"}}} + {nova, ".*", {git, "https://github.com/novaframework/nova.git", {branch, "master"}}}, + {nova_json_schemas, ".*", {git, "https://github.com/novaframework/nova_json_schemas.git", {branch, "master"}}} ]}. diff --git a/rebar.config.script b/rebar.config.script index d80eadf..2159c11 100644 --- a/rebar.config.script +++ b/rebar.config.script @@ -4,17 +4,22 @@ NovaBranch = list_to_binary(os:getenv("NOVA_BRANCH", "master")), NovaRepo = os:getenv("NOVA_REPO", "novaframework/nova"), RepoUrl = "https://github.com/" ++ NovaRepo ++ ".git", -Deps = case NovaBranch of - <<"master">> -> {deps, [ - {nova, ".*", {git, RepoUrl, {branch, "master"}}} - ]}; - <<"refs/tags/", Rest/binary>> -> - {deps, [{nova, ".*", {git, RepoUrl, {tag, binary_to_list(Rest)}}}]}; - NovaBranch -> {deps, [ +NovaDep = case NovaBranch of + <<"master">> -> + {nova, ".*", {git, RepoUrl, {branch, "master"}}}; + <<"refs/tags/", Rest/binary>> -> + {nova, ".*", {git, RepoUrl, {tag, binary_to_list(Rest)}}}; + NovaBranch -> {nova, ".*", {git, RepoUrl, {branch, binary_to_list(NovaBranch)}}} - ]} - end, + end, + +%% Get existing deps from rebar.config (minus nova which we override) +ExistingDeps = case proplists:get_value(deps, Conf0) of + undefined -> []; + Deps0 -> [D || D <- Deps0, element(1, D) =/= nova] + end, + +Deps = {deps, [NovaDep | ExistingDeps]}, Conf1 = proplists:delete(deps, Conf0), [Deps|Conf1]. - diff --git a/src/controllers/nova_request_app_main_controller.erl b/src/controllers/nova_request_app_main_controller.erl index ffe286c..6cc4ce6 100644 --- a/src/controllers/nova_request_app_main_controller.erl +++ b/src/controllers/nova_request_app_main_controller.erl @@ -13,7 +13,8 @@ delete_user/1, fallback/1, return_view_with_ok/1, - return_view_with_view/1 + return_view_with_view/1, + create_item/1 ]). -fallback_controller(nova_request_app_fallback_controller). @@ -68,3 +69,6 @@ return_view_with_ok(_) -> return_view_with_view(_) -> {view, #{message => <<"Hello">>}}. +create_item(#{json := Json}) -> + {json, 201, #{}, Json}. + diff --git a/src/nova_request_app.app.src b/src/nova_request_app.app.src index 8c39300..26756d9 100644 --- a/src/nova_request_app.app.src +++ b/src/nova_request_app.app.src @@ -9,7 +9,8 @@ [ kernel, stdlib, - nova + nova, + nova_json_schemas ]}, {env,[]}, {modules, []}, diff --git a/src/nova_request_app_router.erl b/src/nova_request_app_router.erl index 202f31d..ab4dc39 100644 --- a/src/nova_request_app_router.erl +++ b/src/nova_request_app_router.erl @@ -20,7 +20,9 @@ no_fun() -> {"/internalerror", { nova_request_app_main_controller, internal_server_error}, #{methods => [get]}}, {"/fallback", { nova_request_app_main_controller, fallback}, #{methods => [get]}}, {"/viewok", { nova_request_app_main_controller, return_view_with_ok}, #{methods => [get]}}, - {"/viewview", { nova_request_app_main_controller, return_view_with_view}, #{methods => [get]}} + {"/viewview", { nova_request_app_main_controller, return_view_with_view}, #{methods => [get]}}, + {"/items", {nova_request_app_main_controller, create_item}, + #{methods => [post], extra_state => #{json_schema => "schemas/create_item.json"}}} ] }, #{prefix => "/json_binding", diff --git a/test/nova_request_app_SUITE.erl b/test/nova_request_app_SUITE.erl index cdaa487..c4846bb 100644 --- a/test/nova_request_app_SUITE.erl +++ b/test/nova_request_app_SUITE.erl @@ -124,7 +124,9 @@ all() -> trailingslash, fallback, view_with_ok, - view_with_view]. + view_with_view, + json_schema_valid, + json_schema_invalid]. %%-------------------------------------------------------------------- %% @spec TestCase(Config0) -> %% ok | exit() | {skip,Reason} | {comment,Comment} | @@ -292,9 +294,19 @@ websocket(Path, _Token) -> exit(timeout) end. +json_schema_valid(_) -> + Path = [?BASEPATH, <<"items">>], + Json = #{<<"name">> => <<"widget">>, <<"quantity">> => 5}, + #{status := {201, _}, body := RespBody} = jhn_shttpc:post(Path, encode(Json), opts(json_post)), + #{<<"name">> := <<"widget">>, <<"quantity">> := 5} = decode(RespBody). + +json_schema_invalid(_) -> + Path = [?BASEPATH, <<"items">>], + Json = #{<<"name">> => 123}, + #{status := {400, _}} = jhn_shttpc:post(Path, encode(Json), opts(json_post)). + encode(Json) -> - thoas:encode(Json). + iolist_to_binary(json:encode(Json)). decode(Json) -> - {ok, Result} = thoas:decode(Json), - Result. \ No newline at end of file + json:decode(Json). \ No newline at end of file diff --git a/test/nova_request_app_fun_SUITE.erl b/test/nova_request_app_fun_SUITE.erl index 11e714d..a7b6a7d 100644 --- a/test/nova_request_app_fun_SUITE.erl +++ b/test/nova_request_app_fun_SUITE.erl @@ -299,8 +299,7 @@ websocket(Path, _Token) -> end. encode(Json) -> - thoas:encode(Json). + iolist_to_binary(json:encode(Json)). decode(Json) -> - {ok, Result} = thoas:decode(Json), - Result. \ No newline at end of file + json:decode(Json). \ No newline at end of file