lammertb / libhttp

Multi platform HTTP and HTTPS library
MIT License
958 stars 131 forks source link

Why? #41

Open AMorporkian opened 7 years ago

AMorporkian commented 7 years ago

I may be off base here, but whenever I find a new library I try to discern the motivation for creating it. Why are you making this library? What does it address that other libraries don't? Not just the technologies, what are the philosophical differences you have with other libraries that led to you creating this library as opposed to contributing to another that you derived from?

By the way, I do love it. I just want other people to be able to enjoy it without prejudice.

marcoscleison commented 7 years ago

@AMorporkian I am not the library developer but I am very happy to find this library. Libmicrohttp is not well documented, no websocket and not license friendly. :+1:

vladyio commented 7 years ago

It is actually a good question, because it can serve as a motivation to (not) use it in projects.

lammertb commented 7 years ago

Thanks for your question which is very good one.

Some time ago I was in need for an embedded HTTP server for my main product which is written in C. The product is a high availability process controller running on multiple platforms. I decided that writing something myself would take too much time and would produce something with too many bugs and only limited functionality. Mongoose and its successor Civetweb were the most mature candidates for the job as an external add-on. Mongoose stopped being MIT licensed some years ago and Civetweb emerged as the fork of the last MIT licensed Mongoose release. I therefore decided to use Civetweb as the HTTP add-on in my project.

Civetweb is based on a merge file of all individual source files of Mongoose and has been that way since. The good side of an amalgamation source file is that version control and distribution to other systems is relatively easy. The problem however is maintenance. It soon proved to be quite an experience to find where to add enhancements and fix bugs.

With a high availability application I couldn't accept to have an embedded component in my project over which I didn't have full oversight. My first action was therefore to study the full source code and try to determine the functionality of all the individual structures and functions. As a result I wrote the current Civetweb API documentation and committed more than 1700 lines of documentation to that project. At that moment I had a basic understanding of the structure of the program and how the several routines interacted.

But I still wasn't convinced that the 18000 lines of source code in one single file would be easy to debug if a real problem emerged. I therefore decided to split the source code into a few hundred smaller files, each containing only one component. At that moment, my compiled version of the API was still Mongoose/Civetweb compatible, although at source code level it would already be almost impossible to merge my changes with the Civetweb parent project.

While splitting the original source into smaller components, I discovered some deprecated functionality which was still there for backward compatibility with older Mongoose versions. Also IPv6 functionality was rather limited and I had plans to add other server side script engines as addition to the Lua functionality.

The most important discovery was however that somewhere in the development process the original Mongoose developer Sergey Lyubka had shifted from a thread based approach to an event driven approach but he never finished his work in the MIT licensed version of Mongoose. The Civetweb implementation contains therefore parts of both worlds. You have both a pool of pre-started threads to accept connections and a set of callback functions to handle incoming requests.

If I wanted to shift completely to the event driven model, which is my goal for performance and memory usage considerations, remove the deprecated functionality, add full IPv6 functionality and add a module system to load server side scripting engines, there would be no API compatibility anymore with Mongoose and Civetweb.

To not confuse current users of Mongoose and Civetweb , I decided to change all function names and replace the mg prefix of the civetweb functions with the httplib prefix. On average the functionality of the mg_XXX and httplib_XXX functions and structures is still the same, but someone porting their project from one library to another is now triggered to manually check each use of the library functions to see if the outcome is still the same.

So in short, the reasons to add an additional leaf to the Mongoose/Civetweb family tree are:

Lammert

jordanbray commented 7 years ago

As an aside, I think a lot of this information should be on https://www.libhttp.org/. I would at least let people know you are using an event driven architecture over threads. After reading your API, I had assumed you were using one thread per connection due to all the pthread functions.