[swift-server-dev] HTTPMethod, was: Re: Next HTTP API meeting

Helge Heß me at helgehess.eu
Thu Mar 23 08:50:44 CDT 2017

BTW the Swizzlr I think accidentally send me a response as a private email:

On 23 Mar 2017, at 12:16, Swizzlr <me at swizzlr.co> wrote:
> I don't see what benefit an enumeration of HTTP methods would provide. If it's a string, you can still case match.

I think it is very wasteful for a low level parser, but it is easy to agree on. Since you also want to use strings for header keys it may actually be the straight forward thing to do.

On 23 Mar 2017, at 13:35, Logan Wright <logan at qutheory.io> wrote:
> I think it might be lowercase to stick w/ the official Apple swift 3 guidelines, but definitely agree on some type of extensibility. Currently I've been naming that 'other' in general. With that said, that's kind of why I included a String in my proposal. If we can focus on the actual components of the parser and let users define models as much as possible, then it offloads a lot of our opinions into respective frameworks. In terms of Method, here's how I currently have it for discussion:
> enum Method {
>     case get, post, put, patch
>     case other(String)
> }
> I think in addition to adding new official methods (I might be wrong here, need to double check)

You are saying that you would add all currently RFC’ed methods to that enum, right? Remember that you can’t add additional ‘case’ values to the enum later, that wouldn’t even be API compatible.

So you think that this is an OK thing?:

  switch method {
    case .get: …
    case .post: ...
    case other(let m) where m == “PATCH”: ...

That would be very common code if Swift Server would have been released in 2009, for sure we’ll get new methods (e.g. BATCH? ;-) in 2017+ leading to the same issue.

I think it may be worth considering something like that:

  struct HTTPMethod {
    // can/should be done as a RawRepresentable? Don’t know :-)
    static let GET : UInt8 = 0
    … all we know at the time …

    let code : UInt8
    func == (lhs: HTTPMethod, rhs: String)

It looks less Swifty, but this way the thing would be extensible and fast while not breaking the API or ABI when adding new methods to the core library.

Another way would be to fix it to a specific RFC like 2616 and use Strings for anything else. That would include PATCH and provide at least some arguable consistency and stability.

  enum HTTP11Method {
    case other(String) // PATCH, MKCALENDAR, SUBSCRIBE etc

(I don’t care too much about the case, upper feels right though for HTTP)

> but I believe server/clients can define any method they might want to use between them

Yes, for practical purposes. Parts of the infrastructure (intermediate proxies and such) may reject methods they don’t know, but that issue is less common with https. You can use OPTIONS to figure out the methods a URL endpoint supports.

Funny enough a notable exception to this is anything using the Node.js http_parser. That will throw an error for any method unknown (making API stable extensibility even more important for them, example: https://github.com/nodejs/http-parser/pull/179).

There is also the issue that methods are often widely used (sometimes for years) in draft states before a final RFC specs them (e.g. RFC 5789 was only officially RFC’ed in 2010).


P.S.: Does Swift 4 propose any way to intern strings? That is also a nice way to do this kind of thing and still get decent performance (essentially what Cocoa Swift does for NSNotification names).

> , so I completely agree with you that whatever we have will definitely need some type of extensibility (whatever we call it) to conform to spec.
> On Thu, Mar 23, 2017 at 12:12 PM Helge Heß via swift-server-dev <swift-server-dev at swift.org> wrote:
> On 23 Mar 2017, at 11:18, Logan Wright via swift-server-dev <swift-server-dev at swift.org> wrote:
> > some types that I think are pretty unambiguous like HTTPMethod
> May I ask how that would look like in your opinion? I was thinking about that too, and I find it rather hard to come up with a really good solution.
> The desirable thing would be an enum, but such can’t be extended in Swift w/o an associated value. Like so
>   enum HTTPMethod {
>     case ExtendedMethod(String)
>   }
> But I think this would be pretty weird for ‘late’ methods and you’d end up with code like
>   switch method {
>     case .get: ...
>     case ExtendedMethod(“PATCH”): ...
>   }
> which will look really weird quickly. New methods do not come around every day, but more often than you might think (note explicit support for arbitrary ones in todays XHR, this used to support only GET/POST, hence the xhr-method header thing).
> hh
> _______________________________________________
> swift-server-dev mailing list
> swift-server-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-server-dev

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 842 bytes
Desc: Message signed with OpenPGP using GPGMail
URL: <https://lists.swift.org/pipermail/swift-server-dev/attachments/20170323/1d562bf2/attachment.sig>

More information about the swift-server-dev mailing list