Scott Hiett commited on
Commit
e8a4156
·
unverified ·
2 Parent(s): 2dbe17d ba82689

Merge pull request #15 from hiett/14-error-overhaul

Browse files
lib/srh/http/base_router.ex CHANGED
@@ -5,6 +5,7 @@ defmodule Srh.Http.BaseRouter do
5
  alias Srh.Http.ResultEncoder
6
 
7
  plug(:match)
 
8
  plug(Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Jason)
9
  plug(:dispatch)
10
 
@@ -25,7 +26,7 @@ defmodule Srh.Http.BaseRouter do
25
  end
26
 
27
  match _ do
28
- send_resp(conn, 404, "Endpoint not found")
29
  end
30
 
31
  defp do_command_request(conn, success_lambda) do
@@ -71,41 +72,42 @@ defmodule Srh.Http.BaseRouter do
71
  end
72
 
73
  defp handle_response(response, conn) do
74
- %{code: code, message: message, json: json} =
 
 
 
 
75
  case response do
76
  {:ok, data} ->
77
- %{code: 200, message: Jason.encode!(data), json: true}
78
 
79
  {:not_found, message} ->
80
- %{code: 404, message: message, json: false}
81
 
82
  {:malformed_data, message} ->
83
- %{code: 400, message: message, json: false}
84
 
85
  {:redis_error, data} ->
86
- %{code: 400, message: Jason.encode!(data), json: true}
87
 
88
  {:not_authorized, message} ->
89
- %{code: 401, message: message, json: false}
90
 
91
  {: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}
96
 
97
  _ ->
98
- %{code: 500, message: "An error occurred internally", json: false}
99
  end
100
 
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)
110
  end
 
 
 
 
 
 
111
  end
 
5
  alias Srh.Http.ResultEncoder
6
 
7
  plug(:match)
8
+ plug(Srh.Http.ContentTypeCheckPlug)
9
  plug(Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Jason)
10
  plug(:dispatch)
11
 
 
26
  end
27
 
28
  match _ do
29
+ handle_response({:not_found, "SRH: Endpoint not found. SRH might not support this feature yet."}, conn)
30
  end
31
 
32
  defp do_command_request(conn, success_lambda) do
 
72
  end
73
 
74
  defp handle_response(response, conn) do
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} =
80
  case response do
81
  {:ok, data} ->
82
+ {200, {:data, data}}
83
 
84
  {:not_found, message} ->
85
+ {404, {:error, message}}
86
 
87
  {:malformed_data, message} ->
88
+ {400, {:error, message}}
89
 
90
  {:redis_error, data} ->
91
+ {400, {:data, data}}
92
 
93
  {:not_authorized, message} ->
94
+ {401, {:error, message}}
95
 
96
  {:connection_error, message} ->
97
+ {500, {:error, message}}
 
 
 
98
 
99
  _ ->
100
+ {500, {:error, "SRH: An error occurred internally"}}
101
  end
102
 
103
+ conn
104
+ |> put_resp_header("content-type", "application/json")
105
+ |> send_resp(code, create_response_body(resp_data))
 
 
 
 
 
 
106
  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})
113
  end
lib/srh/http/content_type_check_plug.ex ADDED
@@ -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