DEV Community

Cover image for Crest 1.0.0 Release
Anton Maminov
Anton Maminov

Posted on

Crest 1.0.0 Release

This article is about Crest — HTTP and REST client for Crystal programming language.

A little about me

My name is Anton and I'm a self-taught full-stack Ruby on Rails developer.

Back in 2017, I had a desire to learn a new programming language.

Crystal caught my attention because of it's similarity to Ruby and because "Fast as C, Slick as Ruby ©".

Literally you can run the same code in Ruby and in Crystal, and it will work.

Unlike Ruby, Crystal is a typed language, but most of the time it's not required to specify types.

Crystal comes with a great standard library and tools. It has almost all the stuff you need to build applications.
CSV, XML, YAML, JSON, HTTP server/client, and even WebSocket are bundled with Crystal itself, making it super simple to start building something.

Project history

For practical reasons, I decided to re-implement Ruby's rest-client gem to dive into the Crystal.

I started the Crest project at April 2017 when Crystal was 0.21.1.

And in a 7 months I has working implementation with next features:

  • redirects support
  • proxy support
  • support nested hashes for headers, cookies, query params, and form data.
  • multipart file uploads
  • logging

The first stable version 0.9.2 was released on 1 Nov 2017.

After more than 4 years of development and 48 releases, I'm happy to announce version Crest 1.0.0.

Example

The common case of HTTP clients is sending a form data to a server.

Let's implement curl command below:

curl -X POST https://httpbin.org/post\?author\=John+Doe\&offset\=20 -F 'user[name]=Tom' -F 'user[file]=@/path/to/file.png' -H 'Foo: bar' --cookie 'foo=bar' -A 'Mozilla/5.0'
Enter fullscreen mode Exit fullscreen mode

Here is an example showing how to do this in pure Crystal:

require "http/client"

# Builds a multipart/form-data
channel = Channel(String).new(1)
io = IO::Memory.new

HTTP::FormData.build(io) do |formdata|
  channel.send(formdata.content_type)

  formdata.field("user[name]", "Tom")

  File.open("/path/to/file.png") do |file|
    mime = MIME.from_filename(file.path)
    metadata = HTTP::FormData::FileMetadata.new(filename: file.path)
    headers = HTTP::Headers{"Content-Type" => mime}
    formdata.file("user[file]", file, metadata, headers)
  end
end

content_type = channel.receive

# Builds headers
headers = HTTP::Headers{"User-Agent" => "Mozilla/5.0", "Content-Type" => content_type, "Foo" => "bar"}

# Builds cookies
cookies = HTTP::Cookies.new
cookie = HTTP::Cookie.new("foo", "bar")
cookies << cookie

# Adds Cookie headers for the cookies in this collection to the given `HTTP::Headers` instance
cookies.add_request_headers(headers)

# Build a URL encoded HTTP query
params = URI::Params.encode({"author" => "John Doe", "offset" => "20"})

# Make a request
response = HTTP::Client.post(
  URI.new("https", "httpbin.org", path: "/post", query: params),
  headers: headers,
  body: io.to_s
)

puts response.body
Enter fullscreen mode Exit fullscreen mode

Here is an example showing how to do the same with Crest:

require "crest"

response = Crest.post(
  "https://httpbin.org/post",
  form: {"user" => {"name" => "Tom", "file" => File.open("/path/to/file.png")}},
  params: {"author" => "John Doe", "offset" => "20"},
  headers: {"Foo" => "bar"},
  cookies: {"foo" => "bar"},
  user_agent: "Mozilla/5.0"
)

puts response.body
Enter fullscreen mode Exit fullscreen mode

Bonus

Do you remember a curl command from the beginning of this article?
Crest have a .to_curl method to convert Crest::Request object to curl command.

puts response.to_curl
# => curl -X POST https://httpbin.org/post?author=John+Doe&offset=20 -F 'user[name]=Tom' -F 'user[file]=@/home/mama/ruby/crystal/crest/spec/support/fff.png' -H 'Foo: bar' -H 'User-Agent: Mozilla/5.0' -H 'Cookie: foo=bar' -H 'Content-Type: multipart/form-data'
Enter fullscreen mode Exit fullscreen mode

If you have any questions, please let me know. I'd love to get your feedback!

Top comments (2)

Collapse
 
gdotdesign profile image
Szikszai Gusztáv

Congrats on the release! 🤗🎉

Collapse
 
mamantoha profile image
Anton Maminov

Thanks!