Skip to content

Commit aea5f4c

Browse files
authored
Add custom HTTP client instructions (#10)
1 parent 81dcc8f commit aea5f4c

25 files changed

Lines changed: 943 additions & 498 deletions

.github/workflows/ci.yml

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ jobs:
6767

6868
- name: Start Typesense
6969
run: |
70-
docker run -d \
70+
docker run -id \
7171
-p 8108:8108 \
7272
--name typesense \
7373
-v /tmp/typesense-data:/data \
@@ -81,8 +81,24 @@ jobs:
8181
--analytics-minute-rate-limit=100 \
8282
--enable-cors
8383
84-
- name: Curl Typesense
85-
run: sleep 1 && curl http://localhost:8108/health
84+
- name: Wait for Typesense to be healthy
85+
shell: bash
86+
run: |
87+
start_time=$(date +%s)
88+
timeout=30
89+
counter=0
90+
until curl -s http://localhost:8108/health | grep -q '"ok":true'; do
91+
if [ $counter -eq $timeout ]; then
92+
echo "Timed out waiting for Typesense to be healthy"
93+
exit 1
94+
fi
95+
echo "Waiting for Typesense to be healthy..."
96+
sleep 1
97+
counter=$((counter + 1))
98+
done
99+
end_time=$(date +%s)
100+
elapsed=$((end_time - start_time))
101+
echo "Typesense healthcheck elapsed: ${elapsed}s"
86102
87103
- name: Setup Elixir/OTP
88104
uses: erlef/setup-beam@v1
@@ -106,9 +122,6 @@ jobs:
106122
mix local.hex --if-missing
107123
mix deps.get
108124
109-
- name: Compile
110-
run: mix compile
111-
112125
- name: Find unused dependencies
113126
run: mix deps.unlock --check-unused
114127
if: ${{ matrix.lint }}

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## major.minor.patch (yyyy.mm.dd)
99

10+
## 0.5.0 (2025.01.08)
11+
12+
### Added
13+
14+
* User(s) can use another HTTP client instead of default ([Req](https://hexdocs.pm/req)).
15+
16+
### Changed
17+
18+
* Update docs
19+
* Static to Dynamic fetching of application name for connection defaults.
20+
* Update docs and include few anchor links.
21+
* Update specific test where async is disabled when using [`Application.put_env/4`](https://elixirforum.com/t/using-application-get-env-application-put-env-in-exunit-tests/8019/2)
22+
1023
## 0.4.3 (2024.12.27)
1124

1225
### Changed

README.md

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ Restful client for Typesense with adherence to Open API spec 3 (formerly Swagger
1010
[![Coverage Status](https://coveralls.io/repos/github/jaeyson/open_api_typesense/badge.svg?branch=main)](https://coveralls.io/github/jaeyson/open_api_typesense?branch=main)
1111
[![CI Status](https://github.com/jaeyson/open_api_typesense/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/jaeyson/open_api_typesense/actions/workflows/ci.yml)
1212

13-
## TODO
14-
- Custom Http client adapter (currently [`Req`](https://hexdocs.pm/req))
15-
1613
## Installation
1714

1815
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
@@ -21,7 +18,7 @@ by adding `open_api_typesense` to your list of dependencies in `mix.exs`:
2118
```elixir
2219
def deps do
2320
[
24-
{:open_api_typesense, "~> 0.4"}
21+
{:open_api_typesense, "~> 0.5"}
2522

2623
# Or from GitHub repository, if you want the latest greatest from main branch
2724
{:open_api_typesense, git: "https://github.com/jaeyson/open_api_typesense.git"}
@@ -53,8 +50,7 @@ if config_env() == :prod do # if you'll use this in prod environment
5350
api_key: "xyz",
5451
host: "localhost",
5552
port: 8108,
56-
scheme: "http",
57-
options: %{}
53+
scheme: "http"
5854
...
5955
```
6056

@@ -64,11 +60,106 @@ if config_env() == :prod do # if you'll use this in prod environment
6460
6561
For Cloud hosted, you can generate and obtain the credentials from cluster instance admin interface:
6662

63+
```elixir
64+
config :open_api_typesense,
65+
api_key: "credential", # Admin API key
66+
host: "111222333aaabbbcc-9.x9.typesense.net", # Nodes
67+
port: 443,
68+
scheme: "https"
69+
```
70+
71+
## Using a another HTTP client
72+
73+
In order to use another HTTP client, OpenApiTypesense has a
74+
callback function ([Behaviours](https://hexdocs.pm/elixir/typespecs.html#behaviours))
75+
called `request` that contains 2 args:
76+
77+
1. `conn`: your connection map
78+
2. `params`: payload, header, and client-related stuffs.
79+
80+
> #### `conn` and `params` {: .info}
81+
>
82+
> you can change the name `conn` and/or `params` however you want,
83+
> since it's just a variable.
84+
85+
Here's a custom client example ([`HTTPoison`](https://hexdocs.pm/httpoison/readme.html))
86+
in order to match the usage:
87+
88+
```elixir
89+
defmodule MyApp.CustomClient do
90+
def request(conn, params) do
91+
url = %URI{
92+
scheme: conn.scheme,
93+
host: conn.host,
94+
port: conn.port,
95+
path: params.url,
96+
query: URI.encode_query(params[:query] || %{})
97+
}
98+
|> URI.to_string()
99+
100+
request = %HTTPoison.Request{method: params.method, url: url}
101+
102+
request =
103+
if params[:request] do
104+
[{content_type, _schema}] = params.request
105+
106+
headers = [
107+
{"X-TYPESENSE-API-KEY", conn.api_key}
108+
{"Content-Type", content_type}
109+
]
110+
111+
%{request | headers: headers}
112+
else
113+
request
114+
end
115+
116+
request =
117+
if params[:body] do
118+
%{request | body: Jason.encode!(params.body)}
119+
else
120+
request
121+
end
122+
123+
HTTPoison.request!(request)
124+
end
125+
end
126+
```
127+
128+
Then add your client in your config file:
129+
67130
```elixir
68131
config :open_api_typesense,
69132
api_key: "credential", # Admin API key
70133
host: "111222333aaabbbcc-9.x9.typesense.net", # Nodes
71134
port: 443,
72135
scheme: "https",
73-
options: %{}
136+
client: MyApp.CustomClient # <- add this
74137
```
138+
139+
And here's a reference taken from one of functions from [`Collections`](https://hexdocs.pm/open_api_typesense/OpenApiTypesense.Collections.html#create_collection/3), as
140+
you may want to match the params:
141+
142+
```elixir
143+
def create_collection(%Connection{} = conn, body, opts) when is_struct(conn) do
144+
client = opts[:client] || @default_client
145+
query = Keyword.take(opts, [:src_name])
146+
147+
client.request(conn, %{
148+
args: [body: body],
149+
call: {OpenApiTypesense.Collections, :create_collection},
150+
url: "/collections",
151+
body: body,
152+
method: :post,
153+
query: query,
154+
request: [{"application/json", {OpenApiTypesense.CollectionSchema, :t}}],
155+
response: [
156+
{201, {OpenApiTypesense.CollectionResponse, :t}},
157+
{400, {OpenApiTypesense.ApiResponse, :t}},
158+
{409, {OpenApiTypesense.ApiResponse, :t}}
159+
],
160+
opts: opts
161+
})
162+
end
163+
```
164+
165+
Check [the examples](./guides/custom_http_client.md) on some HTTP client implementations.

config/config.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ if Mix.env() in [:dev, :test] do
88
scheme: "http"
99
end
1010

11-
if Mix.env() == :dev do
11+
if config_env() in [:dev] do
1212
config :oapi_generator,
1313
default: [
1414
output: [

0 commit comments

Comments
 (0)