|
@@ -1,17 +1,20 @@
|
|
|
use nom::{
|
|
use nom::{
|
|
|
- bytes::complete::{tag, take_while, take_while1},
|
|
|
|
|
|
|
+ bytes::complete::{tag, take_while},
|
|
|
character::complete::char,
|
|
character::complete::char,
|
|
|
|
|
+ combinator::opt,
|
|
|
multi::many0,
|
|
multi::many0,
|
|
|
- sequence::{preceded, separated_pair},
|
|
|
|
|
|
|
+ sequence::{preceded, separated_pair, terminated},
|
|
|
Parser,
|
|
Parser,
|
|
|
};
|
|
};
|
|
|
use serde::{Deserialize, Serialize};
|
|
use serde::{Deserialize, Serialize};
|
|
|
use std::{collections::HashMap, fmt::Display};
|
|
use std::{collections::HashMap, fmt::Display};
|
|
|
|
|
+use tauri_plugin_log::log;
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
pub struct RequestUrlOwned {
|
|
pub struct RequestUrlOwned {
|
|
|
- pub scheme: String,
|
|
|
|
|
- pub host: String,
|
|
|
|
|
|
|
+ pub pre: String,
|
|
|
|
|
+ // pub scheme: String,
|
|
|
|
|
+ // pub host: String,
|
|
|
pub path: Vec<SegmentOwned>,
|
|
pub path: Vec<SegmentOwned>,
|
|
|
pub query_params: Vec<(String, String)>,
|
|
pub query_params: Vec<(String, String)>,
|
|
|
pub has_query: bool,
|
|
pub has_query: bool,
|
|
@@ -29,10 +32,11 @@ pub enum SegmentOwned {
|
|
|
#[derive(Debug)]
|
|
#[derive(Debug)]
|
|
|
pub struct RequestUrl<'a> {
|
|
pub struct RequestUrl<'a> {
|
|
|
/// The URL scheme, e.g. `http`.
|
|
/// The URL scheme, e.g. `http`.
|
|
|
- pub scheme: &'a str,
|
|
|
|
|
|
|
+ // pub scheme: &'a str,
|
|
|
|
|
|
|
|
/// The URL host, includes the port if specified.
|
|
/// The URL host, includes the port if specified.
|
|
|
- pub host: &'a str,
|
|
|
|
|
|
|
+ // pub host: &'a str,
|
|
|
|
|
+ pub pre: &'a str,
|
|
|
|
|
|
|
|
/// The URL path segments.
|
|
/// The URL path segments.
|
|
|
///
|
|
///
|
|
@@ -96,14 +100,19 @@ impl<'a> RequestUrl<'a> {
|
|
|
|
|
|
|
|
let mut offset = 0;
|
|
let mut offset = 0;
|
|
|
|
|
|
|
|
- let (input, scheme) = match take_while1(char::is_alphabetic)(original_input) {
|
|
|
|
|
- Ok((i, s)) => (i, s),
|
|
|
|
|
- Err(e) => return Err(map_nom_err(original_input, None, e)),
|
|
|
|
|
- };
|
|
|
|
|
-
|
|
|
|
|
- let (input, _) = tag("://")(input).map_err(|e| map_nom_err(input, Some("://"), e))?;
|
|
|
|
|
|
|
+ // Parse the tag if it exists
|
|
|
|
|
|
|
|
- offset += scheme.len() + 3;
|
|
|
|
|
|
|
+ let input =
|
|
|
|
|
+ match opt(terminated(take_while(|c| c != ':'), tag("://"))).parse(original_input) {
|
|
|
|
|
+ Ok((input, scheme)) => match scheme {
|
|
|
|
|
+ Some(scheme) => {
|
|
|
|
|
+ offset += scheme.len() + 3;
|
|
|
|
|
+ input
|
|
|
|
|
+ }
|
|
|
|
|
+ None => input,
|
|
|
|
|
+ },
|
|
|
|
|
+ Err(e) => return Err(map_nom_err(original_input, None, e)),
|
|
|
|
|
+ };
|
|
|
|
|
|
|
|
// Parse until first /
|
|
// Parse until first /
|
|
|
|
|
|
|
@@ -113,19 +122,20 @@ impl<'a> RequestUrl<'a> {
|
|
|
// We've fully parsed the string, no path
|
|
// We've fully parsed the string, no path
|
|
|
|
|
|
|
|
if path.is_empty() {
|
|
if path.is_empty() {
|
|
|
- let (query, host) =
|
|
|
|
|
|
|
+ let (query, remainder) =
|
|
|
take_while(|c| c != '?')(host).map_err(|e| map_nom_err(host, None, e))?;
|
|
take_while(|c| c != '?')(host).map_err(|e| map_nom_err(host, None, e))?;
|
|
|
|
|
|
|
|
- let (query_params, trailing) =
|
|
|
|
|
|
|
+ offset += remainder.len();
|
|
|
|
|
+
|
|
|
|
|
+ let (query_params, trailing_query_pair) =
|
|
|
parse_query(query).map_err(|e| map_nom_err(query, None, e))?;
|
|
parse_query(query).map_err(|e| map_nom_err(query, None, e))?;
|
|
|
|
|
|
|
|
return Ok(RequestUrl {
|
|
return Ok(RequestUrl {
|
|
|
- scheme,
|
|
|
|
|
- host,
|
|
|
|
|
|
|
+ pre: &original_input[..offset],
|
|
|
path: vec![],
|
|
path: vec![],
|
|
|
query_params,
|
|
query_params,
|
|
|
trailing_query: query == "?",
|
|
trailing_query: query == "?",
|
|
|
- trailing_query_pair: trailing,
|
|
|
|
|
|
|
+ trailing_query_pair,
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -146,6 +156,8 @@ impl<'a> RequestUrl<'a> {
|
|
|
.parse(path)
|
|
.parse(path)
|
|
|
.map_err(|e| map_nom_err(path, None, e))?;
|
|
.map_err(|e| map_nom_err(path, None, e))?;
|
|
|
|
|
|
|
|
|
|
+ let mut segment_offset = offset;
|
|
|
|
|
+
|
|
|
let mut path = vec![];
|
|
let mut path = vec![];
|
|
|
|
|
|
|
|
for segment in segments {
|
|
for segment in segments {
|
|
@@ -157,25 +169,24 @@ impl<'a> RequestUrl<'a> {
|
|
|
{
|
|
{
|
|
|
Ok((remainder, segment)) => {
|
|
Ok((remainder, segment)) => {
|
|
|
debug_assert_eq!("", remainder);
|
|
debug_assert_eq!("", remainder);
|
|
|
- path.push(Segment::Dynamic(segment, offset));
|
|
|
|
|
|
|
+ path.push(Segment::Dynamic(segment, segment_offset));
|
|
|
// account for :
|
|
// account for :
|
|
|
- offset += segment.len() + 1;
|
|
|
|
|
|
|
+ segment_offset += segment.len() + 1;
|
|
|
}
|
|
}
|
|
|
Err(_) => {
|
|
Err(_) => {
|
|
|
- path.push(Segment::Static(segment, offset));
|
|
|
|
|
- offset += segment.len();
|
|
|
|
|
|
|
+ path.push(Segment::Static(segment, segment_offset));
|
|
|
|
|
+ segment_offset += segment.len();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// account for the parsed /
|
|
// account for the parsed /
|
|
|
- offset += 1;
|
|
|
|
|
|
|
+ segment_offset += 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
debug_assert!(remainder.is_empty());
|
|
debug_assert!(remainder.is_empty());
|
|
|
|
|
|
|
|
Ok(RequestUrl {
|
|
Ok(RequestUrl {
|
|
|
- scheme,
|
|
|
|
|
- host,
|
|
|
|
|
|
|
+ pre: &original_input[..offset],
|
|
|
path,
|
|
path,
|
|
|
query_params,
|
|
query_params,
|
|
|
trailing_query: query == "?",
|
|
trailing_query: query == "?",
|
|
@@ -183,13 +194,12 @@ impl<'a> RequestUrl<'a> {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- pub fn populate(&mut self, path_params: HashMap<&'a str, &'a str>) {
|
|
|
|
|
|
|
+ pub fn populate_path(&mut self, path_params: HashMap<&'a str, &'a str>) {
|
|
|
let mut total_displaced = 0i64;
|
|
let mut total_displaced = 0i64;
|
|
|
|
|
|
|
|
for path in self.path.iter_mut() {
|
|
for path in self.path.iter_mut() {
|
|
|
match path {
|
|
match path {
|
|
|
Segment::Dynamic(value, offset) => {
|
|
Segment::Dynamic(value, offset) => {
|
|
|
- dbg!(*offset, total_displaced);
|
|
|
|
|
let value_len = value.len();
|
|
let value_len = value.len();
|
|
|
|
|
|
|
|
let new = path_params.get(value).unwrap_or(&"");
|
|
let new = path_params.get(value).unwrap_or(&"");
|
|
@@ -217,13 +227,40 @@ impl<'a> RequestUrl<'a> {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ pub fn swap_path_segment(&mut self, new: Segment<'a>) {
|
|
|
|
|
+ let Some((skip, segment)) = self
|
|
|
|
|
+ .path
|
|
|
|
|
+ .iter_mut()
|
|
|
|
|
+ .enumerate()
|
|
|
|
|
+ .map(|(i, s)| (i + 1, s))
|
|
|
|
|
+ .find(|(_, s)| s.position() == new.position())
|
|
|
|
|
+ else {
|
|
|
|
|
+ log::warn!(
|
|
|
|
|
+ "Attempted to swap segment with invalid position {}",
|
|
|
|
|
+ new.position()
|
|
|
|
|
+ );
|
|
|
|
|
+ return;
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ let offset = new.len() as i64 - segment.len() as i64;
|
|
|
|
|
+
|
|
|
|
|
+ *segment = new;
|
|
|
|
|
+
|
|
|
|
|
+ for path in self.path.iter_mut().skip(skip) {
|
|
|
|
|
+ if offset < 0 {
|
|
|
|
|
+ path.set_position(path.position() - offset.abs() as usize);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ path.set_position(path.position() + offset as usize);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl<'a> From<RequestUrl<'a>> for RequestUrlOwned {
|
|
impl<'a> From<RequestUrl<'a>> for RequestUrlOwned {
|
|
|
- fn from(value: RequestUrl<'a>) -> Self {
|
|
|
|
|
|
|
+ fn from(value: RequestUrl<'_>) -> Self {
|
|
|
Self {
|
|
Self {
|
|
|
- scheme: value.scheme.to_owned(),
|
|
|
|
|
- host: value.host.to_owned(),
|
|
|
|
|
|
|
+ pre: value.pre.to_string(),
|
|
|
path: value.path.into_iter().map(Into::into).collect(),
|
|
path: value.path.into_iter().map(Into::into).collect(),
|
|
|
query_params: value
|
|
query_params: value
|
|
|
.query_params
|
|
.query_params
|
|
@@ -238,8 +275,9 @@ impl<'a> From<RequestUrl<'a>> for RequestUrlOwned {
|
|
|
impl<'a> Display for RequestUrl<'a> {
|
|
impl<'a> Display for RequestUrl<'a> {
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
let RequestUrl {
|
|
let RequestUrl {
|
|
|
- scheme,
|
|
|
|
|
- host,
|
|
|
|
|
|
|
+ // scheme,
|
|
|
|
|
+ // host,
|
|
|
|
|
+ pre,
|
|
|
path,
|
|
path,
|
|
|
query_params,
|
|
query_params,
|
|
|
trailing_query,
|
|
trailing_query,
|
|
@@ -279,7 +317,7 @@ impl<'a> Display for RequestUrl<'a> {
|
|
|
params
|
|
params
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
- write!(f, "{scheme}://{host}{path}{query}")
|
|
|
|
|
|
|
+ write!(f, "{pre}{path}{query}")
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -297,6 +335,29 @@ pub enum Segment<'a> {
|
|
|
Dynamic(&'a str, usize),
|
|
Dynamic(&'a str, usize),
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+impl<'a> Segment<'a> {
|
|
|
|
|
+ pub fn position(&self) -> usize {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Segment::Static(_, pos) => *pos,
|
|
|
|
|
+ Segment::Dynamic(_, pos) => *pos,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn len(&self) -> usize {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Segment::Static(s, _) => s.len(),
|
|
|
|
|
+ Segment::Dynamic(s, _) => s.len(),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ pub fn set_position(&mut self, pos: usize) {
|
|
|
|
|
+ match self {
|
|
|
|
|
+ Segment::Static(_, p) => *p = pos,
|
|
|
|
|
+ Segment::Dynamic(_, p) => *p = pos,
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
impl<'a> From<Segment<'a>> for SegmentOwned {
|
|
impl<'a> From<Segment<'a>> for SegmentOwned {
|
|
|
fn from(value: Segment<'a>) -> Self {
|
|
fn from(value: Segment<'a>) -> Self {
|
|
|
match value {
|
|
match value {
|
|
@@ -398,8 +459,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(expected_path, url.path);
|
|
assert_eq!(expected_path, url.path);
|
|
|
assert!(url.query_params.is_empty());
|
|
assert!(url.query_params.is_empty());
|
|
|
}
|
|
}
|
|
@@ -417,8 +478,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(expected_path, url.path);
|
|
assert_eq!(expected_path, url.path);
|
|
|
assert!(url.query_params.is_empty());
|
|
assert!(url.query_params.is_empty());
|
|
|
}
|
|
}
|
|
@@ -429,8 +490,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert!(url.path.is_empty());
|
|
assert!(url.path.is_empty());
|
|
|
assert!(url.query_params.is_empty());
|
|
assert!(url.query_params.is_empty());
|
|
|
}
|
|
}
|
|
@@ -441,8 +502,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![
|
|
vec![
|
|
|
Segment::Static("", "http://localhost:4000".len()),
|
|
Segment::Static("", "http://localhost:4000".len()),
|
|
@@ -459,8 +520,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![
|
|
vec![
|
|
|
Segment::Dynamic("", "http://localhost:4000".len()),
|
|
Segment::Dynamic("", "http://localhost:4000".len()),
|
|
@@ -477,8 +538,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![Segment::Static("", "http://localhost:4000".len())],
|
|
vec![Segment::Static("", "http://localhost:4000".len())],
|
|
|
url.path
|
|
url.path
|
|
@@ -492,8 +553,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert!(url.path.is_empty());
|
|
assert!(url.path.is_empty());
|
|
|
assert_eq!(vec![("foo", "bar"), ("baz", "bax")], url.query_params);
|
|
assert_eq!(vec![("foo", "bar"), ("baz", "bax")], url.query_params);
|
|
|
}
|
|
}
|
|
@@ -504,8 +565,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![
|
|
vec![
|
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
@@ -523,8 +584,8 @@ mod tests {
|
|
|
|
|
|
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![
|
|
vec![
|
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
@@ -543,8 +604,8 @@ mod tests {
|
|
|
|
|
|
|
|
let mut url = RequestUrl::parse(input).unwrap();
|
|
let mut url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
|
|
|
- assert_eq!("http", url.scheme);
|
|
|
|
|
- assert_eq!("localhost:4000", url.host);
|
|
|
|
|
|
|
+ assert_eq!("http://localhost:4000", url.pre);
|
|
|
|
|
+
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
vec![
|
|
vec![
|
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
Segment::Static("foo", "http://localhost:4000".len()),
|
|
@@ -556,7 +617,7 @@ mod tests {
|
|
|
url.path
|
|
url.path
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- url.populate(HashMap::from([("bar", "VALUE"), ("baz", "EULAV")]));
|
|
|
|
|
|
|
+ url.populate_path(HashMap::from([("bar", "VALUE"), ("baz", "EULAV")]));
|
|
|
|
|
|
|
|
assert_eq!(
|
|
assert_eq!(
|
|
|
"http://localhost:4000/foo/VALUE/qux/EULAV/final",
|
|
"http://localhost:4000/foo/VALUE/qux/EULAV/final",
|
|
@@ -589,7 +650,7 @@ mod tests {
|
|
|
url.path
|
|
url.path
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- url.populate(HashMap::from([("ID", ""), ("myID", "")]));
|
|
|
|
|
|
|
+ url.populate_path(HashMap::from([("ID", ""), ("myID", "")]));
|
|
|
|
|
|
|
|
assert_eq!("http://foo.com//", url.to_string());
|
|
assert_eq!("http://foo.com//", url.to_string());
|
|
|
|
|
|
|
@@ -616,7 +677,7 @@ mod tests {
|
|
|
url.path
|
|
url.path
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
- url.populate(HashMap::from([("ID", "FOO")]));
|
|
|
|
|
|
|
+ url.populate_path(HashMap::from([("ID", "FOO")]));
|
|
|
|
|
|
|
|
assert_eq!("http://foo.com/FOO/", url.to_string());
|
|
assert_eq!("http://foo.com/FOO/", url.to_string());
|
|
|
|
|
|
|
@@ -628,4 +689,50 @@ mod tests {
|
|
|
url.path
|
|
url.path
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ #[test]
|
|
|
|
|
+ fn swaps_dynamic_segment_and_offsets() {
|
|
|
|
|
+ let input = "http://foo.com/bar/:ID/";
|
|
|
|
|
+
|
|
|
|
|
+ let mut url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Segment::Static("bar", "http://foo.com".len()),
|
|
|
|
|
+ Segment::Dynamic("ID", "http://foo.com/bar".len()),
|
|
|
|
|
+ Segment::Static("", "http://foo.com/bar/:ID".len()),
|
|
|
|
|
+ ],
|
|
|
|
|
+ url.path
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ let segment = Segment::Dynamic("AAAAA", "http://foo.com/bar".len());
|
|
|
|
|
+ url.swap_path_segment(segment);
|
|
|
|
|
+
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Segment::Static("bar", "http://foo.com".len()),
|
|
|
|
|
+ Segment::Dynamic("AAAAA", "http://foo.com/bar".len()),
|
|
|
|
|
+ Segment::Static("", "http://foo.com/bar/:AAAAA".len()),
|
|
|
|
|
+ ],
|
|
|
|
|
+ url.path
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[test]
|
|
|
|
|
+ fn parses_with_placeholders() {
|
|
|
|
|
+ let input = "{{BASE_URL}}/bar/:ID/";
|
|
|
|
|
+
|
|
|
|
|
+ let url = RequestUrl::parse(input).unwrap();
|
|
|
|
|
+
|
|
|
|
|
+ assert_eq!("{{BASE_URL}}", url.pre);
|
|
|
|
|
+
|
|
|
|
|
+ assert_eq!(
|
|
|
|
|
+ vec![
|
|
|
|
|
+ Segment::Static("bar", "{{BASE_URL}}".len()),
|
|
|
|
|
+ Segment::Dynamic("ID", "{{BASE_URL}}/bar".len()),
|
|
|
|
|
+ Segment::Static("", "{{BASE_URL}}/bar/:ID".len()),
|
|
|
|
|
+ ],
|
|
|
|
|
+ url.path
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|