Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Requests | 50,295 | 152,228 | 51,242 | 5 days ago | 151 | May 22, 2023 | 261 | apache-2.0 | Python | |
A simple, yet elegant, HTTP library. | ||||||||||
Node Fetch | 8,474 | 219,668 | 33,659 | 7 days ago | 94 | July 25, 2023 | 190 | mit | JavaScript | |
A light-weight module that brings the Fetch API to Node.js | ||||||||||
Werkzeug | 6,430 | 67,722 | 1,832 | 17 hours ago | 91 | June 08, 2023 | 4 | bsd-3-clause | Python | |
The comprehensive WSGI web application library. | ||||||||||
Xutils3 | 5,914 | 905 | 1 | 2 years ago | 87 | June 18, 2020 | 26 | other | Java | |
Android orm, bitmap, http, view inject... | ||||||||||
Evercookie | 3,798 | 6 years ago | February 22, 2021 | 53 | JavaScript | |||||
Produces persistent, respawning "super" cookies in a browser, abusing over a dozen techniques. Its goal is to identify users after they've removed standard cookies and other privacy data such as Flash cookies (LSOs), HTML5 storage, SilverLight storage, and others. | ||||||||||
Req | 3,613 | 42 | 316 | 6 days ago | 181 | August 12, 2023 | 19 | mit | Go | |
Simple Go HTTP client with Black Magic | ||||||||||
Rxeasyhttp | 3,022 | 2 years ago | 29 | apache-2.0 | Java | |||||
本库是一款基于RxJava2+Retrofit2实现简单易用的网络请求框架,结合android平台特性的网络封装库,采用api链式调用一点到底,集成cookie管理,多种缓存模式,极简https配置,上传下载进度显示,请求错误自动重试,请求携带token、时间戳、签名sign动态配置,自动登录成功后请求重发功能,3种层次的参数设置默认全局局部,默认标准ApiResult同时可以支持自定义的数据结构,已经能满足现在的大部分网络请求。 | ||||||||||
Auth Boss | 2,843 | 7 years ago | ||||||||
🔒 Become an Auth Boss. Learn about different authentication methodologies on the web. | ||||||||||
Must Know About Frontend | 2,547 | 4 months ago | ||||||||
:mortar_board: 취준생이라면 알면 좋을 프론트엔드 관련 지식들 | ||||||||||
Httpoison | 2,168 | 4,019 | 1,670 | 2 months ago | 49 | March 10, 2023 | 30 | mit | Elixir | |
Yet Another HTTP client for Elixir powered by hackney |
HTTP client for Elixir, based on HTTPotion (documentation).
First, add HTTPoison to your mix.exs
dependencies:
def deps do
[
{:httpoison, "~> 2.0"}
]
end
and run $ mix deps.get
. Add :httpoison
to your applications list if your Elixir version is 1.3 or lower:
def application do
[applications: [:httpoison]]
end
The main change that caused a major version is that ssl
option now merges with the default options where previously it would override the ssl options. The new option ssl_override
was added to allow people to keep the previous behaviour but it's more explicit now.
defp default_ssl_options() do
[
{:versions, [:"tlsv1.2", :"tlsv1.3"]},
{:verify, :verify_peer},
{:cacertfile, :certifi.cacertfile()},
{:depth, 10},
{:customize_hostname_check,
[
match_fun: :public_key.pkix_verify_hostname_match_fun(:https)
]}
]
end
More context here: https://github.com/edgurgel/httpoison/pull/466
iex> HTTPoison.start
iex> HTTPoison.get! "https://postman-echo.com/get"
%HTTPoison.Response{
status_code: 200,
body: "{\n \"args\": {},\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"x-amzn-trace-id\": \"Root=1-644624fb-769bca0458e739dc07f6b630\",\n \"user-agent\": \"hackney/1.18.1\"\n },\n \"url\": \"https://postman-echo.com/get\"\n}",
headers: [ ... ]
}
iex> HTTPoison.get! "http://localhost:1"
** (HTTPoison.Error) :econnrefused
iex> HTTPoison.get "http://localhost:1"
{:error, %HTTPoison.Error{id: nil, reason: :econnrefused}}
iex> HTTPoison.post "https://postman-echo.com/post", "{\"body\": \"test\"}", [{"Content-Type", "application/json"}]
{:ok,
%HTTPoison.Response{
status_code: 200,
body: "{\n \"args\": {},\n \"data\": {\n \"body\": \"test\"\n },\n \"files\": {},\n \"form\": {},\n \"headers\": {\n \"x-forwarded-proto\": \"https\",\n \"x-forwarded-port\": \"443\",\n \"host\": \"postman-echo.com\",\n \"x-amzn-trace-id\": \"Root=1-6446255e-703101813ec2e395202ab494\",\n \"content-length\": \"16\",\n \"user-agent\": \"hackney/1.18.1\",\n \"content-type\": \"application/json\"\n },\n \"json\": {\n \"body\": \"test\"\n },\n \"url\": \"https://postman-echo.com/post\"\n}",
headers: [ ... ]
}}
You can also easily pattern match on the HTTPoison.Response
struct:
case HTTPoison.get(url) do
{:ok, %HTTPoison.Response{status_code: 200, body: body}} ->
IO.puts body
{:ok, %HTTPoison.Response{status_code: 404}} ->
IO.puts "Not found :("
{:error, %HTTPoison.Error{reason: reason}} ->
IO.inspect reason
end
Here is the list of all possible error reasons.
There are a number of supported options(not to be confused with the HTTP options method), documented here, that can be added to your request. The example below shows the use of the :ssl
and :recv_timeout
options for a post request to an api that requires a bearer token. The :ssl
option allows you to set options accepted by the Erlang SSL module, and :recv_timeout
sets a timeout on receiving a response, the default is 5000ms.
token = "some_token_from_another_request"
url = "https://example.com/api/endpoint_that_needs_a_bearer_token"
headers = ["Authorization": "Bearer #{token}", "Accept": "Application/json; Charset=utf-8"]
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]
{:ok, response} = HTTPoison.get(url, headers, options)
And the example below shows the use of the :ssl
options for a post request to an api that requires a client certification.
url = "https://example.org/api/endpoint_that_needs_client_cert"
options = [ssl: [certfile: "certs/client.crt"]]
{:ok, response} = HTTPoison.post(url, [], options)
HTTPoison.Base
You can also use the HTTPoison.Base
module in your modules in order to make
cool API clients or something. The following example wraps HTTPoison.Base
in
order to build a client for the GitHub API
(Poison is used for JSON decoding):
defmodule GitHub do
use HTTPoison.Base
@expected_fields ~w(
login id avatar_url gravatar_id url html_url followers_url
following_url gists_url starred_url subscriptions_url
organizations_url repos_url events_url received_events_url type
site_admin name company blog location email hireable bio
public_repos public_gists followers following created_at updated_at
)
def process_request_url(url) do
"https://api.github.com" <> url
end
def process_response_body(body) do
body
|> Poison.decode!
|> Map.take(@expected_fields)
|> Enum.map(fn({k, v}) -> {String.to_atom(k), v} end)
end
end
iex> GitHub.start
iex> GitHub.get!("/users/myfreeweb").body[:public_repos]
37
It's possible to extend the functions listed below:
def process_request_body(body), do: body
def process_request_headers(headers) when is_map(headers) do
Enum.into(headers, [])
end
def process_request_headers(headers), do: headers
def process_request_options(options), do: options
def process_request_url(url), do: url
def process_response_body(body), do: body
def process_response_chunk(chunk), do: chunk
def process_response_headers(headers), do: headers
def process_response_status_code(status_code), do: status_code
HTTPoison now comes with async requests!
iex> HTTPoison.get! "https://github.com/", %{}, stream_to: self
%HTTPoison.AsyncResponse{id: #Reference<0.0.0.1654>}
iex> flush
%HTTPoison.AsyncStatus{code: 200, id: #Reference<0.0.0.1654>}
%HTTPoison.AsyncHeaders{headers: %{"Connection" => "keep-alive", ...}, id: #Reference<0.0.0.1654>}
%HTTPoison.AsyncChunk{chunk: "<!DOCTYPE html>...", id: #Reference<0.0.0.1654>}
%HTTPoison.AsyncEnd{id: #Reference<0.0.0.1654>}
:ok
Warning: this option can flood a receiver in messages.
If a server may send very large messages the async: :once
option should be used.
This will send only a single chunk at a time the receiver can call HTTPoison.stream_next/1
to indicate ability to process more chunks.
HTTPoison allows you to send cookies:
iex> HTTPoison.get!("https://postman-echo.com/cookies", %{}, hackney: [cookie: ["session=a933ec1dd923b874e691; logged_in=true"]])
%HTTPoison.Response{
status_code: 200,
body: "{\n \"cookies\": {\n \"session\": \"a933ec1dd923b874e691\",\n \"logged_in\": \"true\"\n }\n}",
headers: [ ... ]
}
You can also receive cookies from the server by reading the "set-cookie"
headers in the response:
iex(1)> response = HTTPoison.get!("https://postman-echo.com/cookies/set?foo=1")
iex(2)> cookies = Enum.filter(response.headers, fn
...(2)> {key, _} -> String.match?(key, ~r/\Aset-cookie\z/i)
...(2)> end)
[ {"set-cookie", "foo=1; Path=/"}, ...]
You can see more usage examples in the test files (located in the
test/
) directory.
Normally hackney opens and closes connections on demand, but it also creates a default pool of connections which are reused for requests to the same host. If the connection and host support keepalive, the connection is kept open until explicitly closed.
To use the default pool, you can just declare it as an option:
HTTPoison.get("httpbin.org/get", [], hackney: [pool: :default])
It is possible to use different pools for different purposes when a more fine grained allocation of resources is necessary.
The easiest way is to just pass the name of the pool, and hackney will create it if it doesn't exist. Pools are independent from each other (they won't compete for connections) and are created with the default configuration.
HTTPoison.get("httpbin.org/get", [], hackney: [pool: :first_pool])
HTTPoison.get("httpbin.org/get", [], hackney: [pool: :second_pool])
If you want to use different configuration options you can create a pool manually when your app starts with :hackney_pool.start_pool/2
.
:ok = :hackney_pool.start_pool(:first_pool, [timeout: 15000, max_connections: 100])
From the already linked hackney's readme:
timeout
is the time we keep the connection alive in the pool,max_connections
is the number of connections maintained in the pool. Each connection in a pool is monitored and closed connections are removed automatically.
If you don't want to use a pool for a single http request, you can do it by passing an option:
HTTPoison.get("httpbin.org/get", [], hackney: [pool: false])
If you want to disable the usage of the pool for every request you can do it by adding this to your environment configuration:
config :hackney, use_default_pool: false
You can find a little explanation here hackney's readme.
A third option is to add the pool as part of your supervision tree:
children = [
:hackney_pool.child_spec(:first_pool, [timeout: 15000, max_connections: 100])
]
Add that to the application supervisor and first_pool
will be available to be used by HTTPoison/hackney.
HTTPoison supports making multipart
requests. E.g. with a local file:
HTTPoison.post("https://myurl.php", {:multipart, [{:file, "test.txt", {"form-data", [{"name", "mytest"}, {"filename", "test.txt"}]}, []}]})
Sometimes you may already have the file contents in memory and want to upload it elsewhere. A common example is fetching the file from a service like S3 and uploading it somewhere else. There is no need to persist the file locally, you can do the below:
binary_file_content = "Something you fetched and now have it in memory"
token = "some_token_from_another_request"
headers = [{"Authorization", "Bearer #{token}"}, {"Content-Type", "multipart/form-data"}]
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]
HTTPoison.request(
:post,
"https://myurl.com",
{:multipart,
[{"file", binary_file_content, {"form-data", [name: "file", filename: "a_file_name.txt"]}, []}]},
headers,
options
)
Further examples of multipart
requests can be found in the issues (e.g.: here and here).
For more complex queries regarding multipart requests, you should follow the hackney docs for the multipart
API.
HTTPoison supports parsing multipart
responses. E.g.:
iex(1)> response = %HTTPoison.Response{
...(1)> body: "--123\r\nContent-type: application/json\r\n\r\n{\"1\": \"first\"}\r\n--123\r\nContent-type: application/json\r\n\r\n{\"2\": \"second\"}\r\n--123--\r\n",
...(1)> headers: [{"Content-Type", "multipart/mixed;boundary=123"}],
...(1)> request_url: "http://localhost",
...(1)> status_code: 200
...(1)> }
%HTTPoison.Response{
body: "--123\r\nContent-type: application/json\r\n\r\n{\"1\": \"first\"}\r\n--123\r\nContent-type: application/json\r\n\r\n{\"2\": \"second\"}\r\n--123--\r\n",
headers: [{"Content-Type", "multipart/mixed;boundary=123"}],
request_url: "http://localhost",
status_code: 200
}
iex(2)> HTTPoison.Handlers.Multipart.decode_body(response)
[
{[{"Content-Type", "application/json"}], "{\"1\": \"first\"}"},
{[{"Content-Type", "application/json"}], "{\"2\": \"second\"}"}
]
For more complex queries regarding multipart response parsing, you should follow the hackney docs for the hackney_multipart
API.
If you're running on top of hackney (which you probably are) there's a handy way to get detailed request logging:
:hackney_trace.enable(:max, :io)
Just throw this in your code before your HTTPoison call and you'll get low-level log output.
Copyright 2013-present Eduardo Gurgel <[email protected]>
This work is free. You can redistribute it and/or modify it under the
terms of the MIT License. See the LICENSE file for more details.