mirror of https://git.sr.ht/~slondr/spart
some attempt at porting to a new url library
This commit is contained in:
parent
739e875117
commit
3e9d2bcb86
|
@ -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"
|
||||
|
|
50
src/lib.rs
50
src/lib.rs
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue