Comments (16)
In what context would this be use? Should it include the query string? The fragment identifier? Note that HTTP’s origin-form
(the path as typically found in the start line of a request) includes a query but no fragment.
What would be the semantics of path.join(otherPath)
? Should it distinguish absolute paths like /foo/bar
from relative paths like foo/bar
?
What is add_query_param
? Note that the url::form_urlencoded
module already provides conversions between strings in the application/x-www-form-urlencoded
format and vectors of key/value pairs. I’m not convinced that adding a map-like API belongs in rust-url.
In general, I prefer having simple features that can be composed and built on top of to achieved various things, rather than a bunch of elaborate but narrow-purpose features.
from rust-url.
What would be the semantics of path.join(otherPath)? Should it distinguish absolute paths like /foo/bar from relative paths like foo/bar?
My case:
I'm building an API client and wondering what would the idiomatic way of handling multiple paths be.
For example, I have an api constructor, which accepts a base URL.
let api = API::new(Url.parse("https://service.com/api/v1/").unwrap());
Inside I have multiple operations (users, posts, tags, topics etc), each operation can have multiple sub-operations (create/update/read/update_all/delete_all), sub operations are not RESTful, so sub-paths are
required.
So inside my api instance I'll need to join 2 paths all the time,
baseUrl.join(updatePostsPath)
baseUrl.join(readTagsPath)
...
...
2nd case:
Once I have the correct path (i.e. /api/v1/users/delete_all), I will want to build a query string.
For example I may need to have /api/v1/users/delete_all?q=city:Dallas
How should I handle this with current design of rust-url?
To generalise my use cases:
Once I have a base URL (url with host,port and path), I will need to construct other URLs that start with base url, but append sub-paths and modify query string
from rust-url.
@Valve, you can do this by parsing with a base URL:
let api_base = Url::parse("https://service.com/api/v1/").unwrap();
let delete = UrlParser::new().base_url(&api_base).parse("users/delete_all").unwrap();
assert!(delete.to_string() == "https://service.com/api/v1/users/delete_all".to_string());
let dallas = UrlParser::new().base_url(&api_base).parse("?q=city:Dallas").unwrap();
assert!(dallas.to_string() == "https://service.com/api/v1/users/delete_all?q=city:Dallas".to_string());
Alternatively, for the query string, you can set key/value pairs. This will deal with percent-encoding if your string contains &
or non-ASCII characters.
let mut dallas2 = delete.clone();
dallas2.set_query_from_pairs([("q", "city:Dallas")].iter())
assert!(dallas2 == dallas);
(I haven’t tried the code above, so maybe it doesn’t compile. But you get the idea.)
But this is all with full URLs. This issues (if I understand correctly) is about manipulating paths without the rest of the URL.
from rust-url.
@SimonSapin thanks for the update, this is roughly what I've been doing.
Regarding the paths without baser URLs, I think the OP mostly had web server scenarios in mind. I never had them developing a client api library
from rust-url.
Yes, looking at some of the web frameworks (conduit, iron, nicket), I see this code a lot app.get("/foo/bar", handler)
. Seems like a candidate for that to be a Path
instead of &str
. Likewise, since this frameworks are following the pattern in express.js, I could imagine being able to "mount" sub-apps at a path. Something like mainApp.mount("/app", app)
from above, which would mean the route was really at /app/foo/bar
.
For an HTTP library, I'd rather the Request struct have a Path instead of a String for it's uri:
struct Request {
uri: RequestUri,
// ...
}
enum RequestUri {
Star,
AbsoluteUri(Url),
AbsolutePath(Path), // <-- Path instead of String
Authority(Authority),
}
from rust-url.
It’s still not clear to me: what functionality do you think Path
should have that Vec<String>
does not already have?
from rust-url.
- its a better type than
Vec<String>
, as it's more descriptive. If it doesn't make sense in this crate, I'll just make a wrapper structpub struct Path(String)
for my own sanity. - On a server, you tend to deal with pathes instead of complete urls. So,
join
,normalize
,relativeTo
, or whatever could be useful.
let route = Path::new("/app/foo/bar"); // pull off req.url?
let js = route.join("../foo.js");
let css = route.join("./bar.css");
from rust-url.
Could you explain the semantics of join
, normalize
, and relativeTo
? What do they do?
from rust-url.
In particular, for join, should "absolute" paths (starting with /
) be treated differently from relative ones?
from rust-url.
I'm just making up functionality that sounds like one might expect a Path
to do. If these methods existed, here's my expected results:
join
: I'd probably expect thatjoin("/foo", "/bar")
would notice/bar
is absolute, and leave it alone. Another option could be thatjoin
only acceptsRelativePath
s.normalize
: I'd expectPath::new("/app/foo/bar/../baz/./img.png").normalize()
to create/app/foo/baz/img.png
relativeTo
:Path::new("/foo/bar/baz").relativeTo(Path::new("/foo/moo/meow.js"))
to provide../../moo/meow.js
. (Again, perhaps as aRelativePath
?)
from rust-url.
Likewise, to deal with multiple absolute Paths, perhaps path.append("/bar")
would give /foo/bar
.
from rust-url.
I'm just making up functionality that sounds like one might expect a
Path
to do.
It sounds like you don’t need any of this yourself. Do you? I’d rather wait until someone with a use case asks for something specific than speculate.
from rust-url.
True, the specific functionality I don't need myself. I'm working on an http
crate, instead of waiting on Teepee, so I would like to be able to set request.uri = AbsolutePath(Path(someStr))
.
from rust-url.
I’ve added parse_path()
which, like the relevant part of the "main" URL parser, normalizes .
and ..
components. It returns (Vec<String>, Option<String>, Option<String>)
for the path, query string, and fragment identifier.
Web browsers string the fragment identifier when sending an HTTP request, but a misbehaved client could still send it. After some quick testing with netcat against a few servers, it appears that servers typically parse the fragment identifier (rather than let it be part of the path or query string) but then ignore it. So I’d recommend something like this for an HTTP server:
struct PathRequestTarget {
path: Vec<String>,
query: Option<String>
}
let (path, query, _fragment) = url::parse_path(input).unwrap();
PathRequestTarget { path: path, query: query }
from rust-url.
@seanmonstar By the way, is your HTTP library only for the server-side, or also clients? Is it available online yet?
from rust-url.
I'd like for it to do both. I'm aiming at it being a valid options for extern crate http
. Server is getting close, and then client. I planned to push it to github once it actually worked (in the simplest sense).
from rust-url.
Related Issues (20)
- Origin port as an `Option<u16>`
- percent ("%) character must be percent-encoded as "%25" HOT 1
- Optional API to convert to http::Uri HOT 3
- Wrongly resolves ip to domain. HOT 2
- feature request: more complicated percent-encoding rules HOT 2
- feature: expose pathname publicly HOT 3
- Please add an option to not remove wellknown default ports from URL HOT 1
- Feature Proposal: Builder for Constructing New URL Instances from Parts HOT 2
- The program crashed after using the "join" function.
- Program Crash in fuzzing (assert failed in parse_path)
- `set_port`, `set_username` & `set_password` should check for a value before returning `Err(())` HOT 7
- Shouldn't `Host` be lowercase by default?
- URL pathname and search setter incorrectly strips trailing spaces
- Roadmap HOT 1
- Stabilize `debugger_visualizer` feature
- InvalidPort is returned for URLs with a '#' HOT 1
- Fix `serde::Deserialize` impl for `Url` prints confusing error message
- Feature request: Provide customary RFC 3986 encoding
- Panic in set_path HOT 1
- parse: fuzzing errors
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rust-url.