Skip to content

Request "always" has a Uri #110

@thanatos

Description

@thanatos

Request has the following method:

fn uri(&self) -> &Uri

Returns a reference to the associated URI.

But an actual HTTP request doesn't always contain a URI. HTTP's RFC notes that a request has a request-target, which is,

     request-target = origin-form
                    / absolute-form
                    / authority-form
                    / asterisk-form

Only absolute-form is a URI; the remaining three are not. origin-form, I would say, is the form most folks implementing basic CRUD APIs are going to interact with.

My concern is that the API encourages writing origin servers that will respond to non-origin requests poorly, and defeats the point of strong static typing by essentially munging what is an enumeration into a singly string. (i.e., it "stringly types" the data)

E.g., if you receive the following request:

GET http://example.com/ HTTP/1.1
Host: example.com
Connection: close

(assuming the receiving server is not example.com) If your routing does something like request.uri() == "/something", you won't erroneously match a proxy request; however, you're still likely to return 404. If you do request.uri().path(), you're likely going to incorrectly respond with the wrong content.

Ultimately, I feel that the actual type implied by the spec is,

enum RequestTarget {
    Origin(Path),
    Absolute(Uri),
    Authority(Authority),
    Asterisk,
}

This would render some of the method that presume they can always return things (e.g., Request::uri) into Options. (e.g., Request::uri() -> Option<Uri>); but this would also mean Uri would actually represent a URI and wouldn't need to be capable of handling weird things like "*". (As others noted: Uri seems like something that should be more common than it is, and removing HTTP-specific meanings from it makes it more easily extractable.)

Request might benefit from some helper methods to deal with "I just want to write an origin server" — but again, the need for such is already present, hidden behind the fact that all four types are munged into one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions