[elixir] Add library option with Req-based client (tesla remains default)
Closes #24834.
Adds a library option to the Elixir client generator, following the pattern used by the Ruby, Python and Java generators, so the client can be generated on top of Req instead of Tesla.
library=tesla(default): the Tesla templates are untouched and the generated client behaves exactly as before. The only change tosamples/client/petstore/elixircomes from the sharedtypespec()fix below, which corrects specs forfalse-mapped responses in both libraries; #24841 makes the same correction on its own.library=req: new template set underelixir/libraries/req/(api.mustache,connection.ex.mustache,request_builder.ex.mustache). Models, deserializer, mix/config/README templates are shared.
What the Req client does
Connection.new/1accepts the same options as the Tesla client (base_url,user_agent,token/token_scopeswith a fetcher,username/password,bearer_token) and returns aReq.Request. Areq_optionskeyword (per client, or viaconfig :<package>, <Module>.Connection, req_options: [...]) replaces Tesla's middleware/adapter configuration.- Same request semantics as the Tesla client: parameter locations, Tesla-compatible query/form flattening, multipart through Req's
form_multipart(JSON parts carryapplication/json, files stream), binary bodies passed through untouched, JSON bodies encoded with the built-inJSONmodule so models keep derivingJSON.Encoder. - Same response semantics:
RequestBuilder.evaluate_response/2decodes mapped statuses through the sharedDeserializer, returns the whole%Req.Response{}for schema-less mappings (as Tesla returns%Tesla.Env{}),{:ok, %Req.Response{}}for a 2xx the spec does not declare,{:error, %Req.Response{}}for other unmapped statuses and{:error, exception}for transport errors. - Cookie parameters (
in: cookie) are rendered into a singlecookieheader (OpenAPIform/explode=falseserialization for arrays and objects); a nil body sends no body. Req's automatic retry and redirect following are disabled by default to match Tesla; they can be re-enabled throughreq_options. - Typespecs use
Req.Request.t()/Req.Response.t()whenlibrary=req, and responses that map tofalsecontributeReq.Response.t()to the{:ok, ...}union rather than the declared schema type, matching what the request builder actually returns. - Dependency:
{:req, "~> 0.6.0 or ~> 0.7.3"}. 0.6.0 is the first release with the multipart header-escaping fix; 0.7.0–0.7.2 are excluded because they rejected string multipart part names and turned GET requests with a body into POST.
Also in this PR
bin/configs/elixir-req.yamland the generatedsamples/client/petstore/elixir-reqsample, added to.github/workflows/samples-elixir.yaml(same OTP/Elixir matrix, same petstore service).- Codegen unit tests for the option (default,
req, unknown library, generation throughCodegenConfigurator). - Regenerated
docs/generators/elixir.md.
Related
The same cookie / optional-body-comma / undeclared-2xx fixes for the default Tesla templates are in #24841, which is independent of this PR. Cookie parameters are implemented for the req library here; the generator's ParameterFeature.Cookie stays excluded until #24841 adds them to the default Tesla templates, so this PR does not overstate the generator's capabilities.
Not addressed in either PR, present in both clients today and worth separate issues: array query parameters always use bracket style (#23339); path parameters are not percent-encoded; request Content-Type/Accept are not derived from consumes/produces.
Verification
mvn test -Dtest='Elixir*': 6 tests pass.samples/client/petstore/elixir-req:mix compile --warnings-as-errors,mix test(30 tests, againstswaggerapi/petstore),mix dialyzerall pass.samples/client/petstore/elixir: regenerated (typespec corrections only);mix test12 pass.bin/utils/detect_carriage_return.shand tab check clean.
PR checklist
- Read the contribution guidelines.
- Pull Request title clearly describes the work in the pull request and Pull Request description provides details about how to validate the work. Missing information here may result in delayed response from the community.
- Run the following to build the project and update samples:
./mvnw clean package,./bin/generate-samples.sh bin/configs/elixir*.yaml,./bin/utils/export_docs_generators.sh. - File the PR against the correct branch:
master(upcoming minor release). - If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.
cc @wing328 @mrmstn