Spaces:
Sleeping
Sleeping
File size: 3,061 Bytes
2e92879 a8d7371 2e92879 b2ff4b5 21d5884 b2ff4b5 2e92879 a8d7371 0b53aa4 a8d7371 0b53aa4 abcde98 a8d7371 abcde98 0b53aa4 f085bb2 0b53aa4 a8d7371 8f1b0f2 a8d7371 0b53aa4 2e92879 b2ff4b5 2e92879 0b53aa4 b2ff4b5 2e92879 8f1b0f2 a8d7371 bb41a4c a8d7371 bb41a4c a8d7371 2e92879 0f49779 2e92879 b2ff4b5 0f49779 b2ff4b5 0f49779 b2ff4b5 0f49779 b2ff4b5 abcde98 0f49779 abcde98 b2ff4b5 0f49779 b2ff4b5 bb41a4c 0f49779 b2ff4b5 76486d3 ba82689 2e92879 0f49779 b2ff4b5 5ce1d4c 0f49779 5ce1d4c 2e92879 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
defmodule Srh.Http.BaseRouter do
use Plug.Router
alias Srh.Http.RequestValidator
alias Srh.Http.CommandHandler
alias Srh.Http.ResultEncoder
plug(:match)
plug(Srh.Http.ContentTypeCheckPlug)
plug(Plug.Parsers, parsers: [:json], pass: ["application/json"], json_decoder: Jason)
plug(:dispatch)
get "/" do
handle_response({:ok, "Welcome to Serverless Redis HTTP!"}, conn)
end
post "/" do
do_command_request(conn, &CommandHandler.handle_command(&1, &2))
end
post "/pipeline" do
do_command_request(conn, &CommandHandler.handle_command_array(&1, &2))
end
post "/multi-exec" do
do_command_request(conn, &CommandHandler.handle_command_transaction_array(&1, &2))
end
match _ do
handle_response(
{:not_found, "SRH: Endpoint not found. SRH might not support this feature yet."},
conn
)
end
defp do_command_request(conn, success_lambda) do
encoding_enabled = handle_extract_encoding?(conn)
conn
|> handle_extract_auth(&success_lambda.(conn, &1))
|> handle_encoding_step(encoding_enabled)
|> handle_response(conn)
end
defp handle_extract_auth(conn, success_lambda) do
case conn
|> get_req_header("authorization")
|> RequestValidator.validate_bearer_header() do
{:ok, token} ->
success_lambda.(token)
{:error, _} ->
{:malformed_data, "Missing/Invalid authorization header"}
end
end
defp handle_extract_encoding?(conn) do
case conn
|> get_req_header("upstash-encoding")
|> RequestValidator.validate_encoding_header() do
{:ok, _encoding_enabled} -> true
# it's not required to be present
{:error, _} -> false
end
end
defp handle_encoding_step(response, encoding_enabled) do
case encoding_enabled do
true ->
# We need to use the encoder to
ResultEncoder.encode_response(response)
false ->
response
end
end
defp handle_response(response, conn) do
# Errors are strings, and data just means the content is directly encoded with Jason.encode!
# {404, {:error, "Message"}}
# {200, {:data, ""}}
{code, resp_data} =
case response do
{:ok, data} ->
{200, {:data, data}}
{:not_found, message} ->
{404, {:error, message}}
{:malformed_data, message} ->
{400, {:error, message}}
{:redis_error, data} ->
{400, {:data, data}}
{:not_authorized, message} ->
{401, {:error, message}}
{:connection_error, message} ->
{500, {:error, message}}
_ ->
{500, {:error, "SRH: An error occurred internally"}}
end
conn
|> put_resp_header("content-type", "application/json")
|> send_resp(code, create_response_body(resp_data))
end
# :data just directly encodes
defp create_response_body({:data, data}), do: Jason.encode!(data)
# :error wraps the message in an error object
defp create_response_body({:error, error}), do: Jason.encode!(%{error: error})
end
|