[swift-server-dev] HTTP API v0.1.0

Vladimir.S svabox at gmail.com
Wed Oct 4 12:55:31 CDT 2017

On 02.10.2017 19:30, Chris Bailey via swift-server-dev wrote:
> We spent some time updating and validating the HTTP API, along with creating a full set of API docs etc. In order to 
> make it easier for the wider community to build applications that use it to test out the API and provide feedback, I've 
> just tagged v0.1.0.

In addition to my previous message, I'd like to raise some concrete questions. I understand that most likely they were 
answered at some point of time during the discussions. But currently there is 0.1.0 version, some checkpoint, and so it 
attracts more attention of developers who did not participate yet in discussions and I think it is worth to summarize 
answers in some reply. So :

(I based my questions on examples of 'echo' and 'hello world' on https://github.com/swift-server/http and on 
documentation on https://swift-server.github.io/http/ )

1. What about change of writeHeader()/writeBody() to write() ? I see that PR was raised, but 0.1.0 is still uses the 
first form.

2. At the moment, when we enter into echo()/hello(), is _body_ of HTTP request already *downloaded*(received from 
socket) or not?
I assume it is not downloaded, and this is why we need this HTTPBodyProcessing return value, right?
What is the logic/strategy of reading a very large bodies of HTTP request from socket? Via chunks in HTTPBodyProcessing?

3. HTTPRequest is described as "A structure representing the headers from a HTTP request, without the body of the 
request.". If it is so, why not HTTPRequestHeaders, or HTTPRequestInfo, or HTTPRequestDescription etc ?
IMO HTTPRequest mentally includes all parts of request, including content. I was very confused by the name when trying 
to understand the examples.

4. Returning of HTTPBodyProcessing from handler function.

4.a. If the body 'ignored', does this mean that the body content of the request will not be read from socket at all?
I.e. what is the purpose and logic behind .ignored?

4.b. As was said, HTTPBodyProcessing is long and non-meaning name. First it is not clear *which* body it will process 
and why we need this process at all and why some processing closure is a return of our handler function.
Was it discussed(and if so, why declined) to implement this in some another form, not as result value?
For example:
func echo(http: HTTPContext, request: HTTPRequest, response: HTTPResponse) {
	response.writeHeader(status: .ok)
	http.serve { (chunk, stop) in ..

5. HTTPResponseWriter ('response' variable) has a methods to write data. But for reading the data we use 
HTTPBodyProcessing, for which processing closure returned as associated value for enum instance.
Did you think about introducing of a HTTPRequestReader, which encapsulates Request details(request's headers) and 
methods to read the body?
Then, we probably can have a very nice and Swifty handler code with clear naming and purpose :
func echo(request: HTTPRequestReader, response: HTTPResponseWriter) {
	response.writeHeader(status: .ok)
	request.read { chunk in
		switch chunk {
         	case .chunk(let data):
             		response.writeBody(data) { result in
				switch result {
                 		case .ok:
				case .error:
         	case .end:
func hello(request: HTTPRequestReader, response: HTTPResponseWriter) {
	response.writeHeader(status: .ok)
	response.writeBody("Hello, World!")

, then current HTTPRequest instance could be accessed via request.info property or similar.
The logic behind the scene could be the same : check if request contains a closure assigned in read() method and then 
use it.
In client, this will be RequestWriter and ResponseReader accordingly.

6. HTTPBodyChunk has .failed case. Why not .error like in Result in completion handler. I think they should be the same 
for better uniform of code.

7. HTTPResponseWriter.done() and HTTPBodyChunk.end. I believe it will be nice to call them both the same(done or end) 
for symmetry, so we can have in code:
switch chunk {
case .done:
switch chunk {
case .end:

8. Why we need convenience functions that just hides completion handler and so make it easy to not process the .error 
case in Result of completion handler? (I.e. make it easy to skip error checking). Shouldn't they at least trow exceptions?
If I understand correctly, the 'hello world' example should looks at least like this:
func hello(request: HTTPRequest, response: HTTPResponseWriter ) -> HTTPBodyProcessing {
	try? response.writeHeader(status: .ok)
	try? response.writeBody("Hello, World!")
	try? response.done()

	return .discardBody

9. write*(..) functions in HTTPResponseWriter. Are they writing directly to socket or they are buffered?

10. What is the purpose of HTTPResponseWriter.done() function?

Thank you for your time and for answers.

> You can see that here:
>          HTTP 0.1.0 https://github.com/swift-server/http/tree/0.1.0
> I've also submitted a PR to add the HTTP API into the set servers/frameworks being tested as part of the "Which is the 
> fastest?" benchmark.
> In parallel, Gelareh Taban has been working on adding providing a TLS API, and HTTPS support to the HTTP project. You 
> can see her incubator work here:
>          HTTPS incubator: https://github.com/gtaban/http
>          TLS incubator:        https://github.com/gtaban/TLSService.git <https://github.com/gtaban/TLSService.git>
> The aim is to validate and include the TLS work in v0.2.0, along with feedback from the wider community on the existing 
> API surface, fixing bugs, and working on implementing outstanding items like trailer support, backpressure, etc.
> Chris
> Unless stated otherwise above:
> IBM United Kingdom Limited - Registered in England and Wales with number 741598.
> Registered office: PO Box 41, North Harbour, Portsmouth, Hampshire PO6 3AU
> _______________________________________________
> swift-server-dev mailing list
> swift-server-dev at swift.org
> https://lists.swift.org/mailman/listinfo/swift-server-dev

More information about the swift-server-dev mailing list