# Question about HTTP::Client

**URL:** <https://forum.crystal-lang.org/t/question-about-http-client/4153>\
**Category:** Help & Support\
**Created:** [December 16, 2021, 11:31pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153 "2021-12-16T23:31:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [December 16, 2021, 11:31pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/1 "2021-12-16T23:31:31Z")

</div>

Hello, because actually now crystal is in 1.2.2 version, I have a question. In past, HTTP::Client didn’t have the fonctionnality to do automatically redirections. And actually ?

Because I would like to download a file with crystal and as well write a nice output when I’m downloading a file. For example showing percentage, amount of received data, progress bar …etc

---

<div class="post-metadata">

**Author:** ![oprypin](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/oprypin/32/859_2.png) [@oprypin](https://forum.crystal-lang.org/u/oprypin)\
**Post date:** [December 17, 2021, 1:47pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/2 "2021-12-17T13:47:47Z")

</div>

I also don’t know if my information is up to date, but I’m pretty sure that HTTP::Client from standard library will _not_ handle redirects automatically.

For a featureful HTTP client (that handles redirects) I recommend this one instead:

> **[GitHub - icyleaf/halite: 💎HTTP Requests Client with a chainable REST API,...](https://github.com/icyleaf/halite)**
>
> 💎HTTP Requests Client with a chainable REST API, built-in sessions and middlewares. - GitHub - icyleaf/halite: 💎HTTP Requests Client with a chainable REST API, built-in sessions and middlewares.

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [December 9, 2022, 3:42pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/3 "2022-12-09T15:42:52Z")

</div>

Sorry to come back again to my old post, but any news about the redirects solutions for crystal ? I saw HTTP:Client didn’t implement that actually. Is halite the only available library actually for that ?

If it’s not, just one question, how can I get the current network speed of download, amount of data transfered …etc ?

---

<div class="post-metadata">

**Author:** ![chillfox](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/chillfox/32/1870_2.png) [@chillfox](https://forum.crystal-lang.org/u/chillfox)\
**Post date:** [December 12, 2022, 12:34am UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/4 "2022-12-12T00:34:12Z")

</div>

To handle [redirects](https://developer.mozilla.org/en-US/docs/Web/HTTP/Redirections) you can look at the response code and if it’s `301` or `302` then do another request to the location specified in the `Location` header.

For the download speed you could use [Time.monotonic](https://crystal-lang.org/api/1.6.2/Time.html#monotonic%3ATime%3A%3ASpan-class-method) to calculate how much you download every second.

---

<div class="post-metadata">

**Author:** ![Fulgurance](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fulgurance/32/1463_2.png) [@Fulgurance](https://forum.crystal-lang.org/u/Fulgurance)\
**Post date:** [January 17, 2023, 7:52pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/5 "2023-01-17T19:52:43Z")

</div>

Hi ! Sorry I know I made this post long time ago.

But I’m coming back because I found an another shard to have an HTTP client with redirections supports, and more updated.

**I’m using Crest:** [GitHub - mamantoha/crest: HTTP and REST client for Crystal](https://github.com/mamantoha/crest)

I did that to get the size of the downloaded data.

Is it correct in that way ? Because network isn’t my speciality (this code is just a test):

```auto
require "crest"

startingTime = Time.monotonic
currentTime = Time.monotonic

Crest.get("https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.13.12.tar.xz") do |resp|
  filename = resp.filename || "crystal.zip"

  while line = resp.body_io.gets
    if (currentTime - startingTime).seconds > 1
      text = "crystal.zip | Received data: #{line.bytesize} bytes/seconde"
      print text
      print "\r"
      startingTime = Time.monotonic
    end
    currentTime = Time.monotonic
  end

  File.open(filename, "w") do |file|
    IO.copy(resp.body_io, file)
  end
end

```

I have two questions as well. How can I get before my code download to get the downloaded filename and get the total size of the file ? For the filename, do I need to just extract it from the url ?  
I would like as well to know how much data are already downloaded.

---

<div class="post-metadata">

**Author:** ![mamantoha](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/mamantoha/32/30_2.png) [@mamantoha](https://forum.crystal-lang.org/u/mamantoha)\
**Post date:** [May 6, 2023, 7:17pm UTC](https://forum.crystal-lang.org/t/question-about-http-client/4153/6 "2023-05-06T19:17:51Z")

</div>

Hi @Fulgurance . Maintainer of `crest` here.

Regarding your question on how to retrieve the downloaded file’s filename and total size, you can do this by checking the response headers. Specifically, you can look for the “Content-Disposition” header to get the filename and the “Content-Length” header to get the total size.

If you also want to track the amount of data downloaded, you can use this code.

```crystal
require "crest"

url = "https://github.com/crystal-lang/crystal/archive/1.8.1.zip"
buffer_size = 4096
downloaded_size = 0

Crest.get(url) do |response|
  output_file = response.filename || "crystal.zip"

  File.open(output_file, "w") do |file|
    buffer = Bytes.new(buffer_size)

    loop do
      bytes_read = response.body_io.read(buffer)

      break if bytes_read == 0

      file.write(buffer[0, bytes_read])

      downloaded_size += bytes_read

      print "Received data: #{downloaded_size.humanize_bytes}"
      print "\r"
    end
  end

  puts
  puts "Download complete! Saved as #{output_file}"
end

```
