Scott Hiett commited on
Commit
0b53aa4
·
1 Parent(s): 89df778

Pipeline support

Browse files
lib/srh/http/base_router.ex CHANGED
@@ -12,33 +12,55 @@ defmodule Srh.Http.BaseRouter do
12
  end
13
 
14
  post "/" do
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  case conn
16
  |> get_req_header("authorization")
17
  |> RequestValidator.validate_bearer_header()
18
  do
19
  {:ok, token} ->
20
- CommandHandler.handle_command(conn, token)
21
  {:error, _} ->
22
  {:malformed_data, "Missing/Invalid authorization header"}
23
  end
24
- |> handle_response(conn)
25
- end
26
-
27
- match _ do
28
- send_resp(conn, 404, "Endpoint not found")
29
  end
30
 
31
  defp handle_response(response, conn) do
32
- %{code: code, message: message} =
33
  case response do
34
- {:ok, data} -> %{code: 200, message: Jason.encode!(data)}
35
- {:not_found, message} -> %{code: 404, message: message}
36
- {:malformed_data, message} -> %{code: 400, message: message}
37
- {:not_authorized, message} -> %{code: 401, message: message}
38
- {:server_error, _} -> %{code: 500, message: "An error occurred internally"}
 
 
 
39
  end
40
 
41
- conn
 
 
 
 
 
 
42
  |> send_resp(code, message)
43
  end
44
  end
 
12
  end
13
 
14
  post "/" do
15
+ conn
16
+ |> handle_extract_auth(&(CommandHandler.handle_command(conn, &1)))
17
+ |> handle_response(conn)
18
+ end
19
+
20
+ post "/pipeline" do
21
+ conn
22
+ |> handle_extract_auth(
23
+ &(CommandHandler.handle_command_array(conn, &1))
24
+ )
25
+ |> handle_response(conn)
26
+ end
27
+
28
+ match _ do
29
+ send_resp(conn, 404, "Endpoint not found")
30
+ end
31
+
32
+ defp handle_extract_auth(conn, success_lambda) do
33
  case conn
34
  |> get_req_header("authorization")
35
  |> RequestValidator.validate_bearer_header()
36
  do
37
  {:ok, token} ->
38
+ success_lambda.(token)
39
  {:error, _} ->
40
  {:malformed_data, "Missing/Invalid authorization header"}
41
  end
 
 
 
 
 
42
  end
43
 
44
  defp handle_response(response, conn) do
45
+ %{code: code, message: message, json: json} =
46
  case response do
47
+ {:ok, data} -> %{code: 200, message: Jason.encode!(data), json: true}
48
+ {:not_found, message} -> %{code: 404, message: message, json: false}
49
+ {:malformed_data, message} -> %{code: 400, message: message, json: false}
50
+ {:not_authorized, message} -> %{code: 401, message: message, json: false}
51
+ {:server_error, _} -> %{code: 500, message: "An error occurred internally", json: false}
52
+ other ->
53
+ IO.inspect(other)
54
+ %{code: 500, message: "An error occurred internally", json: false}
55
  end
56
 
57
+ case json do
58
+ true ->
59
+ conn
60
+ |> put_resp_header("content-type", "application/json")
61
+ false ->
62
+ conn
63
+ end
64
  |> send_resp(code, message)
65
  end
66
  end
lib/srh/http/command_handler.ex CHANGED
@@ -14,6 +14,16 @@ defmodule Srh.Http.CommandHandler do
14
  end
15
  end
16
 
 
 
 
 
 
 
 
 
 
 
17
  defp do_handle_command(command_array, token) do
18
  case TokenResolver.resolve(token) do
19
  {:ok, connection_info} ->
@@ -22,6 +32,31 @@ defmodule Srh.Http.CommandHandler do
22
  end
23
  end
24
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  defp dispatch_command(command_array, %{"srh_id" => srh_id, "max_connections" => max_connections} = connection_info)
26
  when is_number(max_connections) do
27
  case GenRegistry.lookup_or_start(Client, srh_id, [max_connections, connection_info]) do
 
14
  end
