some attempt at porting to a new url library

This commit is contained in:
Eric S. Londres 2023-03-07 22:13:47 -05:00
parent 739e875117
commit 3e9d2bcb86
Signed by: slondr
GPG Key ID: A2D25B4D5CB970E4
2 changed files with 33 additions and 25 deletions

View File

@ -1,12 +1,8 @@
[package]
name = "spart"
version = "0.1.0"
version = "0.2.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
# Some functionality of the normal url crate is only available for "special" schemes such as http.
# As we want to use this functionality for spartan urls, we use a patched version instead.
url = { git = "https://github.com/slondr/rust-url-additional-specials", branch = "master" }
url-parse = "1.0.5"
urlencoding = "~2.1"

View File

@ -1,5 +1,7 @@
use url::Url;
use std::collections::HashMap;
use std::io::prelude::*;
use url_parse::core::Parser;
use url_parse::url::Url;
pub struct Request {
host: String,
@ -10,24 +12,28 @@ pub struct Request {
impl Request {
pub fn from_url(parsed_url: Url) -> Result<Request, &'static str> {
if parsed_url.scheme() != "spartan" {
if parsed_url.scheme.as_ref().unwrap() != "spartan" {
return Err("Not a spartan URL")
}
match parsed_url.host_str() {
None => Err("No hostname"),
Some(unparsed_host) => {
let (data, content_length) = match parsed_url.query() {
let (data, content_length) = match parsed_url.query {
None => (None, 0),
Some(s) => {
let decoded_data = urlencoding::decode(s).unwrap().into_owned();
let decoded_data = urlencoding::decode(s.as_str()).unwrap().into_owned();
let decoded_len = decoded_data.chars().count();
(Some(decoded_data), decoded_len)
}
};
let host = unparsed_host.to_string();
let path = parsed_url.path().to_string();
let path = match parsed_url.path {
Some(p) => p.join("/"),
None => String::from("/")
};
Ok(Request { host, path, data, content_length })
}
@ -45,7 +51,7 @@ impl std::fmt::Display for Request {
}
pub fn get(r: String) -> Result<String, &'static str> {
match Url::parse(&r) {
match Parser::new(None).parse(&r) {
Err(_) => Err("Cannot parse url"),
Ok(url) => {
if let Some(port) = url.port_or_known_default() { // patched version of `uri` DOES have a default
@ -73,81 +79,87 @@ pub fn get(r: String) -> Result<String, &'static str> {
}
}
fn parse(url: String) -> Url {
let mut mappings = HashMap::new();
mappings.insert("spartan", (300, "Spartan"));
Parser::new(Some(mappings)).parse(url.as_str()).unwrap()
}
#[cfg(test)]
mod tests {
use crate::Request;
use crate::{Request, Parser, parse};
/// taken from 5.1 of the spec
#[test]
fn basic_url_mapping_without_slash() {
let request = Request::from_url(url::Url::parse("spartan://example.com").unwrap()).unwrap();
let request = Request::from_url(parse("spartan://example.com".to_string())).unwrap();
assert_eq!("example.com / 0\r\n", format!("{}", request))
}
#[test]
fn basic_url_mapping_with_slash() {
let request = Request::from_url(url::Url::parse("spartan://example.com/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com/").unwrap()).unwrap();
assert_eq!("example.com / 0\r\n", format!("{}", request))
}
#[test]
fn basic_url_mapping_with_port() {
let request = Request::from_url(url::Url::parse("spartan://example.com:3000/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com:3000/").unwrap()).unwrap();
assert_eq!("example.com / 0\r\n", format!("{}", request))
}
#[test]
fn basic_url_mapping_with_anchor() {
let request = Request::from_url(url::Url::parse("spartan://example.com/#about").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com/#about").unwrap()).unwrap();
assert_eq!("example.com / 0\r\n", format!("{}", request))
}
#[test]
fn basic_url_mapping_with_user() {
let request = Request::from_url(url::Url::parse("spartan://anon@example.com/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://anon@example.com/").unwrap()).unwrap();
assert_eq!("example.com / 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_from_ip_address() {
let request = Request::from_url(url::Url::parse("spartan://127.0.0.1/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://127.0.0.1/").unwrap()).unwrap();
assert_eq!("127.0.0.1 / 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_from_ip6_address() {
let request = Request::from_url(url::Url::parse("spartan://[::1]/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://[::1]/").unwrap()).unwrap();
assert_eq!("[::1] / 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_with_punycode() {
let request = Request::from_url(url::Url::parse("spartan://examplé.com/").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://examplé.com/").unwrap()).unwrap();
assert_eq!("xn--exampl-gva.com / 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_with_urlencoded_path() {
let request = Request::from_url(url::Url::parse("spartan://example.com/my%20file.txt").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com/my%20file.txt").unwrap()).unwrap();
assert_eq!("example.com /my%20file.txt 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_with_unicode_path() {
let request = Request::from_url(url::Url::parse("spartan://example.com/café.txt").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com/café.txt").unwrap()).unwrap();
assert_eq!("example.com /caf%C3%A9.txt 0\r\n", format!("{}", request))
}
#[test]
fn url_mapping_with_data() {
let request = Request::from_url(url::Url::parse("spartan://example.com?a=1&b=2").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com?a=1&b=2").unwrap()).unwrap();
assert_eq!("example.com / 7\r\na=1&b=2", format!("{}", request))
}
#[test]
fn url_mapping_with_urlencoded_data() {
let request = Request::from_url(url::Url::parse("spartan://example.com?hello%20world").unwrap()).unwrap();
let request = Request::from_url(Parser::new(None).parse("spartan://example.com?hello%20world").unwrap()).unwrap();
assert_eq!("example.com / 11\r\nhello world", format!("{}", request))
}