halite~kalinon
💎 Halite
Yet another simple HTTP and REST client with a chainable API, built-in sessions and timeouts written by Crystal. Inspired from the awesome Ruby's HTTP/RESTClient gem and Python's requests.
Build in crystal version >= v0.23.1
, Docs Generated in latest commit.
Installation
Add this to your application's shard.yml
:
dependencies:
halite:
github: icyleaf/halite
Usage
require "halite"
Making Requests
Make a GET request:
# Direct get url
Halite.get("http://httpbin.org/get")
# Support NamedTuple as query params
Halite.get("http://httpbin.org/get", params: {
language: "crystal",
shard: "halite"
})
# Also support Array as query params
Halite.get("http://httpbin.org/get", headers: {
"Private-Token" => "T0k3n"
}, params: {
"language" => "crystal",
"shard" => "halite"
})
# And support chainable
Halite.header(private_token: "T0k3n")
.get("http://httpbin.org/get", params: {
"language" => "crystal",
"shard" => "halite"
})
See also all chainable methods.
Many other HTTP methods are avaiabled as well:
get
head
patch
post
put
delete
Halite.get("http://httpbin.org/get", params: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Halite.head("http://httpbin.org/anything", params: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Halite.post("http://httpbin.org/post", form: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Halite.put("http://httpbin.org/put", json: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Halite.patch("http://httpbin.org/anything", json: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Haltie.delete("http://httpbin.org/delete", params: { "user_id" => 234234 })
Passing Parameters
Query string parameters
Use the params
argument to add query string parameters to requests:
Halite.get("http://httpbin.org/get", params: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Form data
Use the form
argument to pass data serialized as form encoded:
Halite.post("http://httpbin.org/post", form: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
File uploads (via form data)
To upload files as if form data, construct the form as follows:
Halite.post("http://httpbin.org/post", form: {
"username" => "Quincy",
"avatar" => File.open("/Users/icyleaf/quincy_avatar.png")
})
JSON data
Use the json
argument to pass data serialized as body encoded:
Halite.post("http://httpbin.org/post", json: { "firstname" => "Olen", "lastname" => "Rosenbaum" })
Passing advanced options
Headers
Here are two way to passing headers data:
1. Use the #headers
method
Halite.headers(private_token: "T0k3n").get("http://httpbin.org/get")
# Also support Hash or NamedTuple
Halte.headers({ "private_token" => "T0k3n" }).get("http://httpbin.org/get")
# Or
Halte.headers({ private_token: "T0k3n" }).get("http://httpbin.org/get")
2. Use the headers
argument in availabled request method:
Halite.get("http://httpbin.org/anything" , headers: { private_token: "T0k3n" })
Halite.post("http://httpbin.org/anything" , headers: { private_token: "T0k3n" })
Auth
Use the #basic_auth
method to perform HTTP Basic Authentication using a username and password:
Halite.basic_auth(user: "user", password: "p@ss").get("http://httpbin.org/get")
# You can pass a raw authorization header using the auth method:
Halite.auth("Bearer dXNlcjpwQHNz").get("http://httpbin.org/get")
Cookies
Passing cookies in requests
The Halite.cookies
option can be used to configure cookies for a given request:
Halite.cookies(session_cookie: "6abaef100b77808ceb7fe26a3bcff1d0")
.get("http://httpbin.org/headers")
Get cookies in requests
To obtain the cookies(cookie jar) for a given response, call the #cookies
method:
r = Halite.get("http://httpbin.org/cookies?set?session_cookie=6abaef100b77808ceb7fe26a3bcff1d0")
pp r.cookies
# => #<HTTP::Cookies:0x10dbed980 @cookies={"session_cookie" =>#<HTTP::Cookie:0x10ec20f00 @domain=nil, @expires=nil, @extension=nil, @http_only=false, @name="session_cookie", @path="/", @secure=false, @value="6abaef100b77808ceb7fe26a3bcff1d0">}>
Redirects
Automatically following redirects
The Halite.follow
method can be used for automatically following redirects(Max up to 5 times):
# Set the cookie and redirect to http://httpbin.org/cookies
Halite.follow
.get("http://httpbin.org/cookies/set/name/foo")
Limiting number of redirects
As above, set over 5 times, it will raise a Halite::TooManyRedirectsError
, but you can change less if you can:
Halite.follow(2)
.get("http://httpbin.org/relative-redirect/5")
Disabling unsafe redirects
It only redirects with GET
, HEAD
request and returns a 300
, 301
, 302
by default, otherwise it will raise a Halite::StateError
.
You can diasble it to set :strict
to false
if you want any method(verb) requests, in which case the GET
method(verb) will be used for
that redirect:
Halite.follow(strict: false)
.post("http://httpbin.org/relative-redirect/5")
Timeout
By default, the Halite does not enforce timeout on a request. You can enable per operation timeouts by configuring them through the chaining API.
The connect
timeout is the number of seconds Halite will wait for your client to establish a connection to a remote server call on the socket.
Once your client has connected to the server and sent the HTTP request, the read
timeout is the number of seconds the client will wait for the server to send a response.
# Separate set connect and read timeout
Halite.timeout(connect: 3.0, read: 2.minutes)
.get("http://httpbin.org/anything")
# Boath set connect and read timeout
# The timeout value will be applied to both the connect and the read timeouts.
Halite.timeout(5)
.get("http://httpbin.org/anything")
Response Handling
After an HTTP request, Halite::Response
object have several useful methods. (Also see the API documentation).
- #body: The response body.
- #body_io: The response body io.
- #code: The HTTP status code.
- #content_type: The content type of the response.
- #content_length: The content length of the response.
- #cookies: A
HTTP::Cookies
set by server. - #headers: The
HTTP::Headers
of the response. - #version: The HTTP version.
- #to_a: A
Hash
of status code, response headers and body as a string. - #to_s: Return response body as a string.
Error Handling
- For any status code, a
Halite::Response
will be returned - If request timeout, a
Halite::TimeoutError
will be raised.
Advanced Usage
Sessions
As like requests.Session(), Halite built-in session by default.
Let's persist some cookies across requests:
client = Halite::Client.new
client.get("http://httpbin.org/cookies/set?private_token=6abaef100b77808ceb7fe26a3bcff1d0")
r = client.get("http://httpbin.org/cookies")
puts r.body
# => "{\n \"cookies\": {\n \"private_token\": \"6abaef100b77808ceb7fe26a3bcff1d0\"\n }\n}\n"
All it support with chainable methods in the other examples list in requests.Session.
Help and Discussion
You can browese the API documents:
https://icyleaf.github.io/halite/
You can browse the all chainable methods:
https://icyleaf.github.io/halite/Halite/Chainable.html
If you have found a bug, please create a issue here:
https://github.com/icyleaf/halite/issues/new
Contributing
- Fork it ( https://github.com/icyleaf/halite/fork )
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create a new Pull Request
Contributors
- icyleaf - creator, maintainer