From 3f94502e2d3aa544f4e32446783aa47b59d28b14 Mon Sep 17 00:00:00 2001 From: Hubert Chathi Date: Thu, 22 Oct 2020 22:08:46 -0400 Subject: allow compressed server responses --- lib/polyjuice/client/endpoint.ex | 32 +++++++++++++++++++++++++++++--- lib/polyjuice/client/sync.ex | 28 ++++++++++++++++++++-------- 2 files changed, 49 insertions(+), 11 deletions(-) (limited to 'lib') diff --git a/lib/polyjuice/client/endpoint.ex b/lib/polyjuice/client/endpoint.ex index 7869ec6..e22f758 100644 --- a/lib/polyjuice/client/endpoint.ex +++ b/lib/polyjuice/client/endpoint.ex @@ -54,11 +54,17 @@ defmodule Polyjuice.Client.Endpoint do def prefix_media_r0, do: "_matrix/media/r0" @doc "Headers for endpoints that accept JSON." - def accept_json, do: [{"Accept", "application/json"}] + def accept_json, + do: [ + {"Accept", "application/json"}, + {"Accept-Encoding", "gzip, deflate"} + ] + @doc "Headers for endpoints that send and accept JSON." def send_json, do: [ {"Accept", "application/json"}, + {"Accept-Encoding", "gzip, deflate"}, {"Content-Type", "application/json"} ] @@ -168,9 +174,10 @@ defmodule Polyjuice.Client.Endpoint do ) :: any def parse_response(%{} = endpoint_args, status_code, headers, body) when is_integer(status_code) and is_list(headers) and is_binary(body) do + {:ok, decoded_body} = content_decode(body, headers) # make sure it's JSON content with "application/json" <- get_header(headers, "content-type"), - {:ok, json} <- Jason.decode(body) do + {:ok, json} <- Jason.decode(decoded_body) do case status_code do 200 -> Polyjuice.Client.Endpoint.BodyParser.parse(endpoint_args, json) @@ -181,7 +188,7 @@ defmodule Polyjuice.Client.Endpoint do else _ -> {:error, if(status_code == 200, do: 500, else: status_code), - %{"errcode" => "CA_UHOREG_POLYJUICE_BAD_RESPONSE", "body" => body}} + %{"errcode" => "CA_UHOREG_POLYJUICE_BAD_RESPONSE", "body" => decoded_body}} end end @@ -202,4 +209,23 @@ defmodule Polyjuice.Client.Endpoint do value end + + def content_decode(encoded, headers) do + case get_header(headers, "content-encoding", "identity") do + "identity" -> + {:ok, encoded} + + "gzip" -> + {:ok, :zlib.gunzip(encoded)} + + "deflate" -> + {:ok, :zlib.uncompress(encoded)} + + "x-gzip" -> + {:ok, :zlib.gunzip(encoded)} + + _ -> + {:error, :unknown_method} + end + end end diff --git a/lib/polyjuice/client/sync.ex b/lib/polyjuice/client/sync.ex index 7a9ebf9..4671260 100644 --- a/lib/polyjuice/client/sync.ex +++ b/lib/polyjuice/client/sync.ex @@ -147,6 +147,7 @@ defmodule Polyjuice.Client.Sync do headers = [ {"Accept", "application/json"}, + {"Accept-Encoding", "gzip, deflate"}, {"Content-Type", "application/json"}, {"Authorization", "Bearer #{access_token}"} ] @@ -163,8 +164,10 @@ defmodule Polyjuice.Client.Sync do with "application/json" <- Polyjuice.Client.Endpoint.get_header(resp_headers, "content-type"), - {:ok, %{} = json_body} <- Jason.decode(body), - filter_id = Map.get(json_body, "filter_id") do + {:ok, decoded_body} <- + Polyjuice.Client.Endpoint.content_decode(body, resp_headers), + {:ok, %{} = json_body} <- Jason.decode(decoded_body), + {:ok, filter_id} = Map.fetch(json_body, "filter_id") do Logger.debug("got filter id #{filter_id}") Polyjuice.Client.Storage.set_filter_id( @@ -187,10 +190,11 @@ defmodule Polyjuice.Client.Sync do 401 -> {:ok, body} = :hackney.body(client_ref) + {:ok, decoded_body} = Polyjuice.Client.Endpoint.content_decode(body, resp_headers) with "application/json" <- Polyjuice.Client.Endpoint.get_header(resp_headers, "content-type"), - {:ok, %{} = json_body} <- Jason.decode(body), + {:ok, %{} = json_body} <- Jason.decode(decoded_body), "M_UNKNOWN_TOKEN" <- Map.get(json_body, "errcode") do :hackney.close(state.conn_ref) @@ -204,14 +208,17 @@ defmodule Polyjuice.Client.Sync do # don't recurse -- we're terminating else _ -> - {:ok, body} = :hackney.body(client_ref) - Logger.warn("Unable to set filter for sync. Ignoring. Got message: #{body}") + Logger.warn( + "Unable to set filter for sync. Ignoring. Got message: #{decoded_body}" + ) + do_sync(%{state | set_filter: nil}) end _ -> {:ok, body} = :hackney.body(client_ref) - Logger.warn("Unable to set filter for sync. Ignoring. Got message: #{body}") + {:ok, decoded_body} = Polyjuice.Client.Endpoint.content_decode(body, resp_headers) + Logger.warn("Unable to set filter for sync. Ignoring. Got message: #{decoded_body}") do_sync(%{state | set_filter: nil}) end @@ -242,6 +249,7 @@ defmodule Polyjuice.Client.Sync do headers = [ {"Accept", "application/json"}, + {"Accept-Encoding", "gzip, deflate"}, {"Authorization", "Bearer #{access_token}"} ] @@ -259,7 +267,9 @@ defmodule Polyjuice.Client.Sync do with "application/json" <- Polyjuice.Client.Endpoint.get_header(resp_headers, "content-type"), - {:ok, json_body} <- Jason.decode(body), + {:ok, decoded_body} <- + Polyjuice.Client.Endpoint.content_decode(body, resp_headers), + {:ok, %{} = json_body} <- Jason.decode(decoded_body), %{"next_batch" => next_batch} <- json_body do if state.backoff, do: Logger.info("Sync resumed") process_body(json_body, state) @@ -282,7 +292,9 @@ defmodule Polyjuice.Client.Sync do with "application/json" <- Polyjuice.Client.Endpoint.get_header(resp_headers, "content-type"), - {:ok, %{} = json_body} <- Jason.decode(body), + {:ok, decoded_body} <- + Polyjuice.Client.Endpoint.content_decode(body, resp_headers), + {:ok, %{} = json_body} <- Jason.decode(decoded_body), "M_UNKNOWN_TOKEN" <- Map.get(json_body, "errcode") do :hackney.close(state.conn_ref) -- cgit v1.2.3