Skip to content

Commit e8a4156

Browse files
authored
Merge pull request #15 from hiett/14-error-overhaul
Standardise errors
2 parents 2dbe17d + ba82689 commit e8a4156

File tree

2 files changed

+65
-21
lines changed

2 files changed

+65
-21
lines changed

lib/srh/http/base_router.ex

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ defmodule Srh.Http.BaseRouter do
55
alias Srh.Http.ResultEncoder
66

77
plug(:match)
8+
plug(Srh.Http.ContentTypeCheckPlug)
89
plug(Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Jason)
910
plug(:dispatch)
1011

@@ -25,7 +26,7 @@ defmodule Srh.Http.BaseRouter do
2526
end
2627

2728
match _ do
28-
send_resp(conn, 404, "Endpoint not found")
29+
handle_response({:not_found, "SRH: Endpoint not found. SRH might not support this feature yet."}, conn)
2930
end
3031

3132
defp do_command_request(conn, success_lambda) do
@@ -71,41 +72,42 @@ defmodule Srh.Http.BaseRouter do
7172
end
7273

7374
defp handle_response(response, conn) do
74-
%{code: code, message: message, json: json} =
75+
# Errors are strings, and data just means the content is directly encoded with Jason.encode!
76+
# {404, {:error, "Message"}}
77+
# {200, {:data, ""}}
78+
79+
{code, resp_data} =
7580
case response do
7681
{:ok, data} ->
77-
%{code: 200, message: Jason.encode!(data), json: true}
82+
{200, {:data, data}}
7883

7984
{:not_found, message} ->
80-
%{code: 404, message: message, json: false}
85+
{404, {:error, message}}
8186

8287
{:malformed_data, message} ->
83-
%{code: 400, message: message, json: false}
88+
{400, {:error, message}}
8489

8590
{:redis_error, data} ->
86-
%{code: 400, message: Jason.encode!(data), json: true}
91+
{400, {:data, data}}
8792

8893
{:not_authorized, message} ->
89-
%{code: 401, message: message, json: false}
94+
{401, {:error, message}}
9095

9196
{:connection_error, message} ->
92-
%{code: 500, message: Jason.encode!(%{error: message}), json: true}
93-
94-
{:server_error, _} ->
95-
%{code: 500, message: "An error occurred internally", json: false}
97+
{500, {:error, message}}
9698

9799
_ ->
98-
%{code: 500, message: "An error occurred internally", json: false}
100+
{500, {:error, "SRH: An error occurred internally"}}
99101
end
100102

101-
case json do
102-
true ->
103-
conn
104-
|> put_resp_header("content-type", "application/json")
105-
106-
false ->
107-
conn
108-
end
109-
|> send_resp(code, message)
103+
conn
104+
|> put_resp_header("content-type", "application/json")
105+
|> send_resp(code, create_response_body(resp_data))
110106
end
107+
108+
# :data just directly encodes
109+
defp create_response_body({:data, data}), do: Jason.encode!(data)
110+
111+
# :error wraps the message in an error object
112+
defp create_response_body({:error, error}), do: Jason.encode!(%{error: error})
111113
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
defmodule Srh.Http.ContentTypeCheckPlug do
2+
import Plug.Conn
3+
4+
def init(opts), do: opts
5+
6+
def call(conn, _opts) do
7+
# Only parse for POST, PUT, PATCH, and DELETE requests, which is what Plug.Parsers does
8+
case conn.method do
9+
"POST" ->
10+
check_content_type(conn)
11+
12+
"PUT" ->
13+
check_content_type(conn)
14+
15+
"PATCH" ->
16+
check_content_type(conn)
17+
18+
"DELETE" ->
19+
check_content_type(conn)
20+
21+
# All other methods can proceed
22+
_ ->
23+
conn
24+
end
25+
end
26+
27+
defp check_content_type(conn) do
28+
case get_req_header(conn, "content-type") do
29+
["application/json"] ->
30+
# Proceed, this is the valid content type for SRH
31+
conn
32+
33+
# Either missing, or a type that we don't support
34+
_ ->
35+
# Return a custom error, ensuring the same format as the other errors
36+
conn
37+
|> put_resp_content_type("application/json")
38+
|> send_resp(400, Jason.encode!(%{error: "Invalid content type. Expected application/json."}))
39+
|> halt()
40+
end
41+
end
42+
end

0 commit comments

Comments
 (0)