cpp-httplib
cpp-httplib copied to clipboard
support custom plugins for HTTP 101 protocol switch
Adds a way to add handlers for various protocols and support alternate protocols which use HTTP for initial negotiation.
We will not be responsible for implementing any of those handlers ourselves, but this should at least make it possible for downstream developers to insert their own middleware to partially handle websockets, IRC or other protocols within the same client or server. I have successfully created an example websocket client plugin with bidirectional support, but have not published it as it seems to have problems with high traffic flow and compatibility with some servers.
cleaned up and published the example websocket plugin, but for now not sure how to identify an unexpected disconnect
@PixlRainbow, thank you for working on this. It looks very interesting enhancement!
but for now not sure how to identify an unexpected disconnect
Could is_socket_alive be used for this unexpected disconnect check?
https://github.com/yhirose/cpp-httplib/blob/9e0ff7ba54b7736b146ecb9512196ce7dc2e4904/httplib.h#L2365-L2374
Oddly enough, stability issues with high traffic flow only seem to occur in plain http and not in encrypted https. It appears raw TCP sockets have a chance to drop a byte or two every so often, which is enough to break my websocket example implementation.
I have noticed another issue that a few servers will simply jump directly to another protocol with HTTP 200 code without going through standard HTTP 101 signalling and negotiation. Web browsers seem to be able to handle these cases fine, but I suspect that is because they have the benefit of having an API dedicated to websocket. May need to add an extra method to allow the user to force a protocol type.
I don't intend to create an example for the server side, but I added server side support to have feature parity between client and server.
@yhirose ?
@PixlRainbow, sorry for the late reply. I'll take a look at it when I have time.
@PixlRainbow, I just wonder what the comment 'NOT PRODUCTION READY!' in example/websocket-plugin.cpp means. Does it mean that making a production level WebSocket implementation is too hard with this extension?
I really appreciate your efforts though, I cannot picture how other users including myself can see real benefit from this pull request. If users want a production level WebSocket solution, I'd recomment uWebSockets which is fully tested for WebSocket support.
This is a general plugin API. It is not specific to websocket. The websocket code in the example folder is provided merely as an example as to how one could build a plugin to handle alternate protocols. This pull request does not make any websocket-specific changes to httplib itself.
The "not production ready" comment is a reference to how the "example code" is not meant for direct implementation in a production environment; in production, a user would have to consider other things like setting up a custom thread pool implementation and designing their own code for reusability.
It is similar to how we have an example for SSE in the examples folder that makes use of the content provider/receiver API, but SSE is not directly implemented inside httplib.
A real production use case is that a user could use this API to build an adapter between httplib and an existing websocket library to provide the websocket support on the same network port. Or perhaps instead of websocket, they could build their own adapter that allows them to handle http/2.0 requests without requiring us to directly maintain the actual protocol. Or more likely, they can use http 101 as negotiation onto a TCP/TLS protobuf stream.
Oddly enough, stability issues with high traffic flow only seem to occur in plain http and not in encrypted https. It appears raw TCP sockets have a chance to drop a byte or two every so often, which is enough to break my websocket example implementation.
I have noticed another issue that a few servers will simply jump directly to another protocol with HTTP 200 code without going through standard HTTP 101 signalling and negotiation. Web browsers seem to be able to handle these cases fine, but I suspect that is because they have the benefit of having an API dedicated to websocket. May need to add an extra method to allow the user to force a protocol type.
Not sure if you have fixed this already, but a few years ago I fixed this problem in a huge open source networking library. What happens is fairly simple actually, when you do a tcp READ, it may or may not have all bytes ready, it may give you 300 bytes out of 310, you have to keep calling tcp read and keep inserting at the end of your buffers until all the bytes you expect to receive have arrived. This situation only happens in high traffic situations, which is why many people implement on top of TCP wrong(they never catch this situation when testing). The TCP protocol makes it impossible to drop bytes, meaning, if you are dropping bytes with your high level read, it simply means you didn't pull all bytes, since a few bytes weren't available yet when you did your TCP read, and you didn't keep polling for more bytes.
it may give you 300 bytes out of 310
I do keep polling the Stream interface though, and I make use of the returned value of "number of bytes read"; I don't just assume that the buffer will always be filled. I wonder if the httplib Stream interface is dropping unread bytes before I can read them.