From 2f7089027164fcd30d6bab5b98cd805fe2cdf006 Mon Sep 17 00:00:00 2001 From: "Kian-Meng, Ang" Date: Sat, 30 Jan 2021 14:35:46 +0800 Subject: [PATCH] Misc doc changes List of changes: - Bump license year - Use common source url - Fix typos - Fix markdown - Add release changelog to readme - Add hexdocs badge - Use and set ex_doc to latest version - Update gitignore --- .gitignore | 28 ++++++-- LICENSE | 2 +- README.md | 50 ++++++------- lib/tesla.ex | 25 +++---- lib/tesla/adapter/finch.ex | 6 +- lib/tesla/adapter/gun.ex | 92 ++++++++++++++++++------ lib/tesla/adapter/hackney.ex | 2 +- lib/tesla/adapter/ibrowse.ex | 2 +- lib/tesla/adapter/mint.ex | 4 +- lib/tesla/builder.ex | 2 +- lib/tesla/client.ex | 4 +- lib/tesla/middleware/basic_auth.ex | 2 +- lib/tesla/middleware/compression.ex | 6 +- lib/tesla/middleware/core.ex | 10 +-- lib/tesla/middleware/decode_rels.ex | 2 +- lib/tesla/middleware/digest_auth.ex | 6 +- lib/tesla/middleware/follow_redirects.ex | 4 +- lib/tesla/middleware/form_urlencoded.ex | 2 +- lib/tesla/middleware/fuse.ex | 4 +- lib/tesla/middleware/json.ex | 8 +-- lib/tesla/middleware/keep_request.ex | 4 +- lib/tesla/middleware/logger.ex | 7 +- lib/tesla/middleware/method_override.ex | 9 ++- lib/tesla/middleware/path_params.ex | 2 +- lib/tesla/middleware/retry.ex | 33 ++++----- lib/tesla/middleware/telemetry.ex | 55 +++++++------- lib/tesla/middleware/timeout.ex | 6 +- lib/tesla/mock.ex | 4 +- lib/tesla/multipart.ex | 2 +- mix.exs | 5 +- 30 files changed, 229 insertions(+), 159 deletions(-) diff --git a/.gitignore b/.gitignore index 03de4bf8..00223b06 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,23 @@ -/_build -/deps +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# If the VM crashes, it generates a dump, let's ignore it too. erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). *.ez -/doc -/cover -.tool-versions -/sandbox -.elixir_ls + +# Ignore package tarball (built via "mix hex.build"). +tesla-*.tar + +# Temporary files for e.g. tests +/tmp diff --git a/LICENSE b/LICENSE index 2410a944..08490c4b 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015-2020 Tymon Tobolski +Copyright (c) 2015-2021 Tymon Tobolski Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 7a37e08b..9285fc5f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ [![Build Status](https://github.com/teamon/tesla/workflows/Test/badge.svg?branch=master)](https://github.com/teamon/tesla/actions) [![Hex.pm](https://img.shields.io/hexpm/v/tesla.svg)](http://hex.pm/packages/tesla) +[![Hexdocs.pm](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/tesla/) [![Hex.pm](https://img.shields.io/hexpm/dt/tesla.svg)](https://hex.pm/packages/tesla) [![Hex.pm](https://img.shields.io/hexpm/dw/tesla.svg)](https://hex.pm/packages/tesla) [![codecov](https://codecov.io/gh/teamon/tesla/branch/master/graph/badge.svg)](https://codecov.io/gh/teamon/tesla) @@ -14,11 +15,7 @@ It embraces the concept of middleware when processing the request/response cycle released version on Hex. See [the documentation](http://hexdocs.pm/tesla) for the documentation of the version you're using. ---- - -## [`0.x` to `1.0` Migration Guide](https://github.com/teamon/tesla/wiki/0.x-to-1.0-Migration-Guide) - -[Documentation for 0.x branch](https://github.com/teamon/tesla/tree/0.x) +For the list of changes, checkout the latest [release notes](https://github.com/teamon/tesla/releases). --- @@ -59,7 +56,7 @@ See below for documentation. ## Installation -Add `tesla` as dependency in `mix.exs`: +Add `:tesla` as dependency in `mix.exs`: ```elixir defp deps do @@ -73,7 +70,6 @@ defp deps do {:jason, ">= 1.0.0"} ] end - ``` Tesla uses [Semantic Versioning](https://semver.org) 2.0. @@ -115,17 +111,17 @@ This is very similar to how [Plug Router](https://github.com/elixir-plug/plug#th - [`Tesla.Middleware.Headers`](https://hexdocs.pm/tesla/Tesla.Middleware.Headers.html) - set request headers - [`Tesla.Middleware.Query`](https://hexdocs.pm/tesla/Tesla.Middleware.Query.html) - set query parameters - [`Tesla.Middleware.Opts`](https://hexdocs.pm/tesla/Tesla.Middleware.Opts.html) - set request options -- [`Tesla.Middleware.FollowRedirects`](https://hexdocs.pm/tesla/Tesla.Middleware.FollowRedirects.html) - follow 3xx redirects -- [`Tesla.Middleware.MethodOverride`](https://hexdocs.pm/tesla/Tesla.Middleware.MethodOverride.html) - set X-Http-Method-Override -- [`Tesla.Middleware.Logger`](https://hexdocs.pm/tesla/Tesla.Middleware.Logger.html) - log requests (method, url, status, time) -- [`Tesla.Middleware.KeepRequest`](https://hexdocs.pm/tesla/Tesla.Middleware.KeepRequest.html) - keep request body & headers +- [`Tesla.Middleware.FollowRedirects`](https://hexdocs.pm/tesla/Tesla.Middleware.FollowRedirects.html) - follow HTTP 3xx redirects +- [`Tesla.Middleware.MethodOverride`](https://hexdocs.pm/tesla/Tesla.Middleware.MethodOverride.html) - set `X-Http-Method-Override` header +- [`Tesla.Middleware.Logger`](https://hexdocs.pm/tesla/Tesla.Middleware.Logger.html) - log requests (method, url, status, and time) +- [`Tesla.Middleware.KeepRequest`](https://hexdocs.pm/tesla/Tesla.Middleware.KeepRequest.html) - keep request `body` and `headers` - [`Tesla.Middleware.PathParams`](https://hexdocs.pm/tesla/Tesla.Middleware.PathParams.html) - use templated URLs ### Formats - [`Tesla.Middleware.FormUrlencoded`](https://hexdocs.pm/tesla/Tesla.Middleware.FormUrlencoded.html) - urlencode POST body, useful for POSTing a map/keyword list - [`Tesla.Middleware.JSON`](https://hexdocs.pm/tesla/Tesla.Middleware.JSON.html) - JSON request/response body -- [`Tesla.Middleware.Compression`](https://hexdocs.pm/tesla/Tesla.Middleware.Compression.html) - gzip & deflate +- [`Tesla.Middleware.Compression`](https://hexdocs.pm/tesla/Tesla.Middleware.Compression.html) - `gzip` and `deflate` - [`Tesla.Middleware.DecodeRels`](https://hexdocs.pm/tesla/Tesla.Middleware.DecodeRels.html) - decode `Link` header into `opts[:rels]` field in response ### Auth @@ -141,7 +137,7 @@ This is very similar to how [Plug Router](https://github.com/elixir-plug/plug#th ## Runtime middleware -All HTTP functions (`get`, `post`, etc.) can take a dynamic client as the first argument. +All HTTP functions, such as `Tesla.get/3` and `Tesla.post/4`, can take a dynamic client as the first argument. This allow to use convenient syntax for modifying the behaviour in runtime. Consider the following case: GitHub API can be accessed using OAuth token authorization. @@ -196,13 +192,14 @@ Tesla supports multiple HTTP adapter that do the actual HTTP request processing. - [`Tesla.Adapter.Mint`](https://hexdocs.pm/tesla/Tesla.Adapter.Mint.html) - [mint](https://github.com/elixir-mint/mint), "Functional HTTP client for Elixir with support for HTTP/1 and HTTP/2" - [`Tesla.Adapter.Finch`](https://hexdocs.pm/tesla/Tesla.Adapter.Finch.html) - [finch](https://github.com/keathley/finch), "An HTTP client with a focus on performance, built on top of [Mint](https://github.com/elixir-mint/mint) and [NimblePool](https://github.com/dashbitco/nimble_pool)." -When using adapter other than httpc remember to add it to the dependencies list in `mix.exs` +When using adapter other than `:httpc` remember to add it to the dependencies list in `mix.exs` ```elixir defp deps do - [{:tesla, "~> 1.4.0"}, - {:jason, ">= 1.0.0"}, # optional, required by JSON middleware - {:hackney, "~> 1.10"}] # or :gun etc. + [ + {:tesla, "~> 1.4.0"}, + {:hackney, "~> 1.10"} # when using hackney adapter + ] end ``` @@ -230,7 +227,7 @@ def new(...) do end ``` -Passing directly to `get`/`post`/etc. +Passing directly to request functions such as `MyClient.get/3` or `Tesla.get/3`. ```elixir MyClient.get("/", opts: [adapter: [recv_timeout: 30_000]]) @@ -255,11 +252,11 @@ defmodule ElasticSearch do end ``` -Each piece of stream will be encoded as JSON and sent as a new line (conforming to JSON stream format) +Each piece of stream will be encoded as JSON and sent as a new line (conforming to JSON stream format). ## Multipart -You can pass a `Tesla.Multipart` struct as the body. +You can pass a `Tesla.Multipart` struct as the body: ```elixir alias Tesla.Multipart @@ -280,7 +277,7 @@ mp = ## Testing -You can set the adapter to `Tesla.Mock` in tests. +You can set the adapter to `Tesla.Mock` in tests: ```elixir # config/test.exs @@ -320,8 +317,7 @@ end ## Writing middleware -A Tesla middleware is a module with `c:Tesla.Middleware.call/3` function, that at some point calls `Tesla.run/2` with `env` and `next` to process -the rest of stack. +A Tesla middleware is a module with `c:Tesla.Middleware.call/3` function, that at some point calls `Tesla.run/2` with `env` and `next` to process the rest of stack. ```elixir defmodule MyMiddleware do @@ -384,7 +380,7 @@ defmodule Tesla.Middleware.SomeMiddleware do Longer description, including e.g. additional dependencies. - ### Example usage + ### Examples ``` defmodule MyClient do @@ -503,6 +499,10 @@ defmodule Tesla.Middleware.MyCustomMiddleware do end ``` +## [`0.x` to `1.0` Migration Guide](https://github.com/teamon/tesla/wiki/0.x-to-1.0-Migration-Guide) + +[Documentation for 0.x branch](https://github.com/teamon/tesla/tree/0.x) + ## Contributing 1. Fork it (https://github.com/teamon/tesla/fork) @@ -515,7 +515,7 @@ end This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details -Copyright (c) 2015-2020 [Tymon Tobolski](https://teamon.me/about/) +Copyright (c) 2015-2021 [Tymon Tobolski](https://teamon.me/about/) --- diff --git a/lib/tesla.ex b/lib/tesla.ex index 8b241822..58ee3ca1 100644 --- a/lib/tesla.ex +++ b/lib/tesla.ex @@ -66,7 +66,7 @@ end defmodule Tesla.Middleware do @moduledoc """ - The middleware specification + The middleware specification. Middleware is an extension of basic `Tesla` functionality. It is a module that must implement `c:Tesla.Middleware.call/3`. @@ -77,7 +77,7 @@ defmodule Tesla.Middleware do plug Tesla.Middleware.BaseUrl, "https://example.com" - or inside tuple in case of dynamic middleware (`Tesla.client/1`) + or inside tuple in case of dynamic middleware (`Tesla.client/1`): Tesla.client([{Tesla.Middleware.BaseUrl, "https://example.com"}]) @@ -87,7 +87,7 @@ defmodule Tesla.Middleware do See `c:Tesla.Middleware.call/3` for details. - ### Example + ### Examples defmodule MyProject.InspectHeadersMiddleware do @behaviour Tesla.Middleware @@ -138,7 +138,7 @@ defmodule Tesla.Adapter do See `c:Tesla.Adapter.call/2` for details. - ### Example + ### Examples defmodule MyProject.CustomAdapter do alias Tesla.Multipart @@ -215,18 +215,19 @@ defmodule Tesla do @default_adapter Tesla.Adapter.Httpc @moduledoc """ - A HTTP toolkit for building API clients using middlewares + A HTTP toolkit for building API clients using middlewares. ## Building API client - `use Tesla` macro will generate basic http functions (e.g. get, post) inside your module. + `use Tesla` macro will generate basic HTTP functions (e.g. `get/3`, `post/4`, etc.) inside your module. + It supports following options: - `:only` - builder will generate only functions included in the given list - `:except` - builder will not generate the functions that are listed in the options - `:docs` - when set to false builder will not add documentation to generated functions - ### Example + ### Examples defmodule ExampleApi do use Tesla, only: [:get], docs: false @@ -277,16 +278,16 @@ defmodule Tesla do end end - call to `ExampleApi.fetch_data/0` will fail, because request will be missing base url. + call to `ExampleApi.fetch_data/0` will fail, because request will be missing base URL. ## Default adapter By default `Tesla` is using `Tesla.Adapter.Httpc`, because `:httpc` is included in Erlang/OTP and - doen not require installation of any additional dependency. It can be changed globally with config + does not require installation of any additional dependency. It can be changed globally with config: config :tesla, :adapter, Tesla.Adapter.Hackney - or by `Tesla.Builder.adapter/2` macro for given API client module + or by `Tesla.Builder.adapter/2` macro for given API client module: defmodule ExampleApi do use Tesla @@ -380,7 +381,7 @@ defmodule Tesla do Useful when there's need to store additional middleware data in `Tesla.Env` - ## Example + ## Examples iex> %Tesla.Env{opts: []} |> Tesla.put_opt(:option, "value") %Tesla.Env{opts: [option: "value"]} @@ -509,7 +510,7 @@ defmodule Tesla do Useful when you need to create an URL with dynamic query params from a Keyword list - ## Example + ## Examples iex> Tesla.build_url("http://api.example.com", [user: 3, page: 2]) "http://api.example.com?user=3&page=2" diff --git a/lib/tesla/adapter/finch.ex b/lib/tesla/adapter/finch.ex index 342e9cf6..b119b0f8 100644 --- a/lib/tesla/adapter/finch.ex +++ b/lib/tesla/adapter/finch.ex @@ -11,7 +11,7 @@ if Code.ensure_loaded?(Finch) do mix compile ``` - ## Example usage + ## Examples In order to use Finch, you must start it and provide a `:name`. For example, in your supervision tree: @@ -43,10 +43,10 @@ if Code.ensure_loaded?(Finch) do ## [Finch options](https://hexdocs.pm/finch/Finch.html#request/3) * `:pool_timeout` - This timeout is applied when a connection is checekd - out from the pool. Default value is `5_000`. + out from the pool. Default value is `5_000`. * `:receive_timeout` - The maximum time to wait for a response before - returning an error. Default value is `15_000`. + returning an error. Default value is `15_000`. """ @behaviour Tesla.Adapter diff --git a/lib/tesla/adapter/gun.ex b/lib/tesla/adapter/gun.ex index 771d4b6f..e6c3ca33 100644 --- a/lib/tesla/adapter/gun.ex +++ b/lib/tesla/adapter/gun.ex @@ -4,6 +4,7 @@ if Code.ensure_loaded?(:gun) do Adapter for [gun](https://github.com/ninenines/gun). Remember to add `{:gun, "~> 1.3"}`, `{:idna, "~> 6.0"}` and `{:castore, "~> 0.1"}` to dependencies. + In version 1.3 gun sends `host` header with port. Fixed in master branch. Also, you need to recompile tesla after adding `:gun` dependency: @@ -12,7 +13,7 @@ if Code.ensure_loaded?(:gun) do mix deps.compile tesla ``` - ## Example usage + ## Examples ``` # set globally in config/config.exs @@ -28,34 +29,83 @@ if Code.ensure_loaded?(:gun) do ## Adapter specific options - `:timeout` - Time, while process, will wait for gun messages. - - `:body_as` - What will be returned in `%Tesla.Env{}` body key. Possible values - `:plain`, `:stream`, `:chunks`. Defaults to `:plain`. - - `:plain` - as binary. - - `:stream` - as stream. If you don't want to close connection (because you want to reuse it later) pass `close_conn: false` in adapter opts. - - `:chunks` - as chunks. You can get response body in chunks using `Tesla.Adapter.Gun.read_chunk/3` function. - Processing of the chunks and checking body size must be done by yourself. Example of processing function is in `test/tesla/adapter/gun_test.exs` - `Tesla.Adapter.GunTest.read_body/4`. If you don't need connection later don't forget to close it with `Tesla.Adapter.Gun.close/1`. - - `:max_body` - Max response body size in bytes. Works only with `body_as: :plain`, with other settings you need to check response body size by yourself. + + - `:body_as` - What will be returned in `%Tesla.Env{}` body key. Possible values: + - `:plain` - as binary (default). + - `:stream` - as stream. + If you don't want to close connection (because you want to reuse it later) + pass `close_conn: false` in adapter opts. + - `:chunks` - as chunks. + You can get response body in chunks using `Tesla.Adapter.Gun.read_chunk/3` function. + + Processing of the chunks and checking body size must be done by yourself. + Example of processing function is in `test/tesla/adapter/gun_test.exs` - `Tesla.Adapter.GunTest.read_body/4`. + If you don't need connection later don't forget to close it with `Tesla.Adapter.Gun.close/1`. + + - `:max_body` - Max response body size in bytes. + Works only with `body_as: :plain`, with other settings you need to check response body size by yourself. + - `:conn` - Opened connection pid with gun. Is used for reusing gun connections. - - `:close_conn` - Close connection or not after receiving full response body. Is used for reusing gun connections. Defaults to `true`. - - `:certificates_verification` - Add SSL certificates verification. [erlang-certifi](https://github.com/certifi/erlang-certifi) [ssl_verify_fun.erl](https://github.com/deadtrickster/ssl_verify_fun.erl) - - `:proxy` - Proxy for requests. **Socks proxy are supported only for gun master branch**. Examples: `{'localhost', 1234}`, `{{127, 0, 0, 1}, 1234}`, `{:socks5, 'localhost', 1234}`. - NOTE: By default GUN uses TLS as transport if the specified port is 443, if TLS is required for proxy connection on another port please specify transport using the Gun options below otherwise tcp will be used - - `:proxy_auth` - Auth to be passed along with the proxy opt, supports Basic auth for regular and Socks proxy. Format: `{proxy_username, proxy_password}`. + + - `:close_conn` - Close connection or not after receiving full response body. + Is used for reusing gun connections. Defaults to `true`. + + - `:certificates_verification` - Add SSL certificates verification. + [erlang-certifi](https://github.com/certifi/erlang-certifi) + [ssl_verify_fun.erl](https://github.com/deadtrickster/ssl_verify_fun.erl) + + - `:proxy` - Proxy for requests. + **Socks proxy are supported only for gun master branch**. + Examples: `{'localhost', 1234}`, `{{127, 0, 0, 1}, 1234}`, `{:socks5, 'localhost', 1234}`. + + **NOTE:** By default GUN uses TLS as transport if the specified port is 443, + if TLS is required for proxy connection on another port please specify transport + using the Gun options below otherwise tcp will be used. + + - `:proxy_auth` - Auth to be passed along with the proxy opt. + Supports Basic auth for regular and Socks proxy. + Format: `{proxy_username, proxy_password}`. ## [Gun options](https://ninenines.eu/docs/en/gun/1.3/manual/gun/) - `:connect_timeout` - Connection timeout. + - `:http_opts` - Options specific to the HTTP protocol. + - `:http2_opts` - Options specific to the HTTP/2 protocol. - - `:protocols` - Ordered list of preferred protocols. Defaults: `[:http2, :http]`- for :tls, `[:http]` - for :tcp. - - `:trace` - Whether to enable dbg tracing of the connection process. Should only be used during debugging. Default: false. - - `:transport` - Whether to use TLS or plain TCP. The default varies depending on the port used. Port 443 defaults to tls. All other ports default to tcp. - - `:transport_opts` - Transport options. They are TCP options or TLS options depending on the selected transport. Default: `[]`. Gun version: 1.3 - - `:tls_opts` - TLS transport options. Default: `[]`. Gun from master branch. - - `:tcp_opts` - TCP trasnport options. Default: `[]`. Gun from master branch. - - `:socks_opts` - Options for socks. Default: `[]`. Gun from master branch. + + - `:protocols` - Ordered list of preferred protocols. + Defaults: `[:http2, :http]`- for :tls, `[:http]` - for :tcp. + + - `:trace` - Whether to enable dbg tracing of the connection process. + Should only be used during debugging. Default: false. + + - `:transport` - Whether to use TLS or plain TCP. + The default varies depending on the port used. + Port 443 defaults to tls. All other ports default to tcp. + + - `:transport_opts` - Transport options. + They are TCP options or TLS options depending on the selected transport. + Default: `[]`. Gun version: 1.3. + + - `:tls_opts` - TLS transport options. + Default: `[]`. Gun from master branch. + + - `:tcp_opts` - TCP trasnport options. + Default: `[]`. Gun from master branch. + + - `:socks_opts` - Options for socks. + Default: `[]`. Gun from master branch. + - `:ws_opts` - Options specific to the Websocket protocol. Default: `%{}`. - - `:compress` - Whether to enable permessage-deflate compression. This does not guarantee that compression will be used as it is the server that ultimately decides. Defaults to false. - - `:protocols` - A non-empty list enables Websocket protocol negotiation. The list of protocols will be sent in the sec-websocket-protocol request header. The handler module interface is currently undocumented and must be set to `gun_ws_h`. + + - `:compress` - Whether to enable permessage-deflate compression. + This does not guarantee that compression will be used as it is the server + that ultimately decides. Defaults to false. + + - `:protocols` - A non-empty list enables Websocket protocol negotiation. + The list of protocols will be sent in the sec-websocket-protocol request header. + The handler module interface is currently undocumented and must be set to `gun_ws_h`. """ @behaviour Tesla.Adapter alias Tesla.Multipart diff --git a/lib/tesla/adapter/hackney.ex b/lib/tesla/adapter/hackney.ex index 657bb76c..6a1a4ed7 100644 --- a/lib/tesla/adapter/hackney.ex +++ b/lib/tesla/adapter/hackney.ex @@ -11,7 +11,7 @@ if Code.ensure_loaded?(:hackney) do mix deps.compile tesla ``` - ## Example usage + ## Examples ``` # set globally in config/config.exs diff --git a/lib/tesla/adapter/ibrowse.ex b/lib/tesla/adapter/ibrowse.ex index f637fabc..b0174a0d 100644 --- a/lib/tesla/adapter/ibrowse.ex +++ b/lib/tesla/adapter/ibrowse.ex @@ -11,7 +11,7 @@ if Code.ensure_loaded?(:ibrowse) do mix deps.compile tesla ``` - ## Example usage + ## Examples ``` # set globally in config/config.exs diff --git a/lib/tesla/adapter/mint.ex b/lib/tesla/adapter/mint.ex index fb220963..d5889f5a 100644 --- a/lib/tesla/adapter/mint.ex +++ b/lib/tesla/adapter/mint.ex @@ -3,7 +3,7 @@ if Code.ensure_loaded?(Mint.HTTP) do @moduledoc """ Adapter for [mint](https://github.com/elixir-mint/mint). - Caution: The minimum supported Elixir version for mint is 1.5.0 + **NOTE:** The minimum supported Elixir version for mint is 1.5.0 Remember to add `{:mint, "~> 1.0"}` and `{:castore, "~> 0.1"}` to dependencies. Also, you need to recompile tesla after adding `:mint` dependency: @@ -13,7 +13,7 @@ if Code.ensure_loaded?(Mint.HTTP) do mix deps.compile tesla ``` - ## Example usage + ## Examples ``` # set globally in config/config.exs diff --git a/lib/tesla/builder.ex b/lib/tesla/builder.ex index e339a309..a5f179af 100644 --- a/lib/tesla/builder.ex +++ b/lib/tesla/builder.ex @@ -30,7 +30,7 @@ defmodule Tesla.Builder do ## Options - - `:method` - the request method, one of [:head, :get, :delete, :trace, :options, :post, :put, :patch] + - `:method` - the request method, one of [`:head`, `:get`, `:delete`, `:trace`, `:options`, `:post`, `:put`, `:patch`] - `:url` - either full url e.g. "http://example.com/some/path" or just "/some/path" if using `Tesla.Middleware.BaseUrl` - `:query` - a keyword list of query params, e.g. `[page: 1, per_page: 100]` - `:headers` - a keyworld list of headers, e.g. `[{"content-type", "text/plain"}]` diff --git a/lib/tesla/client.ex b/lib/tesla/client.ex index 023d3bf3..208aa632 100644 --- a/lib/tesla/client.ex +++ b/lib/tesla/client.ex @@ -16,7 +16,7 @@ defmodule Tesla.Client do Returns the client's adapter in the same form it was provided. This can be used to copy an adapter from one client to another. - ## Example + ## Examples iex> client = Tesla.client([], {Tesla.Adapter.Hackney, [recv_timeout: 30_000]}) iex> Tesla.Client.adapter(client) @@ -31,7 +31,7 @@ defmodule Tesla.Client do Returns the client's middleware in the same form it was provided. This can be used to copy middleware from one client to another. - ## Example + ## Examples iex> middleware = [Tesla.Middleware.JSON, {Tesla.Middleware.BaseUrl, "https://api.github.com"}] iex> client = Tesla.client(middleware) diff --git a/lib/tesla/middleware/basic_auth.ex b/lib/tesla/middleware/basic_auth.ex index 8623069d..478e412a 100644 --- a/lib/tesla/middleware/basic_auth.ex +++ b/lib/tesla/middleware/basic_auth.ex @@ -4,7 +4,7 @@ defmodule Tesla.Middleware.BasicAuth do [Wiki on the topic](https://en.wikipedia.org/wiki/Basic_access_authentication) - ## Example + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/compression.ex b/lib/tesla/middleware/compression.ex index b9bb2049..b1577340 100644 --- a/lib/tesla/middleware/compression.ex +++ b/lib/tesla/middleware/compression.ex @@ -2,9 +2,9 @@ defmodule Tesla.Middleware.Compression do @moduledoc """ Compress requests and decompress responses. - Supports "gzip" and "deflate" encodings using erlang's built-in `:zlib` module. + Supports "gzip" and "deflate" encodings using Erlang's built-in `:zlib` module. - ## Example usage + ## Examples ``` defmodule MyClient do @@ -57,7 +57,7 @@ defmodule Tesla.Middleware.Compression do It is used by `Tesla.Middleware.DecompressResponse`. """ def decompress({:ok, env}), do: {:ok, decompress(env)} - def decompress({:error, reasonn}), do: {:error, reasonn} + def decompress({:error, reason}), do: {:error, reason} def decompress(env) do env diff --git a/lib/tesla/middleware/core.ex b/lib/tesla/middleware/core.ex index bae90694..897a9709 100644 --- a/lib/tesla/middleware/core.ex +++ b/lib/tesla/middleware/core.ex @@ -2,10 +2,10 @@ defmodule Tesla.Middleware.BaseUrl do @moduledoc """ Set base URL for all requests. - The base URL will be prepended to request path/url only + The base URL will be prepended to request path/URL only if it does not include http(s). - ## Example usage + ## Examples ``` defmodule MyClient do @@ -55,7 +55,7 @@ defmodule Tesla.Middleware.Headers do @moduledoc """ Set default headers for all requests - ## Example usage + ## Examples ``` defmodule Myclient do @@ -80,7 +80,7 @@ defmodule Tesla.Middleware.Query do @moduledoc """ Set default query params for all requests - ## Example usage + ## Examples ``` defmodule Myclient do @@ -111,7 +111,7 @@ defmodule Tesla.Middleware.Opts do @moduledoc """ Set default opts for all requests. - ## Example usage + ## Examples ``` defmodule Myclient do diff --git a/lib/tesla/middleware/decode_rels.ex b/lib/tesla/middleware/decode_rels.ex index 5311fbb2..a5404134 100644 --- a/lib/tesla/middleware/decode_rels.ex +++ b/lib/tesla/middleware/decode_rels.ex @@ -2,7 +2,7 @@ defmodule Tesla.Middleware.DecodeRels do @moduledoc """ Decode `Link` Hypermedia HTTP header into `opts[:rels]` field in response. - ## Example usage + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/digest_auth.ex b/lib/tesla/middleware/digest_auth.ex index e4ecaa90..b26a8875 100644 --- a/lib/tesla/middleware/digest_auth.ex +++ b/lib/tesla/middleware/digest_auth.ex @@ -1,13 +1,13 @@ defmodule Tesla.Middleware.DigestAuth do @moduledoc """ - Digest access authentication middleware + Digest access authentication middleware. [Wiki on the topic](https://en.wikipedia.org/wiki/Digest_access_authentication) **NOTE**: Currently the implementation is incomplete and works only for MD5 algorithm - and auth qop. + and auth "quality of protection" (qop). - ## Example + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/follow_redirects.ex b/lib/tesla/middleware/follow_redirects.ex index 61b9d06e..a9d75273 100644 --- a/lib/tesla/middleware/follow_redirects.ex +++ b/lib/tesla/middleware/follow_redirects.ex @@ -1,8 +1,8 @@ defmodule Tesla.Middleware.FollowRedirects do @moduledoc """ - Follow 3xx redirects + Follow HTTP 3xx redirects. - ## Example + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/form_urlencoded.ex b/lib/tesla/middleware/form_urlencoded.ex index 65b6ac96..196ae68b 100644 --- a/lib/tesla/middleware/form_urlencoded.ex +++ b/lib/tesla/middleware/form_urlencoded.ex @@ -9,7 +9,7 @@ defmodule Tesla.Middleware.FormUrlencoded do is `application/x-www-form-urlencoded`, so `"foo=bar"` becomes `%{"foo" => "bar"}`. - ## Example usage + ## Examples ``` defmodule Myclient do diff --git a/lib/tesla/middleware/fuse.ex b/lib/tesla/middleware/fuse.ex index c68a8a44..9f6eafb2 100644 --- a/lib/tesla/middleware/fuse.ex +++ b/lib/tesla/middleware/fuse.ex @@ -1,7 +1,7 @@ if Code.ensure_loaded?(:fuse) do defmodule Tesla.Middleware.Fuse do @moduledoc """ - Circuit Breaker middleware using [fuse](https://github.com/jlouis/fuse) + Circuit Breaker middleware using [fuse](https://github.com/jlouis/fuse). Remember to add `{:fuse, "~> 2.4"}` to dependencies (and `:fuse` to applications in `mix.exs`) Also, you need to recompile tesla after adding `:fuse` dependency: @@ -11,7 +11,7 @@ if Code.ensure_loaded?(:fuse) do mix deps.compile tesla ``` - ## Example usage + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/json.ex b/lib/tesla/middleware/json.ex index fa7b109b..81ad1edb 100644 --- a/lib/tesla/middleware/json.ex +++ b/lib/tesla/middleware/json.ex @@ -2,17 +2,17 @@ defmodule Tesla.Middleware.JSON do @moduledoc """ Encode requests and decode responses as JSON. - This middleware requires [jason](https://hex.pm/packages/jason) (or other engine) as dependency. + This middleware requires [Jason](https://hex.pm/packages/jason) (or other engine) as dependency. - Remember to add `{:jason, ">= 1.0"}` to dependencies - Also, you need to recompile tesla after adding `:jason` dependency: + Remember to add `{:jason, ">= 1.0"}` to dependencies. + Also, you need to recompile Tesla after adding `:jason` dependency: ``` mix deps.clean tesla mix deps.compile tesla ``` - ## Example usage + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/keep_request.ex b/lib/tesla/middleware/keep_request.ex index a119ade3..84a2494f 100644 --- a/lib/tesla/middleware/keep_request.ex +++ b/lib/tesla/middleware/keep_request.ex @@ -1,8 +1,8 @@ defmodule Tesla.Middleware.KeepRequest do @moduledoc """ - Store request body, headers and path into `%Tesla.Env{}` opts. + Store request url ,body and headers into `:opts`. - ## Example + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/logger.ex b/lib/tesla/middleware/logger.ex index c0c55f8b..95dab3b5 100644 --- a/lib/tesla/middleware/logger.ex +++ b/lib/tesla/middleware/logger.ex @@ -40,9 +40,10 @@ defmodule Tesla.Middleware.Logger do @moduledoc """ Log requests using Elixir's Logger. - With the default settings it logs request method, url, response status and time taken in milliseconds. + With the default settings it logs request method, URL, response status, and time taken in milliseconds. + + ## Examples - ## Example usage ``` defmodule MyClient do use Tesla @@ -52,6 +53,7 @@ defmodule Tesla.Middleware.Logger do ``` ## Options + - `:log_level` - custom function for calculating log level (see below) - `:filter_headers` - sanitizes sensitive headers before logging in debug mode (see below) - `:debug` - show detailed request/response logging @@ -74,6 +76,7 @@ defmodule Tesla.Middleware.Logger do ## Custom log levels By default, the following log levels will be used: + - `:error` - for errors, 5xx and 4xx responses - `:warn` - for 3xx responses - `:info` - for 2xx responses diff --git a/lib/tesla/middleware/method_override.ex b/lib/tesla/middleware/method_override.ex index e351b4ed..dc65044b 100644 --- a/lib/tesla/middleware/method_override.ex +++ b/lib/tesla/middleware/method_override.ex @@ -1,11 +1,11 @@ defmodule Tesla.Middleware.MethodOverride do @moduledoc """ - Middleware that adds X-Http-Method-Override header with original request + Middleware that adds `X-HTTP-Method-Override` header with original request method and sends the request as post. - Useful when there's an issue with sending non-post request. + Useful when there's an issue with sending non-POST request. - ## Example + ## Examples ``` defmodule MyClient do @@ -17,8 +17,7 @@ defmodule Tesla.Middleware.MethodOverride do ## Options - - `:override` - list of http methods that should be overriden, - everything except `:get` and `:post` if not specified + - `:override` - list of HTTP methods that should be overriden, everything except `:get` and `:post` if not specified """ @behaviour Tesla.Middleware diff --git a/lib/tesla/middleware/path_params.ex b/lib/tesla/middleware/path_params.ex index 8b27dbb1..81dc4c21 100644 --- a/lib/tesla/middleware/path_params.ex +++ b/lib/tesla/middleware/path_params.ex @@ -4,7 +4,7 @@ defmodule Tesla.Middleware.PathParams do Useful when logging or reporting metric per URL. - ## Example usage + ## Examples ``` defmodule MyClient do diff --git a/lib/tesla/middleware/retry.ex b/lib/tesla/middleware/retry.ex index 455cf93c..bbc27431 100644 --- a/lib/tesla/middleware/retry.ex +++ b/lib/tesla/middleware/retry.ex @@ -1,25 +1,25 @@ defmodule Tesla.Middleware.Retry do @moduledoc """ - Retry using exponential backoff and full jitter. This middleware only retries in the - case of connection errors (`nxdomain`, `connrefused` etc). Application error - checking for retry can be customized through `:should_retry` option by - providing a function in returning a boolean. + Retry using exponential backoff and full jitter. + + By defaults, this middleware only retries in the case of connection errors (`nxdomain`, `connrefused`, etc). + Application error checking for retry can be customized through `:should_retry` option. ## Backoff algorithm The backoff algorithm optimizes for tight bounds on completing a request successfully. It does this by first calculating an exponential backoff factor based on the - number of retries that have been performed. It then multiplies this factor against the - base delay. The total maximum delay is found by taking the minimum of either the calculated delay - or the maximum delay specified. This creates an upper bound on the maximum delay - we can see. + number of retries that have been performed. It then multiplies this factor against + the base delay. The total maximum delay is found by taking the minimum of either + the calculated delay or the maximum delay specified. This creates an upper bound + on the maximum delay we can see. - In order to find the actual delay value we apply additive noise which is proportional to the - current desired delay. This ensures that the actual delay is kept within the expected order - of magnitude, while still having some randomness, which ensures that our retried requests - don't "harmonize" making it harder for the downstream service to heal. + In order to find the actual delay value we apply additive noise which is proportional + to the current desired delay. This ensures that the actual delay is kept within + the expected order of magnitude, while still having some randomness, which ensures + that our retried requests don't "harmonize" making it harder for the downstream service to heal. - ## Example + ## Examples ``` defmodule MyClient do @@ -43,7 +43,8 @@ defmodule Tesla.Middleware.Retry do - `:max_retries` - maximum number of retries (non-negative integer, defaults to 5) - `:max_delay` - maximum delay in milliseconds (positive integer, defaults to 5000) - `:should_retry` - function to determine if request should be retried - - `:jitter_factor` - additive noise proportionality constant (float between 0 and 1, defaults to 0.2) + - `:jitter_factor` - additive noise proportionality constant + (float between 0 and 1, defaults to 0.2) """ # Not necessary in Elixir 1.10+ @@ -100,8 +101,8 @@ defmodule Tesla.Middleware.Retry do factor = Bitwise.bsl(1, attempt) max_sleep = min(cap, base * factor) - # This ensures that the delay's order of magnitude is kept intact, - # while still having some jitter. Generates a value x where 1-jitter_factor <= x <= 1 + jitter_factor + # This ensures that the delay's order of magnitude is kept intact, while still having some jitter. + # Generates a value x where 1-jitter_factor <= x <= 1 + jitter_factor jitter = 1 + 2 * jitter_factor * :rand.uniform() - jitter_factor # The actual delay is in the range max_sleep * (1 - jitter_factor), max_sleep * (1 + jitter_factor) diff --git a/lib/tesla/middleware/telemetry.ex b/lib/tesla/middleware/telemetry.ex index d5e4082c..1e01cc75 100644 --- a/lib/tesla/middleware/telemetry.ex +++ b/lib/tesla/middleware/telemetry.ex @@ -3,7 +3,7 @@ if Code.ensure_loaded?(:telemetry) do @moduledoc """ Emits events using the `:telemetry` library to expose instrumentation. - ## Base usage + ## Examples ``` defmodule MyClient do @@ -17,7 +17,33 @@ if Code.ensure_loaded?(:telemetry) do end) ``` - ### URL event scoping with `Tesla.Middleware.PathParams` and `Tesla.Middleware.KeepRequest` + ## Options + + - `:metadata` - additional metadata passed to telemetry events + + ## Telemetry Events + + * `[:tesla, :request, :start]` - emitted at the beginning of the request. + * Measurement: `%{system_time: System.system_time()}` + * Metadata: `%{env: Tesla.Env.t()}` + + * `[:tesla, :request, :stop]` - emitted at the end of the request. + * Measurement: `%{duration: native_time}` + * Metadata: `%{env: Tesla.Env.t()} | %{env: Tesla.Env.t(), error: term()}` + + * `[:tesla, :request, :exception]` - emitted when an exception has been raised. + * Measurement: `%{duration: native_time}` + * Metadata: `%{kind: Exception.kind(), reason: term(), stacktrace: Exception.stacktrace()}` + + ## Legacy Telemetry Events + + * `[:tesla, :request]` - This event is emitted for backwards compatibility only and should be considered deprecated. + This event can be disabled by setting `config :tesla, Tesla.Middleware.Telemetry, disable_legacy_event: true` in your config. + Be sure to run `mix deps.compile --force tesla` after changing this setting to ensure the change is picked up. + + Please check the [telemetry](https://hexdocs.pm/telemetry/) for the further usage. + + ## URL event scoping with `Tesla.Middleware.PathParams` and `Tesla.Middleware.KeepRequest` Sometimes, it is useful to have access to a template url (i.e. `"/users/:user_id"`) for grouping Telemetry events. For such cases, a combination of the `Tesla.Middleware.PathParams`, @@ -42,31 +68,6 @@ if Code.ensure_loaded?(:telemetry) do path_params_resolved_url = meta.env.url end) ``` - - ## Options - - - `:metadata` - additional metadata passed to telemetry events - - ## Telemetry Events - - * `[:tesla, :request, :start]` - emitted at the beginning of the request. - * Measurement: `%{system_time: System.system_time()}` - * Metadata: `%{env: Tesla.Env.t()}` - - * `[:tesla, :request, :stop]` - emitted at the end of the request. - * Measurement: `%{duration: native_time}` - * Metadata: `%{env: Tesla.Env.t()} | %{env: Tesla.Env.t(), error: term()}` - - * `[:tesla, :request, :exception]` - emitted when an exception has been raised. - * Measurement: `%{duration: native_time}` - * Metadata: `%{kind: Exception.kind(), reason: term(), stacktrace: Exception.stacktrace()}` - - ## Legacy Telemetry Events - - * `[:tesla, :request]` - This event is emitted for backwards compatibility only and should be considered deprecated. - This event can be disabled by setting `config :tesla, Tesla.Middleware.Telemetry, disable_legacy_event: true` in your config. Be sure to run `mix deps.compile --force tesla` after changing this setting to ensure the change is picked up. - - Please check the [telemetry](https://hexdocs.pm/telemetry/) for the further usage. """ @disable_legacy_event Application.get_env(:tesla, Tesla.Middleware.Telemetry, diff --git a/lib/tesla/middleware/timeout.ex b/lib/tesla/middleware/timeout.ex index bc56d812..10a8758d 100644 --- a/lib/tesla/middleware/timeout.ex +++ b/lib/tesla/middleware/timeout.ex @@ -1,8 +1,8 @@ defmodule Tesla.Middleware.Timeout do @moduledoc """ - Timeout http request after X milliseconds. + Timeout HTTP request after X milliseconds. - ## Example + ## Examples ``` defmodule MyClient do @@ -14,7 +14,7 @@ defmodule Tesla.Middleware.Timeout do ## Options - - `:timeout` - number of milliseconds a request is allowed to take (defaults to 1000) + - `:timeout` - number of milliseconds a request is allowed to take (defaults to `1000`) """ @behaviour Tesla.Middleware diff --git a/lib/tesla/mock.ex b/lib/tesla/mock.ex index e89d761e..9af16e47 100644 --- a/lib/tesla/mock.ex +++ b/lib/tesla/mock.ex @@ -12,7 +12,7 @@ defmodule Tesla.Mock do config :tesla, MyClient, adapter: Tesla.Mock ``` - ## Example test + ## Examples ``` defmodule MyAppTest do @@ -147,7 +147,7 @@ defmodule Tesla.Mock do @type response_opts :: [{response_opt, any}] @doc """ - Return json response. + Return JSON response. Example diff --git a/lib/tesla/multipart.ex b/lib/tesla/multipart.ex index c186eef9..0f6c041d 100644 --- a/lib/tesla/multipart.ex +++ b/lib/tesla/multipart.ex @@ -2,7 +2,7 @@ defmodule Tesla.Multipart do @moduledoc """ Multipart functionality. - ## Example + ## Examples ``` mp = diff --git a/mix.exs b/mix.exs index d57676b6..5ead75f5 100644 --- a/mix.exs +++ b/mix.exs @@ -1,6 +1,7 @@ defmodule Tesla.Mixfile do use Mix.Project + @source_url "https://github.com/teamon/tesla" @version "1.4.0" def project do @@ -9,7 +10,6 @@ defmodule Tesla.Mixfile do version: @version, description: description(), package: package(), - source_url: "https://github.com/teamon/tesla", elixir: "~> 1.7", elixirc_paths: elixirc_paths(Mix.env()), deps: deps(), @@ -73,7 +73,7 @@ defmodule Tesla.Mixfile do # testing & docs {:excoveralls, "~> 0.8", only: :test}, {:httparrot, "~> 1.2", only: :test}, - {:ex_doc, "~> 0.21", only: :dev}, + {:ex_doc, "~> 0.21", only: :dev, runtime: false}, {:mix_test_watch, "~> 1.0", only: :dev}, {:dialyxir, "~> 1.0", only: [:dev, :test], runtime: false}, {:inch_ex, "~> 2.0", only: :docs} @@ -83,6 +83,7 @@ defmodule Tesla.Mixfile do defp docs do [ main: "readme", + source_url: @source_url, source_ref: "v#{@version}", extras: ["README.md", "LICENSE"], groups_for_modules: [