檢視原始碼 URI (Elixir v1.16.2)
處理 URI 的公用程式。
此模組提供用於處理 URI 的函式(例如,剖析 URI 或編碼查詢字串)。此模組中的函式根據 RFC 3986 實作。
摘要
函式
URI 結構。
將 path
附加至指定的 uri
。
將 query
附加至指定的 uri
。
檢查 character
是否為 URI 中的保留字元。
檢查 character
是否允許在 URI 中不經跳脫。
檢查 character
是否為 URI 中的非保留字元。
百分比跳脫 URI。
將 query
解碼成一個映射。
將 string
解碼為「x-www-form-urlencoded」。
傳回指定 scheme
的預設埠號。
註冊指定 scheme
的預設 port
。
百分比編碼 string
中所有需要跳脫的字元。
使用 編碼
將 可列舉
編碼成查詢字串。
將 字串
編碼為「x-www-form-urlencoded」。
合併兩個 URI。
從 URI 或字串建立新的 URI 結構。
將 URI 解析成其組成部分,而不會進一步驗證。
傳回一個串流,其中包含代表給定 查詢
中的鍵值對的兩個元素元組。
傳回給定 URI 結構 的字串表示形式。
類型
函數
URI 結構。
定義這些欄位以符合下列 URI 表示形式(欄位名稱在括號中)
[scheme]://[userinfo]@[host]:[port][path]?[query]#[fragment]
請注意,權限
欄位已過時。 parse/1
仍會填入它以維持向後相容性,但您通常應避免設定或取得它。
將 path
附加至指定的 uri
。
路徑必須以 /
開頭,且不能包含其他 URL 組成部分,例如片段或查詢字串。此函數進一步假設路徑有效,且不包含查詢字串或片段部分。
範例
iex> URI.append_path(URI.parse("http://example.com/foo/?x=1"), "/my-path") |> URI.to_string()
"http://example.com/foo/my-path?x=1"
iex> URI.append_path(URI.parse("http://example.com"), "my-path")
** (ArgumentError) path must start with "/", got: "my-path"
將 query
附加至指定的 uri
。
給定的 查詢
沒有自動編碼,請使用 encode/2
或 encode_www_form/1
。
範例
iex> URI.append_query(URI.parse("http://example.com/"), "x=1") |> URI.to_string()
"http://example.com/?x=1"
iex> URI.append_query(URI.parse("http://example.com/?x=1"), "y=2") |> URI.to_string()
"http://example.com/?x=1&y=2"
iex> URI.append_query(URI.parse("http://example.com/?x=1"), "x=2") |> URI.to_string()
"http://example.com/?x=1&x=2"
檢查 character
是否為 URI 中的保留字元。
如 RFC 3986 第 2.2 節 所述,保留以下字元::
、/
、?
、#
、[
、]
、@
、!
、$
、&
、'
、(
、)
、*
、+
、,
、;
、=
範例
iex> URI.char_reserved?(?+)
true
檢查 character
是否允許在 URI 中不經跳脫。
這是 URI.encode/2
使用的預設值,其中 保留字元 和 非保留字元 都保持未跳脫。
範例
iex> URI.char_unescaped?(?{)
false
檢查 character
是否為 URI 中的非保留字元。
如 RFC 3986, 第 2.3 節 所述,下列字元為非保留字元
- 字母數字字元:
A-Z
、a-z
、0-9
~
,_
,-
,.
範例
iex> URI.char_unreserved?(?_)
true
百分比跳脫 URI。
範例
iex> URI.decode("https%3A%2F%2Felixir-lang.org")
"https://elixir.dev.org.tw"
@spec decode_query(binary(), %{optional(binary()) => binary()}, :rfc3986 | :www_form) :: %{ optional(binary()) => binary() }
將 query
解碼成一個映射。
給定一個格式為 key1=value1&key2=value2...
的查詢字串,此函式會將每個查詢字串中的金鑰值對插入給定的 map
中作為一個項目。結果 map 中的金鑰和值將是二進位。金鑰和值將會百分比解跳脫。
你可以指定下列 encoding
選項之一
:www_form
- (預設值,自 v1.12.0 起) 金鑰和值會根據decode_www_form/1
解碼。這是瀏覽器通常在查詢字串和表單資料上使用的格式。它會將「+」解碼為「 」。:rfc3986
- (自 v1.12.0 起) 金鑰和值會根據decode/1
解碼。結果與:www_form
相同,但會將「+」保留原樣,符合 RFC 3986。
編碼預設為 :www_form
以維持向後相容性。
如果你想手動迭代每個值,請使用 query_decoder/1
。
範例
iex> URI.decode_query("foo=1&bar=2")
%{"bar" => "2", "foo" => "1"}
iex> URI.decode_query("percent=oh+yes%21", %{"starting" => "map"})
%{"percent" => "oh yes!", "starting" => "map"}
iex> URI.decode_query("percent=oh+yes%21", %{}, :rfc3986)
%{"percent" => "oh+yes!"}
將 string
解碼為「x-www-form-urlencoded」。
請注意「x-www-form-urlencoded」未指定為 RFC 3986 的一部分。然而,這是瀏覽器編碼查詢字串和表單資料的常用格式。
範例
iex> URI.decode_www_form("%3Call+in%2F")
"<all in/"
@spec default_port(binary()) :: nil | non_neg_integer()
傳回指定 scheme
的預設埠號。
如果 URI
模組不知道該架構,此函式會傳回 nil
。任何架構的預設埠都可透過 default_port/2
全域設定。
範例
iex> URI.default_port("ftp")
21
iex> URI.default_port("ponzi")
nil
@spec default_port(binary(), non_neg_integer()) :: :ok
註冊指定 scheme
的預設 port
。
呼叫此函式後,default_port/1
會傳回 port
給定 scheme
。請注意,此函式會變更給定 scheme
的預設埠號,全域性地,表示對每個應用程式而言。
建議在應用程式的啟動回呼中呼叫此函式,以防您想要註冊新的 URI。
@spec encode(binary(), (byte() -> as_boolean(term()))) :: binary()
百分比編碼 string
中所有需要跳脫的字元。
預設情況下,此函式會對整個 URI 進行跳脫,因此它會跳脫所有不屬於 URI 規範的字元。保留字元(例如 :
和 /
)或未保留字元(例如字母和數字)不會被跳脫。
由於 URI 的不同元件需要不同的跳脫規則,因此此函式也接受 predicate
函式作為選用引數。如果傳遞,此函式會以 string
中的每個位元組作為引數呼叫,並在給定的位元組應保持原樣時傳回真值(任何值,除了 false
或 nil
),或在字元應被跳脫時傳回假值(false
或 nil
)。預設為 URI.char_unescaped?/1
。
如果您有興趣也跳脫保留字元,請參閱 encode_www_form/1
。
範例
iex> URI.encode("ftp://s-ite.tld/?value=put it+й")
"ftp://s-ite.tld/?value=put%20it+%D0%B9"
iex> URI.encode("a string", &(&1 != ?i))
"a str%69ng"
@spec encode_query(Enumerable.t(), :rfc3986 | :www_form) :: binary()
使用 編碼
將 可列舉
編碼成查詢字串。
採用可列舉為兩元素組元清單(例如,映射或關鍵字清單)的可列舉,並傳回 key1=value1&key2=value2...
形式的字串。
金鑰和值可以是任何實作 String.Chars
協定的項目,但清單例外,清單明確禁止。
您可以指定下列 encoding
策略之一
:www_form
- (預設,自 v1.12.0 起)金鑰和值會根據encode_www_form/1
以 URL 編碼。這是瀏覽器在查詢字串和表單資料上通常使用的格式。它將 " " 編碼為 "+”。:rfc3986
- (自 v1.12.0 起)與:www_form
相同,但它會根據 RFC 3986 將 " " 編碼為 "%20”。如果您在非瀏覽器情況下進行編碼,這是最佳選項,因為將空格編碼為 "+" 可能對 URI 解析器來說模稜兩可。這可能會無意間導致空格被解釋為實際的加號。
編碼預設為 :www_form
以維持向後相容性。
範例
iex> query = %{"foo" => 1, "bar" => 2}
iex> URI.encode_query(query)
"bar=2&foo=1"
iex> query = %{"key" => "value with spaces"}
iex> URI.encode_query(query)
"key=value+with+spaces"
iex> query = %{"key" => "value with spaces"}
iex> URI.encode_query(query, :rfc3986)
"key=value%20with%20spaces"
iex> URI.encode_query(%{key: [:a, :list]})
** (ArgumentError) encode_query/2 values cannot be lists, got: [:a, :list]
將 字串
編碼為「x-www-form-urlencoded」。
請注意「x-www-form-urlencoded」未指定為 RFC 3986 的一部分。然而,這是瀏覽器編碼查詢字串和表單資料的常用格式。
範例
iex> URI.encode_www_form("put: it+й")
"put%3A+it%2B%D0%B9"
合併兩個 URI。
此函數會根據 RFC 3986 第 5.2 節 將兩個 URI 合併。
範例
iex> URI.merge(URI.parse("http://google.com"), "/query") |> to_string()
"http://google.com/query"
iex> URI.merge("http://example.com", "http://google.com") |> to_string()
"http://google.com"
從 URI 或字串建立新的 URI 結構。
如果給定 %URI{}
結構,它會傳回 {:ok, uri}
。如果給定字串,它會解析並驗證該字串。如果字串有效,它會傳回 {:ok, uri}
,否則會傳回 {:error, part}
,其中包含 URI 的無效部分。如要解析 URI 而無需進一步驗證,請參閱 parse/1
。
此函數可以解析絕對和相對 URL。你可以檢查 URI 是絕對還是相對,方法是檢查 scheme
欄位是否為 nil
。
當給定 URI 沒有連接埠時,會使用 URI.default_port/1
為 URI 的 scheme 傳回的值作為 :port
欄位。scheme 也會標準化為小寫。
範例
iex> URI.new("https://elixir.dev.org.tw/")
{:ok, %URI{
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: 443,
query: nil,
scheme: "https",
userinfo: nil
}}
iex> URI.new("//elixir.dev.org.tw/")
{:ok, %URI{
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}}
iex> URI.new("/foo/bar")
{:ok, %URI{
fragment: nil,
host: nil,
path: "/foo/bar",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}}
iex> URI.new("foo/bar")
{:ok, %URI{
fragment: nil,
host: nil,
path: "foo/bar",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}}
iex> URI.new("//[fe80::]/")
{:ok, %URI{
fragment: nil,
host: "fe80::",
path: "/",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}}
iex> URI.new("https:?query")
{:ok, %URI{
fragment: nil,
host: nil,
path: nil,
port: 443,
query: "query",
scheme: "https",
userinfo: nil
}}
iex> URI.new("/invalid_greater_than_in_path/>")
{:error, ">"}
給定現有的 URI 只會將其包在 tuple 中傳回
iex> {:ok, uri} = URI.new("https://elixir.dev.org.tw/")
iex> URI.new(uri)
{:ok, %URI{
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: 443,
query: nil,
scheme: "https",
userinfo: nil
}}
類似於 new/1
,但如果給定無效的字串,則會引發 URI.Error
。
範例
iex> URI.new!("https://elixir.dev.org.tw/")
%URI{
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: 443,
query: nil,
scheme: "https",
userinfo: nil
}
iex> URI.new!("/invalid_greater_than_in_path/>")
** (URI.Error) cannot parse due to reason invalid_uri: ">"
給定現有的 URI 只會傳回該 URI
iex> uri = URI.new!("https://elixir.dev.org.tw/")
iex> URI.new!(uri)
%URI{
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: 443,
query: nil,
scheme: "https",
userinfo: nil
}
將 URI 解析成其組成部分,而不會進一步驗證。
此函數可以解析絕對和相對 URL。你可以檢查 URI 是絕對還是相對,方法是檢查 scheme
欄位是否為 nil。此外,此函數預期絕對和相對 URI 都格式正確,且不會執行任何驗證。請參閱以下「範例」區段。如果你想在解析後驗證 URI 欄位,請使用 new/1
。
當給定 URI 沒有連接埠時,會使用 URI.default_port/1
為 URI 的 scheme 傳回的值作為 :port
欄位。scheme 也會標準化為小寫。
如果將 %URI{}
結構傳給此函數,此函數會原封不動地傳回該結構。
:authority
欄位此函數會設定
:authority
欄位以維持向後相容性,但已不建議使用。
範例
iex> URI.parse("https://elixir.dev.org.tw/")
%URI{
authority: "elixir-lang.org",
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: 443,
query: nil,
scheme: "https",
userinfo: nil
}
iex> URI.parse("//elixir.dev.org.tw/")
%URI{
authority: "elixir-lang.org",
fragment: nil,
host: "elixir-lang.org",
path: "/",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}
iex> URI.parse("/foo/bar")
%URI{
fragment: nil,
host: nil,
path: "/foo/bar",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}
iex> URI.parse("foo/bar")
%URI{
fragment: nil,
host: nil,
path: "foo/bar",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}
與 URI.new/1
相反,此函數會解析格式不佳的 URI,例如
iex> URI.parse("/invalid_greater_than_in_path/>")
%URI{
fragment: nil,
host: nil,
path: "/invalid_greater_than_in_path/>",
port: nil,
query: nil,
scheme: nil,
userinfo: nil
}
另一個範例是查詢字串中包含括號的 URI。此 URI 會被 parse/1
接受,瀏覽器通常也會接受,但會被 new/1
拒絕。
iex> URI.parse("/?foo[bar]=baz")
%URI{
fragment: nil,
host: nil,
path: "/",
port: nil,
query: "foo[bar]=baz",
scheme: nil,
userinfo: nil
}
@spec query_decoder(binary(), :rfc3986 | :www_form) :: Enumerable.t()
傳回一個串流,其中包含代表給定 查詢
中的鍵值對的兩個元素元組。
每個 tuple 中的鍵和值都會是二進制資料,且會取消百分比編碼。
你可以指定下列 encoding
選項之一
:www_form
- (預設值,自 v1.12.0 起) 金鑰和值會根據decode_www_form/1
解碼。這是瀏覽器通常在查詢字串和表單資料上使用的格式。它會將「+」解碼為「 」。:rfc3986
- (自 v1.12.0 起) 金鑰和值會根據decode/1
解碼。結果與:www_form
相同,但會將「+」保留原樣,符合 RFC 3986。
編碼預設為 :www_form
以維持向後相容性。
範例
iex> URI.query_decoder("foo=1&bar=2") |> Enum.to_list()
[{"foo", "1"}, {"bar", "2"}]
iex> URI.query_decoder("food=bread%26butter&drinks=tap%20water+please") |> Enum.to_list()
[{"food", "bread&butter"}, {"drinks", "tap water please"}]
iex> URI.query_decoder("food=bread%26butter&drinks=tap%20water+please", :rfc3986) |> Enum.to_list()
[{"food", "bread&butter"}, {"drinks", "tap water+please"}]
傳回給定 URI 結構 的字串表示形式。
範例
iex> uri = URI.parse("http://google.com")
iex> URI.to_string(uri)
"http://google.com"
iex> uri = URI.parse("foo://bar.baz")
iex> URI.to_string(uri)
"foo://bar.baz"