derpycoder

derpycoder

How to get Partial Content(206) by, passing range header, using Req?

Hello Guys,

I’m building tools using Elixir, Phoenix & LiveView to learn and perhaps have a portfolio.

There’s a LinkedIn post inspector, that shows how a blog post will show up on LinkedIn.

It also shows redirects trail:

I recreated the same using Req library, by making a custom step.


FetchExtraMetadata

defmodule DerpyTools.FetchExtraMetadata do
  @moduledoc """
  ## Request Options
    * `:fetch_redirects` - if `true`, gets the metadata related to redirects, like final url, redirects, redirection_trail. Defaults to `false`.
  """
  def attach(%Req.Request{} = request, options \\ []) do
    request
    |> Req.Request.register_options([:fetch_redirects, :print_headers])
    |> Req.Request.merge_options(options)
    |> Req.Request.prepend_response_steps(fetch_redirects: &fetch_redirects/1)
  end

  defp fetch_redirects({%{options: %{fetch_redirects: true}} = request, response}) do
    private =
      request.private
      |> Map.update(
        :trail,
        [{response.status, URI.to_string(request.url)}],
        fn val ->
          [{response.status, URI.to_string(request.url)} | val]
        end
      )

    request = %{request | private: private}

    private =
      response.private
      |> Map.put_new(:redirects, %{
        uri: request.url,
        url: URI.to_string(request.url |> Map.replace(:query, nil)),
        count: Map.get(request.private, :req_redirect_count, 0),
        trail: Map.get(request.private, :trail, [])
      })

    response = %{response | private: private}

    {request, response}
  end

  defp fetch_redirects({%{options: _} = request, response}), do: {request, response}
end

Here’s how I use it:

res =
      Req.new()
      |> FetchExtraMetadata.attach(fetch_redirects: true)
      |> Req.get!(url: url)

IO.inspect(res.private.redirects, label: "Redirect Trail")


Notice, how I receive 200 instead of 206 shown on LinkedIn’s post inspector.

The HTTP Status Code 206 means that the server is delivering only part of the resource requested by the client due to a range header sent by the client.

I tried sending range header via Req, but I still receive 200 on some links, and for some I get errors, but no 206!

What is the valid value for range header, and how to send it using Req?

I tried: Req.new(range: "bytes=100-200"), but it errors out on certain routes.

[error] GenServer #PID<0.2572.0> terminating
** (stop) :data_error
    :zlib.inflate_nif(#Reference<0.3960474752.3632136194.182349>, 8192, 16384, 0)
    :zlib.dequeue_all_chunks_1/3
    :zlib.inflate/3
    :zlib.gunzip/1
    (elixir 1.15.4) lib/enum.ex:2510: Enum."-reduce/3-lists^foldl/2-0-"/3
    (elixir 1.15.4) lib/map.ex:916: Map.update!/3
    (req 0.3.11) lib/req/steps.ex:860: Req.Steps.decompress_body/1
    (req 0.3.11) lib/req/request.ex:755: anonymous fn/2 in Req.Request.run_response/2
    (elixir 1.15.4) lib/enum.ex:4830: Enumerable.List.reduce/3
    (elixir 1.15.4) lib/enum.ex:2564: Enum.reduce_while/3
    (req 0.3.11) lib/req/request.ex:683: Req.Request.run/1
    (req 0.3.11) lib/req/steps.ex:1160: Req.Steps.follow_redirects/1
    (req 0.3.11) lib/req/request.ex:755: anonymous fn/2 in Req.Request.run_response/2
    (elixir 1.15.4) lib/enum.ex:4830: Enumerable.List.reduce/3
    (elixir 1.15.4) lib/enum.ex:2564: Enum.reduce_while/3
    (req 0.3.11) lib/req/request.ex:683: Req.Request.run/1
    (req 0.3.11) lib/req/steps.ex:1160: Req.Steps.follow_redirects/1
    (req 0.3.11) lib/req/request.ex:755: anonymous fn/2 in Req.Request.run_response/2
    (elixir 1.15.4) lib/enum.ex:4830: Enumerable.List.reduce/3
    (elixir 1.15.4) lib/enum.ex:2564: Enum.reduce_while/3
Last message: {:analyze_metadata, "http://derpytools.com/hostsfile-mkcert-caddy-achieving-development-production-parity-has-never-been-easier"}

P.S. My project is open source, See: Derpy Tools.
Files to look for:
metadata_analyzer_live.ex
fetch_extra_metadata.ex

Marked As Solved

wojtekmach

wojtekmach

Hex Core Team

you should be able to avoid this error by setting compressed: false. Req 0.3 by default sets accept-encoding: gzip, deflate and then server should give response with content-encoding and then we automatically decompress it. compressed: false will not set accept-encoding. deflate support was broken and will be removed. if you somehow got deflate response that would be the culprit.

Where Next?

Popular in Questions Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

Other popular topics Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 44778 311
New

We're in Beta

About us Mission Statement