-
-
Notifications
You must be signed in to change notification settings - Fork 76
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Improve Request type #51
Conversation
2bdac92
to
91898f3
Compare
b2a10a9
to
65a5edb
Compare
10a02b0
to
250b3f6
Compare
/// Resource URL. Can be either absolute or relative. | ||
public var url: String | ||
public var url: URL? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a motive for optional? I would implicitly expect that the developer would make sure that the request is valid to begin with. We could mimic the final URL construction on Requests.swift L443 and throw URLError(.badURL)
with init(path: String ...)
, but I don't think I like one init throwable and the other not.
This would possibly allow some cleanup in makeURL
regarding your TODO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The initializer that accepts path
as a String
can fail to produce a URL
:
public init(path: String, method: HTTPMethod = .get, ...) {
self.url = URL(string: path) // Optional
Sources/Get/APIClientDelegate.swift
Outdated
@@ -56,7 +56,7 @@ public protocol APIClientDelegate { | |||
/// | |||
/// - returns: The URL for the request. Return `nil` to use the default | |||
/// logic used by client. | |||
func client(_ client: APIClient, makeURLFor url: String, query: [(String, String?)]?) throws -> URL? | |||
func client<T>(_ client: APIClient, makeURLForRequest request: Request<T>) throws -> URL? | |||
|
|||
// Deprecated in Get 1.0 | |||
@available(*, deprecated, message: "Please implement client(_:validateResponse:data:request:) instead. The current method is no longer used.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think that these deprecated methods can be removed in 2.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, absolutely!
/// Resource URL. Can be either absolute or relative. | ||
public var url: String | ||
public var url: URL? | ||
/// Request query items. | ||
public var query: [(String, String?)]? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if this was [URLQueryItem]?
on Request
but with convenience inits? I ask only because I personally don't work much with tuples.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also considered it, and I'm not sure yet. Tuples are probably not the ideal choice for this case. When I think about tuples, I usually think about a bag of values that are loosely related and there is no good name for them. That's not the case for the query items.
var request = Request(path: "/domain.tld")
request.query = [("name", "value1+value2")]
request.query = [URLQueryItem(name: "name", value: "value1+value2")]
Just a few questions but 👍 for everything moving forward!
My understanding of RFC 7231 is that |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 👍 a ExpressibleByStringLiteral
HTTPMethod
struct is how our pre-existing networking client was build while remaining compatible with CreateAPI so I like that approach being taken here
public init( | ||
path: String, | ||
method: HTTPMethod = .get, | ||
query: [(String, String?)]? = nil, | ||
body: Encodable? = nil, | ||
headers: [String: String]? = nil, | ||
id: String? = nil | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes sense to me. I was a bit confused that path
had been renamed to url
in 1.0, but it makes sense given the dual purpose.. But changing the underlying type to URL
and having this initialiser sounds good in terms of CreateAPI usage 👍
Just to confirm though, this is targeting version 2.0.0?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it used to serve both purposes, but both poorly. The new API should be much clearer.
Yes, I know I just released 1.0, but I want to address these issues earlier. Yes, I'll release it in a 2.0 because there are some breaking changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just my opinion, since there are already breaking changes I think it would be okay to just remove the old telescoping methods instead of at a later date. This is a foundational change and developers would have to be responsible for making the 2.0 major update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, I don't want to pollute the APIs, and it's still at the early stage.
I'm not sure what's the reasoning. I'm assuming it's caching. URLs must uniquely identify the resources. |
This MR addresses multiple design issues with the
Request
type in Get 1.0.1. Add support for both
URL
andString
In Get 1.0, request can only be initialized with a
String
that represents either a relative URL (path) or an absolute one.This doesn't match the convention used on Apple platforms where URLs are usually represented using
URL
type. Get 2.0 now has two separate initializer:2. Deprecate telescoping factory methods
Having a separate factory method per HTTP method is not elegant. Initially it was designed this way to prevent "GET" requests from being sent with an HTTP body which is not allowed by the spec and by
URLSession
. But since theRequest
type also has a public initializer without this check, it doesn't make much sense to only have it in one place.The factory methods are deprecated in Get 2.0 and there is also a new
HTTPMethod
type.This is more verbose than writing
.post("/user")
, but I think it's a non-issue, and the clarify should be the priority.3. Change the order of parameters
Previously,
method
was the first parameter, but it had a default value. The first parameter should not have the default value.4. Response type defaulting to
Void
In Get 1.0, there were actually not one, but two sets of factory methods (see p2). In the second set, the default response type (
Request<Response>
) was set toVoid
. It allows the user to avoid explicitly specifying the response type when it'sVoid
. But the initializer for the same type was missing, and Get 2.0 introduces it, so you can now write this:Rejected
The
Request
initializer has a lot of parameters and it can be cumbersome to use. I considered adding some convenience methods for creating the requests, for example:While it's nice to have, I don't think it belongs in the framework. You can achieve the same with simple mutable structs in Swift and the users can add convenience extensions "aftermarket":