hyperium / headers

Typed HTTP Headers from hyper
https://hyper.rs
MIT License
164 stars 83 forks source link

Add WWW-Authenticate header #21

Open algermissen opened 6 years ago

algermissen commented 6 years ago

This a note that I started working on WWW-Authenticate in case someone else does, too.

algermissen commented 6 years ago

@seanmonstar Here is a preview of the direction I am taking. Focus is on the 'encoding-side' because this is what I need right now for adding authorization header to warp.

https://github.com/hyperium/headers/compare/master...algermissen:add-www-authenticate

If you happen to have the spare time I would be especially interested in ideas around representing additional challenges without bloating the primary scenario of exactly one challenge:

https://tinyurl.com/y7kz46x4

seanmonstar commented 6 years ago

@algermissen very cool! It's hard to comment on implementations here in the issue, it may be easier in a pull request.

How do you suppose multiple challenges would be put together by a user? And how would a user access them when decoding the header as well?

scottlamb commented 5 years ago

I was looking for this; thanks for starting it!

I see this declaration:

pub struct WWWAuthenticate<C: Challenge>(pub C, pub Option<Vec<String>>);

Small nit: looks like you're trying to avoid extra allocations in the common single-challenge case. Vec::new doesn't allocate so the Option isn't necessary.

More significant design point: Decoders won't necessarily know what scheme to expect, so I think they'd work better with a sized Challenge type. And you could just parse them all at once, rather than expose Strings that have to be fed back in later.

// simplest form
pub struct WWWAuthenticate(pub Vec<Challenge>);

// head + tail form, as you have, to avoid extra allocations
pub struct WWWAuthenticate(pub Challenge, Vec<Challenge>);

// tempting to use smallvec for this purpose, but probably not wise to use it in an
// interface, especially before 1.0:
// https://github.com/servo/rust-smallvec/issues/73
// Could hide it, but we'd want users to be able to mutate it, without us having to
// duplicate the whole Vec interface...
pub struct WWWAuthenticate(pub smallvec::SmallVec<[Challenge; 1]>);

I have a couple ideas for how a sized Challenge type could look:

single general type

One that allows access to the scheme and a parameter map. Straw man:

struct Challenge {
    scheme: String,
    params: HashMap<String, String>,
}

enum

There are only 10 registered schemes. Straw man:

enum Challenge {
    Basic(BasicChallenge),
    Digest(DigestChallenge),
    Bearer(BearerChallenge),
    // ...a few I'm skipping...
    Unknown(UnknownChallenge),
};

// with some common stuff available, at least:
impl Challenge {
    pub fn scheme(&self) -> &str { ... }
}

// and more tailored structs for each
scottlamb commented 5 years ago

Also, I'm not sure if you've seen this prior work I just ran across. There's a published crate that parses/prints Basic and Digest schemes.

daniel5151 commented 5 years ago

Hey there, any news on this?