Skip to content

Instantly share code, notes, and snippets.

@Ahed91
Created March 22, 2020 08:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Ahed91/b18342b983a3b05be2fba2c20e4313e9 to your computer and use it in GitHub Desktop.
Save Ahed91/b18342b983a3b05be2fba2c20e4313e9 to your computer and use it in GitHub Desktop.
phoenix protobuf gist
config :mime, :types, %{
"application/x-protobuf" => ["protobuf"]
}
# in plugs folder
defmodule AppWeb.Plugs.DecodeProtobuf do
import Plug.Conn
def init(opts), do: opts
def call(conn, protobuf_module) do
with \
true <- protobuf_content?(conn),
{:ok, binary, conn} <- parse_body(conn, ""),
{:ok, binary, conn} <- decode_body(conn, binary)
do
decoded = Jsoorbp.MyPayload.decode(binary)
conn |> assign(:protobuf, decoded)
else
_ ->
conn
|> send_resp(400, "")
|> halt()
end
end
defp protobuf_content?(conn) do
case get_req_header(conn, "content-type") do
["application/x-protobuf" <> _] ->
true
_ ->
false
end
end
def parse_body(%Plug.Conn{} = conn, acc \\ "") do
case read_body(conn) do
{:ok, body, next_conn} ->
{:ok, acc <> body, next_conn}
{:more, body, next_conn} ->
parse_body(next_conn, acc <> body)
other ->
other
end
end
def decode_body(%Plug.Conn{} = conn, binary) do
case get_req_header(conn, "content-encoding") do
["deflate"] ->
binary_decoded = :zlib.uncompress binary
{:ok, binary_decoded, conn}
_ ->
{:ok, binary, conn}
end
end
end
# this will be generated from the schema above
syntax = "proto2";
package jsoorbp;
message MyPayload {
required string key = 1;
}
def log(conn, params) do
send_resp(conn, 200, "")
end
{:protobuf, "~> 0.7.1"},
# Only for files generated from Google's protos.
# Can be ignored if you don't use Google's protos.
# Or you can generate the code by yourself.
{:google_protos, "~> 0.1"},
pipeline :protobuf do
plug :accepts, ["protobuf"]
plug JsoorWeb.Plugs.DecodeProtobuf
end
scope "/", JsoorWeb do
pipe_through [:protobuf]
post "/log", HomeController, :log
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment