-
Notifications
You must be signed in to change notification settings - Fork 291
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
There should be an uri::Builder #206
Comments
Thanks for writing this up! I agree with premise, we should be able to provide a builder for easier creation. Since different parts of a URI have different allowed characters, the builder would need to return a |
Invalid characters are percent encoded so I don't see a way for query/path functions to fail. |
Servo's percent-encoding crate is a small dependency that defines the right encoding for the right part of the URL quite well. |
That's a good point for path and query. |
It doesn't have all that is mentioned in here, but I've at least started a builder concept in #219. |
#219 has been merged, which provides methods for:
There is room to add methods for smaller parts, but they should be discussed first. |
To add more granularities to the Builder, some additionnal struct could be addeded. The PR #268 proposes a If the builder would allow to build path and query separately, we could offer a better way, according to me, to abstract the different endpoints of an API. Inspired by some Swift practices I’m using, we could have some code like this : pub trait Endpoint {
fn method(self) -> http::Method;
fn path(self) -> String;
fn query(self) -> Vec<QueryItem>;
} This would allow to abstract the different API's paths by any element implementing the The form of the struct QueryItem<'a> {
key: &'a str;
value: Option<&'a str>;
} Or: struct QueryItem<'a> {
key: String;
value: Option<String>;
} As a non Rust expert, I do not have a clear vision about the consequences of the adoption of one form or the other. In the end, the URI builder would require new fields to be able to construct the URI. This may involve changing the internal API for #[derive(Debug, Default)]
pub struct Parts {
/// The scheme component of a URI
pub scheme: Option<Scheme>,
/// The authority component of a URI
pub authority: Option<Authority>,
/// The origin-form component of a URI
// pub path_and_query: Option<PathAndQuery>, --> Removed it?
/// The path of the query
pub path: String
/// The different query items
pub query_items: Vec<QueryItem>
/// Allow extending in the future
_priv: (),
} The builder could be updated accordingly: impl Builder {
pub fn path(&mut self, path: String) -> &mut Self;
pub fn query(&mut self, key: String, value: Option<String>) -> &mut Self;
} |
Any movement on this? I'd love to see this feature in 0.2 and am happy to draft a PR if this is something we're still interested in. Building on @SergejJurecko's ideas, I'd like to propose the following API: let uri = Uri::builder()
.scheme(POSTGRES) // Built-in &str constants also supporting HTTPS (default), HTTP, MYSQL, etc. Can also be a user-supplied string
.auth("username", "password")
.host("www.example.com")
.port(12345)
.path(&["a", "b", "c d"])
.query("key", "value")
.query("key2", "value two")
.queries(&[("k3,", "v3"), ("k4", "v4")])
.fragment("heading")
.build()
.unwrap();
assert_eq!(
"postgres://username:password@www.example.com:12345/a/b/c%20d?key=value&key2=value%20two&k3=v3&k4=v4#heading",
uri.as_str()
); I'd also like to propose a convenience I'm having difficulty envisioning a use case for specifying individual path components and would be partial towards omitting the proposed Feedback welcome! Edit: Added |
For building requests against an API. Often different requests share part of a path and differ in some segments. It does not make sense in your example because everything is built in one go. It's for when you require building requests in stages. |
Apologies. I made an assumption in my proposal that wasn't mentioned explicitly (and definitely was't clear in my comment). My intention was for This does raise an interesting question: From the name do we expect these methods to push items or replace their existing values (for both path and query components)? Perhaps a more clear API would be: |
I don't see how replace items would be a useful or expected operation in this context. push_ is pretty verbose and redundant if everything is push. |
Agreed. @seanmonstar @yageek Any additional questions/comments? |
IMO it would be fine to add a few more fns but we should stay on the conservative side. Host, port, path, and query are probably fine. Maybe even push_path, and query_param. |
@carllerche It sounds like you're concerned about bloating the API with redundant functions, which I can appreciate. Wikipedia's URI syntax diagram shows a scheme, userinfo, host, port, path, query, and fragment. These components are detailed in other documentation as well, and I'd argue it's important to offer methods for each one. That said, we might want to think about limiting the number of functions we offer for each component. Some ideas for discussion:
* I recognize it's bad practice to provide authentication credentials in a URI and developers should prefer a more secure method (e.g. HTTP header). That said, from what I've seen this practice is still fairly common. I'd advise adding a cautionary message in the documentation. We could deprecate the
Do you favor this naming over |
The http::Uri type is not intended to be a general purpose URI abstraction. It is the http protocol’s request target. As such, some components don’t apply. Auto should not be included as it is deprecated and it is strongly recommended to not use the auth component. In cases where it is needed, it can be set the more painful way. The current components should remain. Generally, IMO fns that append vs set should be differentiated. I.e push_path and push_query_param. |
It sounds like
Noted.
Noted.
Right now the proposed API only appends (possibly to a blank list). @SergejJurecko and I agree that
|
Right now the burden of correct percent encoding is entirely on the user. This is completely unnecessary. Only accepting string URI also forces users to concatenate strings to construct an URI, which is bad and inefficient practice that leads to bugs.
Examples
Entirely segmented
Only partly segmented because schemes, hosts and optional ports are not a percent encoding problem and often stored as a fixed string on a client.
Query and path segments could also be slices.
(edit by Sean)
To track the progress, here's what's done and needs to be done:
http::uri::Builder
Builder::scheme()
Builder::authority()
Builder::host()
Builder::port()
Builder::path_and_query()
Builder::query()
The text was updated successfully, but these errors were encountered: