MTheProgrammer

MTheProgrammer

Hello,

I am working on a SSO implementation for Line Login and Ueberauth. New version was released but the current maintainer did not update API for Line Login v2.1.

What I’ve found is that each Ueberauth SSO implementation can use it’s very own HTTP client.

I feel is that developer should be able to inject desired HTTP client for all Elixir modules.
Unfortunately, there is no such configuration yet.

This forum has a topic about standard HTTP library implemented in the Elixir and disadvantages of multiple clients for each library:

However, as michalmuskala pointed it would require maintenance by the Elixir team.

I’m coming from the OOP world and dependency inversion is common here. For example, PHP has the PSR - PHP standard recommendations - interfaces defining a contract between libraries and applications.
Here is the example: PSR-18: HTTP Client - PHP-FIG
Another example for Logger: PSR-3: Logger Interface - PHP-FIG

Is it possible to have one standarized client API, e.g. a behaviour, that could be implemented by various HTTP clients? I am curious if this methodology is in line with the Elixir/functional philosophy.

Showing Posts 1 to 6

MTheProgrammer

MTheProgrammer OP

Hello,

I’ve created an example HTTP API library:
https://github.com/LucidModules/elixir-http
and its Hackney implementation:
https://github.com/LucidModules/elixir-http-hackney

The main advantages of this approach are:

  • less dependencies - one HTTP client for all libraries, specified in the main app (in the ideal case)
  • easier testing - mock response for the elixir-http library. Forget about implementation.

I will be glad to receive feedback from you.

al2o3cr

al2o3cr

Some thoughts in no particular order:

  • in the request, headers should not be a map - order is important, and the same header can appear multiple times. Passing a map in the headers position to :hackney.request will get you a MatchError

  • in the response type, body is a map but the Hackney implementation puts the output of :hackney.body there, which is specced as binary

  • loading the entire reply body into memory is probably OK, but there’s a reason that Hackney doesn’t do it automatically. Advanced use cases would want to use :hackney.stream_body or similar and there’s no way to do that with this API

  • the response for connection errors is {:error, binary()} which is universal but also opaque. It’s also not satisified by the Hackney adapter, which will sometimes return errors like {:error, :connect_timeout}. Clients may want to handle situations like “no network connectivity” specifically, but that’s not possible with this interface short of pattern-matching on the error message.

  • there’s no way to pass options from the caller down to the adapter, for things like proxy configuration or Hackney’s pool option. Libraries that depend on LmHttpClient should be indifferent to the adapter in use, but the end-user configuring their system is not.

  • the interface forces a synchronous request, which isn’t always desirable in a BEAM program. There are alternatives nowadays like :gun or Mint that divide the work up differently.

MTheProgrammer

MTheProgrammer OP

Thank you for the fast response and your insights.

the interface forces a synchronous request

Isn’t that responsibility of the business domain to spawn new Tasks? Sometimes order of requests is important.

Neither dialyxyr nor credo found these mismatching return types you mentioned. How can we ensure the data flow integrity?

Back to the topic, do you feel that standardizing the HTTP Api for Elixir is reasonable?

MTheProgrammer

MTheProgrammer OP

I’ve created API server mock as described by Sophie DeBenedetto:
https://medium.com/flatiron-labs/rolling-your-own-mock-server-for-testing-in-elixir-2cdb5ccdd1a0

That’s good enough for me for now as the data integrity check.

wojtekmach

wojtekmach

Hex Core Team

After implementing a bunch of HTTP client behaviour modules for different projects and libraries I realised that vast majority of time we don’t need a module, all we need is a function. (Something to keep in mind for other things too.)

Here’s a signature:

f(options) :: {:ok, %{status:, status, headers: headers, body: body}} | {:error, exception}

where options contains :method, :url, :headers, :body and other arbitrary adapter-specific keys.

And then we’d use it like this: Foo.bar(http_request: &MyApp.http_request/1). And if we want to pass options at callsite we’d do: http_request: {&MyApp.http_request/1, receive_timeout: 1000}.

(It is pure accident that with next version of Req, an http client that I’m working on, it’d be: http_request: &Req.request/1. ;))

tristan

tristan

Rebar3 Core Team

This is an old thread but I just saw this and it stuck out to me :slight_smile:

Headers can be a map, but the values for duplicate fields must be combined into a comma separated list. So there should be no requirement for having headers defined as a list by either a client or server – tho the server may have to combine headers into a single value when receiving the request.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 92995 915
New
AstonJ
The obligatory hello world thread! Who are you and where are you from? :stuck_out_tongue:
4616 55835 594
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
arcanemachine
I was working on an Ecto migration and I needed a timestamp. So, for the nth time, I looked up the different data types for timestamps, a...
New
alexslade
Fly’s CEO posted this recently - Turn And Face The Strange · The Fly Blog It says that Fly is going all-in on sprites, which is a worry ...
New
Herve37
We’re evaluating API mocking tools for OpenAPI-based projects and would love to hear what other teams are using. We’re particularly inte...
New
matt-savvy
Is there a word for the ~> symbol used in Version strings? Do you also just call it a Squiggle Arrow™ ?!
New

Other Trending Topics Top

garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
mcass19
ExRatatui lets you cook up rich terminal UIs in Elixir, powered by Rust’s ratatui via Rustler NIFs. Build interactive terminal applicatio...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge & Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
wintermeyer
There are three potential reasons for members of this forum to have a look at https://vutuv.de You are tired or annoyed of LinkedIn. Yo...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews