Recent

Author Topic: HTTP/2+1.1 server with Free Pascal  (Read 521 times)

iLya2IK

  • New Member
  • *
  • Posts: 10
HTTP/2+1.1 server with Free Pascal
« on: February 26, 2021, 05:26:41 pm »
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.
  • Ability to start the server both in HTTP/2 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  [Select][+][-]
  1. # h2spec -p 8080 http2 -t -k -o 20
  2. 94 tests, 91 passed, 0 skipped, 3 failed
  3. Hypertext Transfer Protocol Version 2 (HTTP/2)
  4.   4. HTTP Frames
  5.     4.2. Frame Size      
  6.       × 1: Sends a DATA frame with 2^14 octets in length
  7.         -> The endpoint MUST be capable of receiving and minimally processing frames up to 2^14 octets in length.
  8.            Expected: HEADERS Frame (stream_id:1)
  9.              Actual: Connection closed
  10.             Comment: Error in h2spec - DATA payload size didn't equal the value of "content-length" header.  
  11.  
  12.   5. Streams and Multiplexing
  13.     5.5. Extending HTTP/2      
  14.       × 2: Sends an unknown extension frame in the middle of a header block
  15.         -> The endpoint MUST treat as a connection error of type PROTOCOL_ERROR.
  16.            Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
  17.                      Connection closed
  18.              Actual: Timeout
  19.             Comment: I didn't find any references in RFC 7540 that unknown extension frame in the middle
  20.                      of a header block should cause a connection error
  21.  
  22.   8. HTTP Message Exchanges
  23.     8.1. HTTP Request/Response Exchange
  24.       8.1.2. HTTP Header Fields
  25.         8.1.2.2. Connection-Specific Header Fields          
  26.           × 1: Sends a HEADERS frame that contains the connection-specific header field
  27.             -> The endpoint MUST respond with a stream error of type PROTOCOL_ERROR.
  28.                Expected: GOAWAY Frame (Error Code: PROTOCOL_ERROR)
  29.                          RST_STREAM Frame (Error Code: PROTOCOL_ERROR)
  30.                          Connection closed
  31.                  Actual: DATA Frame (length:845, flags:0x01, stream_id:1)
  32.                 Comment: I know that this violates the requirements of RFC 7540, but I sincerely consider them
  33.                          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  [Select][+][-]
  1. # h2load -n32000 -c32 -m10 --header=connection:keep-alive --header=cookie:cid=11  https://localhost:8080        
  2. starting benchmark...
  3. spawning thread #0: 32 total client(s). 32000 total requests
  4. TLS Protocol: TLSv1.2
  5. Cipher: ECDHE-RSA-AES256-GCM-SHA384
  6. Server Temp Key: X25519 253 bits
  7. Application protocol: h2
  8. progress: 10% done
  9. progress: 20% done
  10. progress: 30% done
  11. progress: 40% done
  12. progress: 50% done
  13. progress: 60% done
  14. progress: 70% done
  15. progress: 80% done
  16. progress: 90% done
  17. progress: 100% done
  18.  
  19. finished in 17.22s, 1858.68 req/s, 1.54MB/s
  20. requests: 32000 total, 32000 started, 32000 done, 32000 succeeded, 0 failed, 0 errored, 0 timeout
  21. status codes: 32000 2xx, 0 3xx, 0 4xx, 0 5xx
  22. traffic: 26.46MB (27746560) total, 126.38KB (129408) headers (space savings 95.01%), 25.79MB (27040000) data
  23.                      min         max         mean         sd        +/- sd
  24. time for request:    16.59ms    327.96ms    150.22ms     35.42ms    77.80%
  25. time for connect:     7.17ms       1.96s       1.15s    618.49ms    62.50%
  26. time to 1st byte:    59.55ms       2.00s       1.20s    629.72ms    62.50%
  27. req/s           :      58.09       72.88       61.87        4.42    81.25%
  28.  
  29. # h2load -n32000 -c32 -t8 -m1 --h1 --header=connection:keep-alive --header=cookie:cid=11  https://localhost:8080
  30. -t: warning: the number of threads is greater than hardware cores.
  31. starting benchmark...
  32. spawning thread #0: 4 total client(s). 4000 total requests
  33. spawning thread #1: 4 total client(s). 4000 total requests
  34. spawning thread #2: 4 total client(s). 4000 total requests
  35. spawning thread #3: 4 total client(s). 4000 total requests
  36. spawning thread #4: 4 total client(s). 4000 total requests
  37. spawning thread #5: 4 total client(s). 4000 total requests
  38. spawning thread #6: 4 total client(s). 4000 total requests
  39. spawning thread #7: 4 total client(s). 4000 total requests
  40. TLS Protocol: TLSv1.2
  41. Cipher: ECDHE-RSA-AES256-GCM-SHA384
  42. Server Temp Key: X25519 253 bits
  43. Application protocol: http/1.1
  44. progress: 10% done
  45. progress: 20% done
  46. progress: 30% done
  47. progress: 40% done
  48. progress: 50% done
  49. progress: 60% done
  50. progress: 70% done
  51. progress: 80% done
  52. progress: 90% done
  53. progress: 100% done
  54.  
  55. finished in 29.06s, 1101.26 req/s, 1.01MB/s
  56. requests: 32000 total, 32000 started, 32000 done, 32000 succeeded, 0 failed, 0 errored, 0 timeout
  57. status codes: 32000 2xx, 0 3xx, 0 4xx, 0 5xx
  58. traffic: 29.39MB (30816000) total, 2.53MB (2656000) headers (space savings 0.00%), 25.79MB (27040000) data
  59.                      min         max         mean         sd        +/- sd
  60. time for request:     7.99ms    208.16ms     26.31ms      5.94ms    93.71%
  61. time for connect:     8.22ms       3.08s       1.25s    943.18ms    62.50%
  62. time to 1st byte:    99.48ms       3.12s       1.31s    913.25ms    62.50%
  63. req/s           :      34.42       38.74       36.31        1.25    62.50%
« Last Edit: March 08, 2021, 02:49:40 pm by iLya2IK »

 

TinyPortal © 2005-2018