HTTP Post example


(Georgios Moschovitis) #1

One thing that's missing from the NIOHTTP1Server sample is an example of handling an HTTP POST request (e.g. a form submission).

I tried to handle a form submission and I was under the impression that I would receive the post data as a HTTPServerRequestPart.body within the channelRead method. But, it seems, that's not the case (or I did something wrong).


(Helge Heß) #2

Well, no. Because the request body can be arbitrarily large, NIO streams the data to your handler in an asynchronous fashion.

In a naive implementation, you can collect the bytes until you get an end part, and then parse the form. You can find an example of such a naive implementation here: https://github.com/SwiftObjects/SwiftObjects/blob/develop/Sources/SwiftObjects/NIO/WONIOHandler.swift#L28 (this reads the data until it is fully read), and here you have a basic form-submission parser (url encoded, not multipart): https://github.com/SwiftObjects/SwiftObjects/blob/develop/Sources/SwiftObjects/Core/WORequest.swift#L158


(Georgios Moschovitis) #3

Many thanks for the example, I will have a look.

Really appreciated!


(Georgios Moschovitis) #4

My problem is that I get only a single .head HTTPServerRequestPart, i.e. no .body part at all.


(Helge Heß) #5

More details please. How do you trigger the request? What makes you sure that there is a body, etc?


(Georgios Moschovitis) #6

I trigger the request with this form

<form method="post" action="/sign-in">
    <p>
        <input type="text" name="username" />
    </p>
    <p>
        <input type="password" name="password" />
    </p>
    <p>
        <button>Sign in</button>
    </p>
</form>

The only request part I get is:

head(HTTPRequestHead { 
method: POST, 
uri: "/sign-in", version: HTTP/1.1, 
headers: [("Host", "localhost:8000"), ("Connection", "keep-alive"), ("Content-Length", "31"), ("Cache-Control", "max-age=0"), ("Origin", "http://localhost:8000"), ("Upgrade-Insecure-Requests", "1"), ("Content-Type", "application/x-www-form-urlencoded"), ("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36"), ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"), ("Referer", "http://localhost:8000/sign-in"), ("Accept-Encoding", "gzip, deflate, br"), ("Accept-Language", "en-US,en;q=0.9,el;q=0.8")] 
})

(Helge Heß) #7

That looks good, you should definitely get a body part. Maybe show your handler code too?


(Georgios Moschovitis) #8

Oops, I found the issue, an 'upstream' handler was 'silencing' .body and .end part events :(
Sorry for wasting your time, at least the examples in your first reply will be useful for others too.

Thank you.