Forum > Third party
HTTP/2+HTTP/1.1+WebSocket server with Free Pascal
iLya2IK:
The fpweb library is certainly good, but it clearly lacks modern features - namely, full-fledged http/1.1 with persistent connections, and also http/2. I completed my search for the desired analog by creating a server with all the necessary. I would like to present to your attention my project - WCHTTPServer.
The project builds on the fcl-web library and extends it to increase functionality:
Client management using cookies (saving and maintaining sessions).
* Saving information about clients and sessions in SQLite database.
* Saving information about the latest requests and saving logs in SQLite database.
* Multithreading preparation and execution of requests based on thread pools e.g. helpful classes to work with EventSources.
* Client rankings based on the frequency of client requests.
* Built-in support for gzip and deflate compression methods.
* The WebSocket (RFC 6455) protocol is supported with the "permessage-deflate" extension (RFC 7692).
* Ability to start the server both in HTTP/2 (RFC 7540) mode and in HTTP/1.1 mode.
* Modified OpenSSL modules (added necessary TLS extensions) in order to create and maintain HTTP/2 connections.
* Added the ability to save the master key and a random set of client data on the server-side (necessary for debugging TLS dumps using WireShark).
* Works under both Windows and Linux
Link to project on GitHub : https://github.com/iLya2IK/wchttpserver
At the moment, the server follows the RFC 7540 specification fairly closely, but I continue to test and debug to meet a number of non-obvious protocol requirements. For testing, I use the h2spec and h2load utilities.
--- Code: XML [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---# h2spec -p 8080 http2 -t -k -o 2094 tests, 91 passed, 0 skipped, 3 failedHypertext Transfer Protocol Version 2 (HTTP/2) 4. HTTP Frames 4.2. Frame Size × 1: Sends a DATA frame with 2^14 octets in length -> The endpoint MUST be capable of receiving and minimally processing frames up to 2^14 octets in length. Expected: HEADERS Frame (stream_id:1) Actual: Connection closed Comment: Error in h2spec - DATA payload size didn't equal the value of "content-length" header. 5. Streams and Multiplexing 5.5. Extending HTTP/2 × 2: Sends an unknown extension frame in the middle of a header block -> The endpoint MUST treat as a connection error of type PROTOCOL_ERROR. Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR) Connection closed Actual: Timeout Comment: I didn't find any references in RFC 7540 that unknown extension frame in the middle of a header block should cause a connection error 8. HTTP Message Exchanges 8.1. HTTP Request/Response Exchange 8.1.2. HTTP Header Fields 8.1.2.2. Connection-Specific Header Fields × 1: Sends a HEADERS frame that contains the connection-specific header field -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR. Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR) RST_STREAM Frame (Error Code: PROTOCOL_ERROR) Connection closed Actual: DATA Frame (length:845, flags:0x01, stream_id:1) Comment: I know that this violates the requirements of RFC 7540, but I sincerely consider them redundant and the type of reaction to the header value should remain on the server side
And here are the results of testing with h2load
--- Code: XML [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---# h2load -n32000 -c32 -m10 --header=connection:keep-alive --header=cookie:cid=11 https://localhost:8080 starting benchmark...spawning thread #0: 32 total client(s). 32000 total requestsTLS Protocol: TLSv1.2Cipher: ECDHE-RSA-AES256-GCM-SHA384Server Temp Key: X25519 253 bitsApplication protocol: h2progress: 10% doneprogress: 20% doneprogress: 30% doneprogress: 40% doneprogress: 50% doneprogress: 60% doneprogress: 70% doneprogress: 80% doneprogress: 90% doneprogress: 100% done finished in 17.22s, 1858.68 req/s, 1.54MB/srequests: 32000 total, 32000 started, 32000 done, 32000 succeeded, 0 failed, 0 errored, 0 timeoutstatus codes: 32000 2xx, 0 3xx, 0 4xx, 0 5xxtraffic: 26.46MB (27746560) total, 126.38KB (129408) headers (space savings 95.01%), 25.79MB (27040000) data min max mean sd +/- sdtime for request: 16.59ms 327.96ms 150.22ms 35.42ms 77.80%time for connect: 7.17ms 1.96s 1.15s 618.49ms 62.50%time to 1st byte: 59.55ms 2.00s 1.20s 629.72ms 62.50%req/s : 58.09 72.88 61.87 4.42 81.25% # h2load -n32000 -c32 -t8 -m1 --h1 --header=connection:keep-alive --header=cookie:cid=11 https://localhost:8080-t: warning: the number of threads is greater than hardware cores.starting benchmark...spawning thread #0: 4 total client(s). 4000 total requestsspawning thread #1: 4 total client(s). 4000 total requestsspawning thread #2: 4 total client(s). 4000 total requestsspawning thread #3: 4 total client(s). 4000 total requestsspawning thread #4: 4 total client(s). 4000 total requestsspawning thread #5: 4 total client(s). 4000 total requestsspawning thread #6: 4 total client(s). 4000 total requestsspawning thread #7: 4 total client(s). 4000 total requestsTLS Protocol: TLSv1.2Cipher: ECDHE-RSA-AES256-GCM-SHA384Server Temp Key: X25519 253 bitsApplication protocol: http/1.1progress: 10% doneprogress: 20% doneprogress: 30% doneprogress: 40% doneprogress: 50% doneprogress: 60% doneprogress: 70% doneprogress: 80% doneprogress: 90% doneprogress: 100% done finished in 29.06s, 1101.26 req/s, 1.01MB/srequests: 32000 total, 32000 started, 32000 done, 32000 succeeded, 0 failed, 0 errored, 0 timeoutstatus codes: 32000 2xx, 0 3xx, 0 4xx, 0 5xxtraffic: 29.39MB (30816000) total, 2.53MB (2656000) headers (space savings 0.00%), 25.79MB (27040000) data min max mean sd +/- sdtime for request: 7.99ms 208.16ms 26.31ms 5.94ms 93.71%time for connect: 8.22ms 3.08s 1.25s 943.18ms 62.50%time to 1st byte: 99.48ms 3.12s 1.31s 913.25ms 62.50%req/s : 34.42 38.74 36.31 1.25 62.50%
iLya2IK:
The latest update adds support for the websocket protocol, and therefore the demo site has been changed. As an example of interaction over the websocket protocol, the JSON-RPC application level protocol (well, or some of its similarity ::) - you can change it to your own) is used. Now I am working on adding the permessage-deflate extension (RFC 7692)
Leledumbo:
While I admire this work, I find it hard to not have a clear separation between which files belong to the library/package, demo/examples and so on. See fcl-web's own directory structure as an example.
iLya2IK:
--- Quote from: Leledumbo on May 14, 2021, 05:23:49 am ---While I admire this work, I find it hard to not have a clear separation between which files belong to the library/package, demo/examples and so on. See fcl-web's own directory structure as an example.
--- End quote ---
Yes, I get it - this is really a problem. I will start reworking the repository in the near future.
iLya2IK:
The structure of the project has been put in order. Added lpk file. The "permessage-deflate" extension for websocket has been fully implemented.
Navigation
[0] Message Index
[#] Next page