m1.txt 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. Dear all,
  2. We're happy to announce reaching the first milestone for the
  3. STF-funded MHD 2.0 project, which is completing the MHD HTTP header
  4. and thus the design for the next generation API. We have now
  5. spent several months iterating between discussing, designing,
  6. optimising, editing, and testing details and are finally
  7. happy with the result.
  8. Key objectives for us were:
  9. - simplify application code that uses MHD
  10. - keep the API and the MHD code size small
  11. - ensure the API is extensible
  12. - enable use of different TLS backends, avoid backend-specific
  13. settings to use backends in the same way.
  14. - make API work with HTTP 1.x, HTTP/2 and HTTP/3
  15. - preserve or improve portability across platforms
  16. - stay compatible to a wide range of C and C++ compilers
  17. The main changes these objectives inspired are to:
  18. - Split the MHD_AccessHandlerCallback functionality into
  19. various separate callbacks to keep the API simple for
  20. simple requests while allowing complex logic to be
  21. incrementally introduced via the new "struct MHD_Action".
  22. Main effects:
  23. * improved type safety
  24. * client code most likely to always need all arguments
  25. passed to callbacks, while keeping rarely used
  26. arguments available via the introspection API
  27. * harder or impossible to make calls at the wrong time
  28. or to forget to do key processing steps
  29. * clients more likely to avoid repeated URL dispatching
  30. * Easier to add commonly used features like a generic
  31. URL dispatcher
  32. * Improved modularity, easier to not compile in some
  33. features (actions) to minimize code size
  34. - We changed how MHD is configured, providing a new
  35. strongly-typed but still extensible mechanism
  36. to set options, avoiding the use of 'varargs' for
  37. options while also not introducing new symbols for
  38. any kind of option. The new construction uses
  39. either inline functions or macros depending on the
  40. compiler to initialize a struct with a variant union;
  41. as a result, application developers get the experience
  42. of using well-typed functions, while no such functions
  43. actually exist in the library, keeping the code size
  44. minimal, especially if features are not even used :-).
  45. - Unified the way how settings are used for daemon,
  46. connection and response objects.
  47. - Removed the separation of options and flags and
  48. made it harder to pass inconsistent options
  49. - improved terminology across the API, in particular by
  50. eliminating confusion between 'request' and 'connection',
  51. but also by introducing new 'nouns' such as 'session',
  52. 'stream' and 'action', but also 'String' which returns a
  53. 'String' that is both 0-terminated but ALSO has a
  54. known length (eliminating need for applications
  55. to call strlen() on all strings returned by MHD).
  56. Also changed the API to use more consistent
  57. prefixes for related functions by using
  58. "MHD_subject_verb_object" naming convention
  59. - significantly simplified for application processing of
  60. client's upload. Removed the need for troublesome (for
  61. application) incremental processing (especially problematic
  62. for forms processing), while keeping automatic limits
  63. for memory allocations, preventing by design a wide range
  64. of remote attacks.
  65. - Added unified and detailed introspection API for library,
  66. daemon, connection, stream and request objects.
  67. The API is designed in the same way for all object, simplifying
  68. use for the application. The new API is detailed and allow
  69. application to extract any required information in a simple
  70. way. Also separated "fixed" and "dynamic" properties of objects
  71. for letting compiler optimise application code better.
  72. - Integrated HTTP status into the response object, as
  73. this is way more logical and we are aware of various
  74. implementations being forced to basically pass them
  75. around as a tuple.
  76. - simplified API for common-case of one-shot responses by
  77. eliminating need for destroy response in most cases
  78. - Improved portability by avoiding fixed types, like uint32_t,
  79. as they may not exist on some platforms. Instead use
  80. types like uint_fast32_t. Avoided use of enums with very
  81. large bitmasks as 'int' could be just 16 bits on some platforms
  82. resulting in enum values higher than 65535 being silently dropped.
  83. - Improved possibility of use of zero-copy style for parsing
  84. uploaded data, including of the PostProcessor parser while
  85. still allowing applications to do stream processing if data
  86. does not fit into main memory. This both simplifies usage
  87. in the common case where uploaded data is small, while also
  88. nicely supporting use-cases with large data streams.
  89. - Made responses unmodifiable after first use. Modifiable responses
  90. cannot be thread-safe. However, MHD-generated headers (Date,
  91. Connection/Keep-Alive) are part of the *request* and do not count
  92. as part of the immutable "response" here. Removed "footers" from
  93. responses. With unmodifiable responses everything should be "headers".
  94. However, footers are supported as part of a *request* instead.
  95. - Move response codes from MHD_HTTP_xxx namespace to MHD_HTTP_CODE_xxx
  96. namespace. This avoids potential clashes with other MHD constant names.
  97. - Introduced various new "enums" especially for constants
  98. introduced in HTTP/2 where use of these constants can
  99. then avoid having to map between protocol numbers and
  100. strings (but applications may still also use the strings)
  101. This also includes better status codes returned from
  102. API calls to diagnose issues (no more just "YES/NO")
  103. - Let application to use request methods as a enum, avoid repeated
  104. string comparison by sharing result of the already performed
  105. internal detection of the request method. Keep ability to
  106. use non-standard HTTP requests methods if needed via use
  107. of introspection API.
  108. - Introduced "MHD_APP_SOCKET_CNTX_TYPE" hack to allow
  109. applications to improve type-safety by overriding
  110. the type of "closure" arguments instead of using
  111. "void *" pointers.
  112. - Significant re-design of the event loop APIs to simplify integrating
  113. MHD with external event loops while preserving O(1) processing cost.
  114. - Added many annotations to help compiler determine invariants (if
  115. supported by the compiler), such as arguments not being NULL, etc.
  116. - Removal of various legacy symbols only exported for API compatibility.
  117. While these are lots of changes, we want to give you a first brief preview of
  118. how this will impact client code using the library. Here is an example of how
  119. clients used to initialize the MHD daemon (from demo.c):
  120. OLD>>
  121. d = MHD_start_daemon (
  122. MHD_USE_AUTO | MHD_USE_INTERNAL_POLLING_THREAD
  123. | MHD_USE_ERROR_LOG,
  124. (uint16_t) port,
  125. NULL, NULL,
  126. &generate_page,
  127. NULL,
  128. MHD_OPTION_CONNECTION_MEMORY_LIMIT,
  129. (size_t) (256 * 1024),
  130. #ifdef PRODUCTION
  131. MHD_OPTION_PER_IP_CONNECTION_LIMIT,
  132. (unsigned int) (64),
  133. #endif
  134. MHD_OPTION_CONNECTION_TIMEOUT,
  135. (unsigned int) (120 /* seconds */),
  136. MHD_OPTION_THREAD_POOL_SIZE,
  137. (unsigned int) NUMBER_OF_THREADS,
  138. MHD_OPTION_NOTIFY_COMPLETED,
  139. &response_completed_callback,
  140. NULL,
  141. MHD_OPTION_END);
  142. if (NULL == d)
  143. error();
  144. <<
  145. This was one big variadic mess, and getting any of the
  146. types wrong for any of the options could result in
  147. trouble, sometimes depending on the target platform.
  148. With MHD 2.0, the same code will look like this:
  149. NEW>>
  150. d = MHD_daemon_create (&generate_page,
  151. NULL);
  152. if (MHD_SC_OK !=
  153. MHD_daemon_options_set (
  154. d,
  155. MHD_D_OPTION_BIND_PORT (MHD_AF_DUAL, port),
  156. MHD_D_OPTION_WM_WORKER_THREADS (NUMBER_OF_THREADS),
  157. MHD_D_OPTION_CONN_MEMORY_LIMIT (256*1024),
  158. MHD_D_OPTION_PER_IP_LIMIT (64),
  159. MHD_D_OPTION_DEFAULT_TIMEOUT (120),
  160. MHD_D_OPTION_NOTIFY_CONNECTION (&response_completed_callback,
  161. NULL)))
  162. error();
  163. if (MHD_SC_OK !=
  164. MHD_daemon_start (d))
  165. error();
  166. <<
  167. Note that you can can call MHD_daemon_options_set() multiple times if you need
  168. to handle errors for individual options. Thanks to extensive trickery on our
  169. part, the resulting type-safe code should *also* be almost as compact and fast
  170. as the previous version (mostly, this adds two additional library API calls,
  171. but in return you can get more precise status codes back).
  172. While we thought hard about the new API and poured our experience into the
  173. re-design, we still might have overlooked something and thus value community
  174. feedback.
  175. We thank Sovereign Tech Fund for funding this work.
  176. Happy hacking!
  177. Christian & Evgeny