Code Monkey home page Code Monkey logo

Comments (16)

SimonSapin avatar SimonSapin commented on July 4, 2024

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.

Valve avatar Valve commented on July 4, 2024

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.

SimonSapin avatar SimonSapin commented on July 4, 2024

@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.

Valve avatar Valve commented on July 4, 2024

@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.

seanmonstar avatar seanmonstar commented on July 4, 2024

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.

SimonSapin avatar SimonSapin commented on July 4, 2024

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.

seanmonstar avatar seanmonstar commented on July 4, 2024
  1. 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 struct pub struct Path(String) for my own sanity.
  2. 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.

SimonSapin avatar SimonSapin commented on July 4, 2024

Could you explain the semantics of join, normalize, and relativeTo? What do they do?

from rust-url.

SimonSapin avatar SimonSapin commented on July 4, 2024

In particular, for join, should "absolute" paths (starting with /) be treated differently from relative ones?

from rust-url.

seanmonstar avatar seanmonstar commented on July 4, 2024

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 that join("/foo", "/bar") would notice /bar is absolute, and leave it alone. Another option could be that join only accepts RelativePaths.
  • normalize: I'd expect Path::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 a RelativePath?)

from rust-url.

seanmonstar avatar seanmonstar commented on July 4, 2024

Likewise, to deal with multiple absolute Paths, perhaps path.append("/bar") would give /foo/bar.

from rust-url.

SimonSapin avatar SimonSapin commented on July 4, 2024

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.

seanmonstar avatar seanmonstar commented on July 4, 2024

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.

SimonSapin avatar SimonSapin commented on July 4, 2024

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.

SimonSapin avatar SimonSapin commented on July 4, 2024

@seanmonstar By the way, is your HTTP library only for the server-side, or also clients? Is it available online yet?

from rust-url.

seanmonstar avatar seanmonstar commented on July 4, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.