aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-shim/src/url.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/shirabe-php-shim/src/url.rs')
-rw-r--r--crates/shirabe-php-shim/src/url.rs94
1 files changed, 27 insertions, 67 deletions
diff --git a/crates/shirabe-php-shim/src/url.rs b/crates/shirabe-php-shim/src/url.rs
index c2ac725d..45920402 100644
--- a/crates/shirabe-php-shim/src/url.rs
+++ b/crates/shirabe-php-shim/src/url.rs
@@ -1,80 +1,40 @@
use crate::PhpMixed;
use indexmap::IndexMap;
-pub const PHP_URL_SCHEME: i64 = 0;
-pub const PHP_URL_HOST: i64 = 1;
-pub const PHP_URL_PORT: i64 = 2;
-pub const PHP_URL_USER: i64 = 3;
-pub const PHP_URL_PASS: i64 = 4;
-pub const PHP_URL_PATH: i64 = 5;
-pub const PHP_URL_QUERY: i64 = 6;
-pub const PHP_URL_FRAGMENT: i64 = 7;
-
-pub fn parse_url(url: &str, component: i64) -> PhpMixed {
- let all = parse_url_all(url);
- let map = match all.as_array() {
- Some(map) => map,
- // parse_url_all already collapsed a malformed URL to false; propagate it.
- None => return all,
- };
- let key = match component {
- PHP_URL_SCHEME => "scheme",
- PHP_URL_HOST => "host",
- PHP_URL_PORT => "port",
- PHP_URL_USER => "user",
- PHP_URL_PASS => "pass",
- PHP_URL_PATH => "path",
- PHP_URL_QUERY => "query",
- PHP_URL_FRAGMENT => "fragment",
- _ => return PhpMixed::Null,
- };
- map.get(key).cloned().unwrap_or(PhpMixed::Null)
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
+pub struct UrlComponents {
+ pub scheme: Option<String>,
+ pub host: Option<String>,
+ pub port: Option<i64>,
+ pub user: Option<String>,
+ pub pass: Option<String>,
+ pub path: Option<String>,
+ pub query: Option<String>,
+ pub fragment: Option<String>,
}
-pub fn parse_url_all(url: &str) -> PhpMixed {
+/// PHP `parse_url()`. `None` for an invalid URL.
+pub fn parse_url(url: &str) -> Option<UrlComponents> {
// TODO(php-semantics): PHP's parse_url uses php_url_parse_ex, which accepts relative
// and partial URLs and leaves an absent component absent. reqwest::Url
// (WHATWG/RFC 3986) requires an absolute URL, lowercases the host of special
// schemes, and normalizes the path (e.g. "http://host" yields path "/"). This
// is therefore not a byte-for-byte compatible port of parse_url.
- let parsed = match reqwest::Url::parse(url) {
- Ok(parsed) => parsed,
- Err(_) => return PhpMixed::Bool(false),
- };
- let mut map: IndexMap<String, PhpMixed> = IndexMap::new();
- map.insert(
- "scheme".to_string(),
- PhpMixed::String(parsed.scheme().to_string()),
- );
- if let Some(host) = parsed.host_str() {
- map.insert("host".to_string(), PhpMixed::String(host.to_string()));
- }
- if let Some(port) = parsed.port() {
- map.insert("port".to_string(), PhpMixed::Int(port as i64));
- }
- if !parsed.username().is_empty() {
- map.insert(
- "user".to_string(),
- PhpMixed::String(parsed.username().to_string()),
- );
- }
- if let Some(pass) = parsed.password() {
- map.insert("pass".to_string(), PhpMixed::String(pass.to_string()));
- }
- let path = parsed.path();
- if !path.is_empty() {
- map.insert("path".to_string(), PhpMixed::String(path.to_string()));
- }
- if let Some(query) = parsed.query() {
- map.insert("query".to_string(), PhpMixed::String(query.to_string()));
- }
- if let Some(fragment) = parsed.fragment() {
- map.insert(
- "fragment".to_string(),
- PhpMixed::String(fragment.to_string()),
- );
- }
- PhpMixed::Array(map)
+ let parsed = reqwest::Url::parse(url).ok()?;
+ Some(UrlComponents {
+ scheme: Some(parsed.scheme().to_string()),
+ host: parsed.host_str().map(str::to_string),
+ port: parsed.port().map(i64::from),
+ user: Some(parsed.username())
+ .filter(|user| !user.is_empty())
+ .map(str::to_string),
+ pass: parsed.password().map(str::to_string),
+ path: Some(parsed.path())
+ .filter(|path| !path.is_empty())
+ .map(str::to_string),
+ query: parsed.query().map(str::to_string),
+ fragment: parsed.fragment().map(str::to_string),
+ })
}
pub fn http_build_query_mixed(