This library provides a lightweight http client written in Odin. The underlying socket is from SDL2.net provided by Odin/Vendor.
// inside odin/shared
// git clone -b v0.1.3 https://github.com/Inch4Tk/odinhttp
// then in project:
import http "shared:odinhttp/http"
// alternatively to run tests, inside odinhttp folder:
// for some reason the builtin odin (dev-2022-04) test command does not work
odin run test
For Windows (find and add the following dlls to path or directory):
- SDL2.dll (from odin/vendor/sdl2)
- SDL2_net.dll (from odin/vendor/sdl2/net)
For Unix:
- sudo apt-get install libsdl2-2.0
Important: Then follow the instructions in the SSL section to either install OpenSSL oder compile without SSL support.
For a more complete example check example/example.odin
// Before you send requests always make a session, keep this session around
// for the time you want to make requests.
// Right now you can (should) only have a single session and it is not threadsafe.
session := http.make_session() or_return
defer http.delete_session(session)
// Example: Simple get request
req := http.request_prepare(.Get, "https://xyz.com/404") or_return
fmt.printf("Request:\n%s\n", req.buffer)
res := http.request(session, req) or_return
fmt.printf("Response in %d milliseconds:\n%s\n", res.elapsed_ms, res.buffer)
defer http.request_delete(req)
defer http.response_delete(res)
- Http 1.1
- SSL/TLS (compile with SSL Support see below)
- All methods (except CONNECT)
- Headers
- Params
- Body as binary/bytestring data
- Cookies (as Odin map)
- content-encoding: deflate and gzip (automatically set to accept both)
- Timeout
This is an incomplete list of unsupported behavior
- Http2
- Redirects
- "Expect: 100 Continue" requests/responses
- Http tunnels (Method = CONNECT)
- Proxies
- CookieJar (only supports cookies that are supplied as Odin map)
- Ipv6 (no SDL2.net support)
- Parallel requests (library is not threadsafe)
- Charset is assumed to always be utf8
- transfer-encoding: compress, gzip, deflate (this is unlikely to be used when content-encoding is set, which is the preferred way to do compression anyways)
- Chunked requests (only responses can be chunked)
- Chunk extensions
- Timeouts will not work reliably when servers misbehave and send incomplete messages while keeping the connection open
- If a server does not send crlf as last line of header
- If any chunk was not sent completely. This is partly a limitation in SDL, since there is no timeout on read.
- Probably others
- No support for brotli encoding (if someone makes bindings for brotli, I will happily add this)
Add the authorization headers of your choice yourself. Examples:
// Bearer:
token := "...."
headers := make(map[string]string)
defer delete(headers)
headers["authorization"] = fmt.tprintf("Bearer %s", token)
req, err := request_prepare(.Get, "https://xyz.com/404", headers=headers)
// Basic
// expects username/password in base64 encoding separated with ":"
import "core:mem"
import base64 "core:encoding/base64"
username := "...."
password := "...."
headers := make(map[string]string)
defer delete(headers)
concat := fmt.tprintf("%s:%s", username, password)
// have to do some acrobatics to get []u8 from string without copy, is there a better way?
bytecrobatics : []u8 = mem.slice_ptr(strings.ptr_from_string(concat), len(concat))
headers["authorization"] = fmt.tprintf("Basic %s", base64.encode(bytecrobatics))
req, err := request_prepare(.Get, "https://xyz.com/404", headers=headers)
Before sending a request, convert any content-types and input them as byte array. The same goes for content-types received. The response will only contain a byte buffer of the body. Conversion of the content-type has to happen in the calling code.
// Form data
headers := make(map[string]string)
defer delete(headers)
headers["content-type"] = "application/x-www-form-urlencoded"
body_data := "parameter1=value&anykeyname=anothervalue"
req, err := request_prepare(.Post, "https://xyz.com/404", headers=headers, body_data=body_data)
For building bodies with other complex types refer to here:
Content-Length header will be set automatically based on the body size