[swift-server-dev] HTTP API Sketch v2

George Leontiev georgeleontiev at gmail.com
Sat Apr 8 21:12:53 CDT 2017


Hello everyone,

I’ve been following this conversation and think we missed something. One of Swift’s main benefits is it’s type system, which is much more expressive than other popular server-side languages (I’m looking at you Go). Now, there are certainly benefits to having a standard “HTTPRequest” type, whether it be a reference or value type. What is more powerful, however, is to allow the user to determine what they expect the structure of a particular Request or Response to be.
Earlier in this thread, I think someone dismissed protocols/generics because “at some point, we need to implement a concrete type”. I don’t agree with this. I think we can leverage the Swift type system to have something much better.

I recommend having protocols for HTTP{Request,Response}{Encodable,Decoder} types, which are driven by a encoder or decoder in the standard library. 
For sending requests, you could have:
protocol HTTPRequestEncodable {
	var method: String { get }
	var path: String { get }
	var queryParameters: [String:String] { get }
	…etc
}

When writing to the socket, and ONLY when writing to the socket, these methods will be called to serialize the data. The body may have a slightly more complex API to support streaming bodies (the main issue would be notifying the new driver when new data is available and differentiating between repayable and not-replayable requests).

On the server side, you can have (this is a rough sketch):
protocol HTTPRequestDecoder {
	mutating func processMethod(string)
	mutating func processPathComponent(string)
	mutating fund processHeader(string, string)
	… and so on
}
When reading off the socket, these methods can be called on the actual data which is in the socket’s buffer, with the user deciding how to represent the data. That way, if they only care about “GET”/“POST”, that can be represented as a 2-case enum, or if they care about more exotic methods, they can represent those as well without passing the cost of those exotic methods onto users who just want to use the simple case.

The types implementing these protocols would, of course be in a partial state for some of the decoding part, but that can be remedied with a validated() method (I welcome better names) which is called after processing is done and returns a validated type if all the fields are what the user expects them to be.

I can flesh out the APIs more if people are interested, but I think this is sufficient to communicate the idea, and I’d love to hear more feedback. 

There is a performance overhead to using protocols/generics, but I believe these can be effectively mediated by the compiler. Also, this does not preclude the standard library from providing a default HTTPRequest type which can leverage full module optimization to get the same performance as a simple concrete type.

- George



More information about the swift-server-dev mailing list