Skip to content

Redesign the Uri type #1000

Closed
Closed
@seanmonstar

Description

@seanmonstar

There are a couple of things that a redesign could help with:

  • Making it an opaque struct instead of an enum means fiddling with internals is no longer a breaking change
  • It'd be best if we could create less copies when parsing out a URI
  • To future-proof for when hyper supports HTTP2

We want to optimize for the most common case, which is the origin-form, (currently RequestUri::AbsolutePath). We can start with keeping a single String, and then keeping indices into it to know where the path and query are.

In HTTP2, the URI would gain additional fields, scheme and authority (what is in HTTP1 the Host header), and the asterisk-form request target is defined as path = *.

We could eventually change the internal source representation to be a MemSlice or whatever it is at that point, to reduce a further copy.

Some quick code describing what it could look like:

pub struct Uri {
    source: String,
    scheme_end: Option<usize>,
    authority_end: Option<usize>,
    query: Option<usize>,
}

impl Uri {
    pub fn path(&self) -> &str {
        let index = self.scheme_end.unwrap_or(0) + self.authority_end.unwrap_or(0);
        let end = self.query.unwrap_or(self.source.len());
        &self.source[index..end]
    }
    // .. and other accessors
}

let star = Uri::from_str("*").unwrap();
assert_eq!(Uri {
    source: String::from("*"),
    scheme_end: None,
    authority_end: None,
    query: None,
}, star);
assert_eq!(star.path(), "*");

let common = Uri::from_str("/p?foo=bar").unwrap();
assert_eq!(Uri {
    source: String::from("/p?foo=bar"),
    scheme_end: None,
    authority_end: None,
    query: Some(2),
}, common);
assert_eq!(common.path(), "/p");
assert_eq!(common.query(), "?foo=bar");

cc @GuillaumeGomez

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions