Skip to content

HTTP Client

Overview

Frankie has a built-in HTTP client for making GET, POST, PUT, and DELETE requests — no external libraries, no imports.

Built on Python's urllib, it handles JSON automatically and supports custom headers.


Making Requests

http_get(url)

GET request

resp = http_get("https://api.example.com/users")
puts resp.status    200
puts resp.body      raw response body string

http_post(url, data)

POST request

Pass a hash to send as JSON, or a string for plain text.

# Send JSON
resp = http_post("https://api.example.com/users", {
  name:  "Alice",
  email: "alice@example.com"
})
puts resp.status    201

http_put(url, data)

PUT request

resp = http_put("https://api.example.com/users/42", {
  name: "Alice Updated"
})
puts resp.status    200

http_delete(url)

DELETE request

resp = http_delete("https://api.example.com/users/42")
puts resp.status    204

The Response Object

Every HTTP function returns an HTTPResponse with these fields and methods:

Property / Method Type Description
.status Integer HTTP status code
.body String Raw response body
.headers Hash Response headers
.json() Hash / Vector Parse body as JSON
.ok() Boolean True if status is 2xx
resp = http_get("https://api.example.com/data")

puts resp.status               200
puts resp.ok()                 true
puts resp.headers["Content-Type"]   # application/json

# Parse JSON body
data = resp.json()
puts data["name"]

Custom Headers

Pass a hash of headers as the last argument to any function.

# Bearer token auth
resp = http_get(
  "https://api.example.com/protected",
  {"Authorization": "Bearer your_token_here"}
)

# Multiple headers
resp = http_post(
  "https://api.example.com/data",
  {value: 42},
  {
    "Authorization": "Bearer token",
    "X-Request-ID":  "abc-123"
  }
)

When you pass a hash as data, Frankie automatically sets Content-Type: application/json. You don't need to set it manually.


Checking Status

resp = http_get("https://api.example.com/resource")

if resp.ok()
  data = resp.json()
  puts data["result"]
else
  puts "Error #{resp.status}: #{resp.body}"
end

Common status codes:

Code Meaning
200 OK
201 Created
204 No Content
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
500 Internal Server Error

URL Utilities

url_encode(hash)

Encode a hash as a query string

params = {page: 1, limit: 20, sort: "name"}
puts url_encode(params)
# page=1&limit=20&sort=name

# Append to URL manually
base = "https://api.example.com/users"
resp = http_get("#{base}?#{url_encode(params)}")

url_decode(str)

Decode a query string into a hash

qs = "page=1&limit=20&sort=name"
params = url_decode(qs)
puts params["page"]    # 1
puts params["sort"]    # name

Error Handling

HTTP errors (4xx, 5xx) are returned as responses with the corresponding status code — they do not raise exceptions.

Network errors (no connection, timeout, DNS failure) do raise RuntimeError.

# HTTP error — returns a response, no raise
resp = http_get("https://api.example.com/missing")
puts resp.status   # 404
puts resp.body     # error body from server

# Network error — raises
begin
  resp = http_get("https://does-not-exist.invalid/")
rescue RuntimeError e
  puts "Network error: #{e}"
end

Quick Reference

Function Description
http_get(url) GET request
http_get(url, headers) GET with custom headers
http_post(url, data) POST — hash sends as JSON
http_post(url, data, headers) POST with custom headers
http_put(url, data) PUT request
http_put(url, data, headers) PUT with custom headers
http_delete(url) DELETE request
http_delete(url, headers) DELETE with custom headers
url_encode(hash) Hash → query string
url_decode(str) Query string → hash
resp.status HTTP status code
resp.body Raw response string
resp.headers Response headers hash
resp.json() Parse body as JSON
resp.ok() True if 2xx status