15
  end
16
 
17
+ def handle_command_array(conn, token) do
18
+ case RequestValidator.validate_pipeline_redis_body(conn.body_params) do
19
+ {:ok, array_of_command_arrays} ->
20
+ IO.inspect(array_of_command_arrays)
21
+ do_handle_command_array(array_of_command_arrays, token)
22
+ {:error, error_message} ->
23
+ {:malformed_data, error_message}
24
+ end
25
+ end
26
+
27
  defp do_handle_command(command_array, token) do
28
  case TokenResolver.resolve(token) do
29
  {:ok, connection_info} ->
 
32
  end
33
  end
34
 
35
+ defp do_handle_command_array(array_of_command_arrays, token) do
36
+ case TokenResolver.resolve(token) do
37
+ {:ok, connection_info} ->
38
+ dispatch_command_array(array_of_command_arrays, connection_info)
39
+ {:error, msg} -> {:not_authorized, msg}
40
+ end
41
+ end
42
+
43
+ defp dispatch_command_array([current | rest], connection_info, responses \\ []) do
44
+ updated_responses = case dispatch_command(current, connection_info) do
45
+ {:ok, result_map} ->
46
+ [result_map | responses]
47
+ {:malformed_data, result_json} ->
48
+ # TODO: change up the chain to json this at the last moment, so this isn't here
49
+ [Jason.decode!(result_json) | responses]
50
+ end
51
+
52
+ dispatch_command_array(rest, connection_info, updated_responses)
53
+ end
54
+
55
+ defp dispatch_command_array([], connection_info, responses) do
56
+ # The responses will be in reverse order, as we're adding them to the list with the faster method of putting them at head.
57
+ {:ok, Enum.reverse(responses)}
58
+ end
59
+
60
  defp dispatch_command(command_array, %{"srh_id" => srh_id, "max_connections" => max_connections} = connection_info)
61
  when is_number(max_connections) do
62
  case GenRegistry.lookup_or_start(Client, srh_id, [max_connections, connection_info]) do
lib/srh/http/request_validator.ex CHANGED
@@ -4,6 +4,24 @@ defmodule Srh.Http.RequestValidator do
4
  def validate_redis_body(payload),
5
  do: {:error, "Invalid command array. Expected a string array at root of the command and its arguments."}
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  def validate_bearer_header(header_value_array) when is_list(header_value_array) do
8
  do_validate_bearer_header(header_value_array)
9
  end
@@ -18,7 +36,7 @@ defmodule Srh.Http.RequestValidator do
18
  do_validate_bearer_header(rest)
19
  end
20
  end
21
-
22
  # no items left
23
  defp do_validate_bearer_header([]), do: {:error, :not_found}
24
  end
 
4
  def validate_redis_body(payload),
5
  do: {:error, "Invalid command array. Expected a string array at root of the command and its arguments."}
6
 
7
+ def validate_pipeline_redis_body(%{"_json" => array_of_command_arrays}) when is_list(array_of_command_arrays) do
8
+ do_validate_pipeline_redis_body(array_of_command_arrays, array_of_command_arrays)
9
+ end
10
+
11
+ # any amount of items left
12
+ defp do_validate_pipeline_redis_body([first_item | rest], original) do
13
+ case do_validate_pipeline_item(first_item) do
14
+ :ok -> do_validate_pipeline_redis_body(rest, original)
15
+ :error -> {:error, "Invalid command array. Expected an array of string arrays at root."}
16
+ end
17
+ end
18
+
19
+ defp do_validate_pipeline_redis_body([], original), do: {:ok, original}
20
+
21
+ defp do_validate_pipeline_item(item) when is_list(item), do: :ok
22
+
23
+ defp do_validate_pipeline_item(item), do: :error
24
+
25
  def validate_bearer_header(header_value_array) when is_list(header_value_array) do
26
  do_validate_bearer_header(header_value_array)
27
  end
 
36
  do_validate_bearer_header(rest)
37
  end
38
  end
39
+
40
  # no items left
41
  defp do_validate_bearer_header([]), do: {:error, :not_found}
42
  end