iodine 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of iodine might be problematic. Click here for more details.

Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +11 -0
  3. data/README.md +4 -4
  4. data/SPEC-Websocket-Draft.md +3 -6
  5. data/bin/mustache.rb +128 -0
  6. data/examples/test_template.mustache +16 -0
  7. data/ext/iodine/fio.c +9397 -0
  8. data/ext/iodine/fio.h +4723 -0
  9. data/ext/iodine/fio_ary.h +353 -54
  10. data/ext/iodine/fio_cli.c +351 -361
  11. data/ext/iodine/fio_cli.h +84 -105
  12. data/ext/iodine/fio_hashmap.h +70 -16
  13. data/ext/iodine/fio_json_parser.h +35 -24
  14. data/ext/iodine/fio_siphash.c +104 -4
  15. data/ext/iodine/fio_siphash.h +18 -2
  16. data/ext/iodine/fio_str.h +1218 -0
  17. data/ext/iodine/fio_tmpfile.h +1 -1
  18. data/ext/iodine/fiobj.h +13 -8
  19. data/ext/iodine/fiobj4sock.h +6 -8
  20. data/ext/iodine/fiobj_ary.c +107 -17
  21. data/ext/iodine/fiobj_ary.h +36 -4
  22. data/ext/iodine/fiobj_data.c +146 -127
  23. data/ext/iodine/fiobj_data.h +25 -23
  24. data/ext/iodine/fiobj_hash.c +7 -7
  25. data/ext/iodine/fiobj_hash.h +6 -5
  26. data/ext/iodine/fiobj_json.c +20 -17
  27. data/ext/iodine/fiobj_json.h +5 -5
  28. data/ext/iodine/fiobj_mem.h +71 -0
  29. data/ext/iodine/fiobj_mustache.c +310 -0
  30. data/ext/iodine/fiobj_mustache.h +40 -0
  31. data/ext/iodine/fiobj_numbers.c +199 -94
  32. data/ext/iodine/fiobj_numbers.h +7 -7
  33. data/ext/iodine/fiobj_str.c +142 -333
  34. data/ext/iodine/fiobj_str.h +65 -55
  35. data/ext/iodine/fiobject.c +49 -11
  36. data/ext/iodine/fiobject.h +40 -39
  37. data/ext/iodine/http.c +382 -190
  38. data/ext/iodine/http.h +124 -80
  39. data/ext/iodine/http1.c +99 -127
  40. data/ext/iodine/http1.h +5 -5
  41. data/ext/iodine/http1_parser.c +3 -2
  42. data/ext/iodine/http1_parser.h +2 -2
  43. data/ext/iodine/http_internal.c +14 -12
  44. data/ext/iodine/http_internal.h +25 -19
  45. data/ext/iodine/iodine.c +37 -18
  46. data/ext/iodine/iodine.h +4 -0
  47. data/ext/iodine/iodine_caller.c +9 -2
  48. data/ext/iodine/iodine_caller.h +2 -0
  49. data/ext/iodine/iodine_connection.c +82 -117
  50. data/ext/iodine/iodine_defer.c +57 -50
  51. data/ext/iodine/iodine_defer.h +0 -1
  52. data/ext/iodine/iodine_fiobj2rb.h +4 -2
  53. data/ext/iodine/iodine_helpers.c +4 -4
  54. data/ext/iodine/iodine_http.c +25 -32
  55. data/ext/iodine/iodine_json.c +2 -1
  56. data/ext/iodine/iodine_mustache.c +423 -0
  57. data/ext/iodine/iodine_mustache.h +6 -0
  58. data/ext/iodine/iodine_pubsub.c +48 -153
  59. data/ext/iodine/iodine_pubsub.h +5 -4
  60. data/ext/iodine/iodine_rack_io.c +7 -5
  61. data/ext/iodine/iodine_store.c +16 -13
  62. data/ext/iodine/iodine_tcp.c +26 -34
  63. data/ext/iodine/mustache_parser.h +1085 -0
  64. data/ext/iodine/redis_engine.c +740 -646
  65. data/ext/iodine/redis_engine.h +13 -15
  66. data/ext/iodine/resp_parser.h +11 -5
  67. data/ext/iodine/websocket_parser.h +13 -13
  68. data/ext/iodine/websockets.c +240 -393
  69. data/ext/iodine/websockets.h +52 -113
  70. data/lib/iodine.rb +1 -1
  71. data/lib/iodine/mustache.rb +140 -0
  72. data/lib/iodine/version.rb +1 -1
  73. metadata +15 -28
  74. data/ext/iodine/defer.c +0 -566
  75. data/ext/iodine/defer.h +0 -148
  76. data/ext/iodine/evio.c +0 -26
  77. data/ext/iodine/evio.h +0 -161
  78. data/ext/iodine/evio_callbacks.c +0 -26
  79. data/ext/iodine/evio_epoll.c +0 -251
  80. data/ext/iodine/evio_kqueue.c +0 -194
  81. data/ext/iodine/facil.c +0 -2325
  82. data/ext/iodine/facil.h +0 -616
  83. data/ext/iodine/fio_base64.c +0 -277
  84. data/ext/iodine/fio_base64.h +0 -71
  85. data/ext/iodine/fio_llist.h +0 -257
  86. data/ext/iodine/fio_mem.c +0 -675
  87. data/ext/iodine/fio_mem.h +0 -143
  88. data/ext/iodine/fio_random.c +0 -248
  89. data/ext/iodine/fio_random.h +0 -45
  90. data/ext/iodine/fio_sha1.c +0 -362
  91. data/ext/iodine/fio_sha1.h +0 -107
  92. data/ext/iodine/fio_sha2.c +0 -842
  93. data/ext/iodine/fio_sha2.h +0 -169
  94. data/ext/iodine/pubsub.c +0 -867
  95. data/ext/iodine/pubsub.h +0 -221
  96. data/ext/iodine/sock.c +0 -1366
  97. data/ext/iodine/sock.h +0 -566
  98. data/ext/iodine/spnlock.inc +0 -111
@@ -7,7 +7,9 @@ Feel free to copy, use and enjoy according to the license provided.
7
7
  */
8
8
  #define H_HTTP_H
9
9
 
10
- #include "facil.h"
10
+ #include <fio.h>
11
+
12
+ #include <fiobj.h>
11
13
 
12
14
  #include <time.h>
13
15
 
@@ -40,7 +42,7 @@ Compile Time Settings
40
42
  #define HTTP_MAX_HEADER_LENGTH 8192
41
43
  #endif
42
44
 
43
- /** the `http_listen settings, see detils in the struct definition. */
45
+ /** the `http_listen settings, see details in the struct definition. */
44
46
  typedef struct http_settings_s http_settings_s;
45
47
 
46
48
  /* *****************************************************************************
@@ -114,18 +116,18 @@ This struct is used together with the `http_response_set_cookie`. i.e.:
114
116
  */
115
117
  typedef struct {
116
118
  /** The cookie's name (Symbol). */
117
- char *name;
119
+ const char *name;
118
120
  /** The cookie's value (leave blank to delete cookie). */
119
- char *value;
121
+ const char *value;
120
122
  /** The cookie's domain (optional). */
121
- char *domain;
123
+ const char *domain;
122
124
  /** The cookie's path (optional). */
123
- char *path;
124
- /** The cookie name's size in bytes or a terminating NULL will be assumed.*/
125
+ const char *path;
126
+ /** The cookie name's size in bytes or a terminating NUL will be assumed.*/
125
127
  size_t name_len;
126
- /** The cookie value's size in bytes or a terminating NULL will be assumed.*/
128
+ /** The cookie value's size in bytes or a terminating NUL will be assumed.*/
127
129
  size_t value_len;
128
- /** The cookie domain's size in bytes or a terminating NULL will be assumed.*/
130
+ /** The cookie domain's size in bytes or a terminating NUL will be assumed.*/
129
131
  size_t domain_len;
130
132
  /** The cookie path's size in bytes or a terminating NULL will be assumed.*/
131
133
  size_t path_len;
@@ -151,16 +153,15 @@ int http_set_header(http_s *h, FIOBJ name, FIOBJ value);
151
153
  *
152
154
  * Returns -1 on error and 0 on success.
153
155
  */
154
- int http_set_header2(http_s *h, fio_cstr_s name, fio_cstr_s value);
156
+ int http_set_header2(http_s *h, fio_str_info_s name, fio_str_info_s value);
155
157
 
156
158
  /**
157
- * Sets a response cookie, taking ownership of the value object, but NOT the
158
- * name object (so name objects could be reused in future responses).
159
+ * Sets a response cookie.
159
160
  *
160
161
  * Returns -1 on error and 0 on success.
161
162
  *
162
163
  * Note: Long cookie names and long cookie values will be considered a security
163
- * vaiolation and an error will be returned. It should be noted that most
164
+ * violation and an error will be returned. It should be noted that most
164
165
  * proxies and servers will refuse long cookie names or values and many impose
165
166
  * total header lengths (including cookies) of ~8Kib.
166
167
  */
@@ -248,6 +249,7 @@ int http_push_file(http_s *h, FIOBJ filename, FIOBJ mime_type);
248
249
  HTTP evented API (pause / resume HTTp handling)
249
250
  ***************************************************************************** */
250
251
 
252
+ typedef struct http_pause_handle_s http_pause_handle_s;
251
253
  /**
252
254
  * Pauses the request / response handling and INVALIDATES the current `http_s`
253
255
  * handle (no `http` functions can be called).
@@ -258,11 +260,11 @@ HTTP evented API (pause / resume HTTp handling)
258
260
  * The opaque `http` pointer is only valid for a single call to `http_resume`
259
261
  * and can't be used by any other `http` function (it's a different data type).
260
262
  *
261
- * Note: the currecnt `http_s` handle will become invalid once this function is
263
+ * Note: the current `http_s` handle will become invalid once this function is
262
264
  * called and it's data might be deallocated, invalid or used by a different
263
265
  * thread.
264
266
  */
265
- void http_pause(http_s *h, void (*task)(void *http));
267
+ void http_pause(http_s *h, void (*task)(http_pause_handle_s *http));
266
268
 
267
269
  /**
268
270
  * Resumes a request / response handling within a task and INVALIDATES the
@@ -281,24 +283,24 @@ void http_pause(http_s *h, void (*task)(void *http));
281
283
  * called and it's data might be deallocated, invalidated or used by a
282
284
  * different thread.
283
285
  */
284
- void http_resume(void *http, void (*task)(http_s *h),
286
+ void http_resume(http_pause_handle_s *http, void (*task)(http_s *h),
285
287
  void (*fallback)(void *udata));
286
288
 
287
289
  /** Returns the `udata` associated with the paused opaque handle */
288
- void *http_paused_udata_get(void *http);
290
+ void *http_paused_udata_get(http_pause_handle_s *http);
289
291
 
290
292
  /**
291
293
  * Sets the `udata` associated with the paused opaque handle, returning the
292
294
  * old value.
293
295
  */
294
- void *http_paused_udata_set(void *http, void *udata);
296
+ void *http_paused_udata_set(http_pause_handle_s *http, void *udata);
295
297
 
296
298
  /* *****************************************************************************
297
299
  HTTP Connections - Listening / Connecting / Hijacking
298
300
  ***************************************************************************** */
299
301
 
300
302
  /** The HTTP settings. */
301
- typedef struct http_settings_s {
303
+ struct http_settings_s {
302
304
  /** Callback for normal HTTP requests. */
303
305
  void (*on_request)(http_s *request);
304
306
  /**
@@ -386,17 +388,19 @@ typedef struct http_settings_s {
386
388
  uint8_t log;
387
389
  /** a read only flag set automatically to indicate the protocol's mode. */
388
390
  uint8_t is_client;
389
- } http_settings_s;
391
+ };
390
392
 
391
393
  /**
392
394
  * Listens to HTTP connections at the specified `port`.
393
395
  *
394
396
  * Leave as NULL to ignore IP binding.
395
397
  *
396
- * Returns -1 on error and 0 on success. the `on_finish` callback is always
397
- * called.
398
+ * Returns -1 on error and the socket's uuid on success.
399
+ *
400
+ * the `on_finish` callback is always called.
398
401
  */
399
- int http_listen(const char *port, const char *binding, struct http_settings_s);
402
+ intptr_t http_listen(const char *port, const char *binding,
403
+ struct http_settings_s);
400
404
  /** Listens to HTTP connections at the specified `port` and `binding`. */
401
405
  #define http_listen(port, binding, ...) \
402
406
  http_listen((port), (binding), (struct http_settings_s){__VA_ARGS__})
@@ -424,24 +428,23 @@ int http_listen(const char *port, const char *binding, struct http_settings_s);
424
428
  * signature. However, it would be better to use the `websocket_connect`
425
429
  * function instead.
426
430
  *
427
- * Returns -1 on error and 0 on success. the `on_finish` callback is always
428
- * called.
431
+ * Returns -1 on error and the socket's uuid on success.
432
+ *
433
+ * The `on_finish` callback is always called.
429
434
  */
430
- int http_connect(const char *address, struct http_settings_s);
435
+ intptr_t http_connect(const char *address, struct http_settings_s);
431
436
  #define http_connect(address, ...) \
432
437
  http_connect((address), (struct http_settings_s){__VA_ARGS__})
433
438
 
434
439
  /**
435
- * Returns the settings used to setup the connection.
436
- *
437
- * Returns -1 on error and 0 on success.
440
+ * Returns the settings used to setup the connection or NULL on error.
438
441
  */
439
442
  struct http_settings_s *http_settings(http_s *h);
440
443
 
441
444
  /**
442
445
  * Returns the direct address of the connected peer (likely an intermediary).
443
446
  */
444
- sock_peer_addr_s http_peer_addr(http_s *h);
447
+ fio_str_info_s http_peer_addr(http_s *h);
445
448
 
446
449
  /**
447
450
  * Hijacks the socket away from the HTTP protocol and away from facil.io.
@@ -452,7 +455,7 @@ sock_peer_addr_s http_peer_addr(http_s *h);
452
455
  * It's possible to call `http_finish` immediately after calling `http_hijack`
453
456
  * in order to send the outgoing headers.
454
457
  *
455
- * If any aditional HTTP functions are called after the hijacking, the protocol
458
+ * If any additional HTTP functions are called after the hijacking, the protocol
456
459
  * object might attempt to continue reading data from the buffer.
457
460
  *
458
461
  * Returns the underlining socket connection's uuid. If `leftover` isn't NULL,
@@ -462,7 +465,7 @@ sock_peer_addr_s http_peer_addr(http_s *h);
462
465
  * WARNING: this isn't a good way to handle HTTP connections, especially as
463
466
  * HTTP/2 enters the picture.
464
467
  */
465
- intptr_t http_hijack(http_s *h, fio_cstr_s *leftover);
468
+ intptr_t http_hijack(http_s *h, fio_str_info_s *leftover);
466
469
 
467
470
  /* *****************************************************************************
468
471
  Websocket Upgrade (Server and Client connection establishment)
@@ -478,12 +481,10 @@ Websocket Upgrade (Server and Client connection establishment)
478
481
  typedef struct ws_s ws_s;
479
482
 
480
483
  /**
481
- * This struct is used for the named agruments in the `http_upgrade2ws`
484
+ * This struct is used for the named arguments in the `http_upgrade2ws`
482
485
  * function and macro.
483
486
  */
484
487
  typedef struct {
485
- /** REQUIRED: The `http_s` to be initiating the websocket connection.*/
486
- http_s *http;
487
488
  /**
488
489
  * The (optional) on_message callback will be called whenever a websocket
489
490
  * message is received for this connection.
@@ -492,7 +493,7 @@ typedef struct {
492
493
  * overwritten once the function exits (it cannot be saved for later, but it
493
494
  * can be copied).
494
495
  */
495
- void (*on_message)(ws_s *ws, char *data, size_t size, uint8_t is_text);
496
+ void (*on_message)(ws_s *ws, fio_str_info_s msg, uint8_t is_text);
496
497
  /**
497
498
  * The (optional) on_open callback will be called once the websocket
498
499
  * connection is established and before is is registered with `facil`, so no
@@ -518,7 +519,7 @@ typedef struct {
518
519
  *
519
520
  * The `uuid` is the connection's unique ID that can identify the Websocket. A
520
521
  * value of `uuid == 0` indicates the Websocket connection wasn't established
521
- * (an error occured).
522
+ * (an error occurred).
522
523
  *
523
524
  * The `udata` is the user data as set during the upgrade or using the
524
525
  * `websocket_udata_set` function.
@@ -540,7 +541,7 @@ typedef struct {
540
541
  * A client connection's `on_finish` callback will be called (since the HTTP
541
542
  * stage has finished).
542
543
  */
543
- int http_upgrade2ws(websocket_settings_s);
544
+ int http_upgrade2ws(http_s *http, websocket_settings_s);
544
545
 
545
546
  /** This macro allows easy access to the `http_upgrade2ws` function. The macro
546
547
  * allows the use of named arguments, using the `websocket_settings_s` struct
@@ -555,8 +556,8 @@ int http_upgrade2ws(websocket_settings_s);
555
556
  * http_upgrade2ws( .http = h, .on_message = on_message);
556
557
  * }
557
558
  */
558
- #define http_upgrade2ws(...) \
559
- http_upgrade2ws((websocket_settings_s){__VA_ARGS__})
559
+ #define http_upgrade2ws(http, ...) \
560
+ http_upgrade2ws((http), (websocket_settings_s){__VA_ARGS__})
560
561
 
561
562
  /**
562
563
  * Connects to a Websocket service according to the provided address.
@@ -574,7 +575,7 @@ int websocket_connect(const char *address, websocket_settings_s settings);
574
575
  #define websocket_connect(address, ...) \
575
576
  websocket_connect((address), (websocket_settings_s){__VA_ARGS__})
576
577
 
577
- #include "websockets.h"
578
+ #include <websockets.h>
578
579
 
579
580
  /* *****************************************************************************
580
581
  EventSource Support (SSE)
@@ -587,7 +588,7 @@ EventSource Support (SSE)
587
588
  typedef struct http_sse_s http_sse_s;
588
589
 
589
590
  /**
590
- * This struct is used for the named agruments in the `http_upgrade2sse`
591
+ * This struct is used for the named arguments in the `http_upgrade2sse`
591
592
  * function and macro.
592
593
  */
593
594
  struct http_sse_s {
@@ -612,12 +613,8 @@ struct http_sse_s {
612
613
  * The (optional) on_close callback will be called once a connection is
613
614
  * terminated or failed to be established.
614
615
  *
615
- * The `uuid` is the connection's unique ID that can identify the Websocket. A
616
- * value of `uuid == 0` indicates the Websocket connection wasn't established
617
- * (an error occured).
618
- *
619
- * The `udata` is the user data as set during the upgrade or using the
620
- * `websocket_udata_set` function.
616
+ * The `udata` passed to the `http_upgrade2sse` function is available
617
+ * through the `http_sse_s` pointer (`sse->udata`).
621
618
  */
622
619
  void (*on_close)(http_sse_s *sse);
623
620
  /** Opaque user data. */
@@ -627,7 +624,7 @@ struct http_sse_s {
627
624
  /**
628
625
  * Upgrades an HTTP connection to an EventSource (SSE) connection.
629
626
  *
630
- * Thie `http_s` handle will be invalid after this call.
627
+ * The `http_s` handle will be invalid after this call.
631
628
  *
632
629
  * On HTTP/1.1 connections, this will preclude future requests using the same
633
630
  * connection.
@@ -639,9 +636,7 @@ int http_upgrade2sse(http_s *h, http_sse_s);
639
636
  * members. i.e.:
640
637
  *
641
638
  * on_open_sse(sse_s * sse) {
642
- * ; // ... this is the websocket on_message callback
643
- * FIOBJ ch = (FIOBJ)sse->udata;
644
- * http_sse_subscribe(ch, NULL, NULL); // a simple echo example
639
+ * http_sse_subscribe(sse, .channel = CHANNEL_NAME);
645
640
  * }
646
641
  *
647
642
  * on_upgrade(http_s* h) {
@@ -657,30 +652,29 @@ int http_upgrade2sse(http_s *h, http_sse_s);
657
652
  void http_sse_set_timout(http_sse_s *sse, uint8_t timeout);
658
653
 
659
654
  struct http_sse_subscribe_args {
660
- /** The channel namr used for the subscription. */
661
- FIOBJ channel;
655
+ /** The channel name used for the subscription. */
656
+ fio_str_info_s channel;
662
657
  /** The optional on message callback. If missing, Data is directly writen. */
663
- void (*on_message)(http_sse_s *sse, FIOBJ channel, FIOBJ msg, void *udata);
658
+ void (*on_message)(http_sse_s *sse, fio_str_info_s channel,
659
+ fio_str_info_s msg, void *udata);
664
660
  /** An optional callback for when a subscription is fully canceled. */
665
661
  void (*on_unsubscribe)(void *udata);
666
662
  /** Opaque user */
667
663
  void *udata;
668
- /** Use pattern matching for channel subscription. */
669
- unsigned use_pattern : 1;
664
+ /** A callback for pattern matching. */
665
+ fio_match_fn match;
670
666
  };
671
667
 
672
668
  /**
673
- * Subscribes to a channel. See {struct http_sse_subscribe_args} for possible
674
- * arguments.
669
+ * Subscribes to a channel for direct message deliverance. See {struct
670
+ * http_sse_subscribe_args} for possible arguments.
675
671
  *
676
672
  * Returns a subscription ID on success and 0 on failure.
677
673
  *
678
- * All subscriptions are automatically revoked once the connection is closed.
674
+ * To unsubscripbe from the channel, use `http_sse_unsubscribe` (NOT
675
+ * `fio_unsubscribe`).
679
676
  *
680
- * If the connections subscribes to the same channel more than once, messages
681
- * will be merged. However, another subscription ID will be assigned, and two
682
- * calls to {http_sse_unsubscribe} will be required in order to unregister from
683
- * the channel.
677
+ * All subscriptions are automatically cleared once the connection is closed.
684
678
  */
685
679
  uintptr_t http_sse_subscribe(http_sse_s *sse,
686
680
  struct http_sse_subscribe_args args);
@@ -703,10 +697,10 @@ void http_sse_unsubscribe(http_sse_s *sse, uintptr_t subscription);
703
697
  * https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
704
698
  */
705
699
  struct http_sse_write_args {
706
- fio_cstr_s id; /* (optionl) sets the `id` event property. */
707
- fio_cstr_s event; /* (optionl) sets the `event` event property. */
708
- fio_cstr_s data; /* (optionl) sets the `data` event property. */
709
- intptr_t retry; /* (optionl) sets the `retry` event property. */
700
+ fio_str_info_s id; /* (optional) sets the `id` event property. */
701
+ fio_str_info_s event; /* (optional) sets the `event` event property. */
702
+ fio_str_info_s data; /* (optional) sets the `data` event property. */
703
+ intptr_t retry; /* (optional) sets the `retry` event property. */
710
704
  };
711
705
 
712
706
  /**
@@ -719,7 +713,7 @@ int http_sse_write(http_sse_s *sse, struct http_sse_write_args);
719
713
  http_sse_write((sse), (struct http_sse_write_args){__VA_ARGS__})
720
714
 
721
715
  /**
722
- * Get the connection's UUID (for facil_defer and similar use cases).
716
+ * Get the connection's UUID (for `fio_defer_io_task`, pub/sub, etc').
723
717
  */
724
718
  intptr_t http_sse2uuid(http_sse_s *sse);
725
719
 
@@ -787,10 +781,10 @@ void http_parse_cookies(http_s *h, uint8_t is_url_encoded);
787
781
  * * "name[][key]" references a nested Hash within an array. Hash keys will be
788
782
  * unique (repeating a key advances the hash).
789
783
  * * These rules can be nested (i.e. "name[][key1][][key2]...")
790
- * * "name[][]" is an error (there's no way for the parser to analyse
791
- * dimentions)
784
+ * * "name[][]" is an error (there's no way for the parser to analyze
785
+ * dimensions)
792
786
  *
793
- * Note: names can't begine with "[" or end with "]" as these are reserved
787
+ * Note: names can't begin with "[" or end with "]" as these are reserved
794
788
  * characters.
795
789
  */
796
790
  int http_add2hash(FIOBJ dest, char *name, size_t name_len, char *value,
@@ -805,12 +799,12 @@ int http_add2hash(FIOBJ dest, char *name, size_t name_len, char *value,
805
799
  * * "name[]" references a nested Array (nested in the Hash).
806
800
  * * "name[key]" references a nested Hash.
807
801
  * * "name[][key]" references a nested Hash within an array. Hash keys will be
808
- * unique (repeating a key advances the hash).
802
+ * unique (repeating a key advances the array).
809
803
  * * These rules can be nested (i.e. "name[][key1][][key2]...")
810
- * * "name[][]" is an error (there's no way for the parser to analyse
811
- * dimentions)
804
+ * * "name[][]" is an error (there's no way for the parser to analyze
805
+ * dimensions)
812
806
  *
813
- * Note: names can't begine with "[" or end with "]" as these are reserved
807
+ * Note: names can't begin with "[" or end with "]" as these are reserved
814
808
  * characters.
815
809
  */
816
810
  int http_add2hash2(FIOBJ dest, char *name, size_t name_len, FIOBJ value,
@@ -821,7 +815,7 @@ HTTP Status Strings and Mime-Type helpers
821
815
  ***************************************************************************** */
822
816
 
823
817
  /** Returns a human readable string related to the HTTP status number. */
824
- fio_cstr_s http_status2str(uintptr_t status);
818
+ fio_str_info_s http_status2str(uintptr_t status);
825
819
 
826
820
  /** Registers a Mime-Type to be associated with the file extension. */
827
821
  void http_mimetype_register(char *file_ext, size_t file_ext_len,
@@ -843,7 +837,7 @@ FIOBJ http_mimetype_find(char *file_ext, size_t file_ext_len);
843
837
  */
844
838
  FIOBJ http_mimetype_find2(FIOBJ url);
845
839
 
846
- /** Clears the Mime-Type registry (it will be emoty afterthis call). */
840
+ /** Clears the Mime-Type registry (it will be empty after this call). */
847
841
  void http_mimetype_clear(void);
848
842
 
849
843
  /* *****************************************************************************
@@ -912,7 +906,7 @@ size_t http_date2rfc2822(char *target, struct tm *tmbuf);
912
906
  /**
913
907
  * Prints Unix time to a HTTP time formatted string.
914
908
  *
915
- * This variation implements chached results for faster processeing, at the
909
+ * This variation implements cached results for faster processing, at the
916
910
  * price of a less accurate string.
917
911
  */
918
912
  size_t http_time2str(char *target, const time_t t);
@@ -930,10 +924,60 @@ ssize_t http_decode_url(char *dest, const char *url_data, size_t length);
930
924
  /** Decodes the "path" part of a request, no buffer overflow protection. */
931
925
  ssize_t http_decode_path_unsafe(char *dest, const char *url_data);
932
926
 
933
- /** Decodes the "path" part of an HTTP request, no buffer overflow protection.
927
+ /**
928
+ * Decodes the "path" part of an HTTP request, no buffer overflow protection.
934
929
  */
935
930
  ssize_t http_decode_path(char *dest, const char *url_data, size_t length);
936
931
 
932
+ /* *****************************************************************************
933
+ HTTP URL parsing
934
+ ***************************************************************************** */
935
+
936
+ /** the result returned by `http_url_parse` */
937
+ typedef struct {
938
+ fio_str_info_s scheme;
939
+ fio_str_info_s user;
940
+ fio_str_info_s password;
941
+ fio_str_info_s host;
942
+ fio_str_info_s port;
943
+ fio_str_info_s path;
944
+ fio_str_info_s query;
945
+ fio_str_info_s target;
946
+ } http_url_s;
947
+
948
+ /**
949
+ * Parses the URI returning it's components and their lengths (no decoding
950
+ * performed, doesn't accept decoded URIs).
951
+ *
952
+ * The returned string are NOT NUL terminated, they are merely locations within
953
+ * the original string.
954
+ *
955
+ * This function expects any of the following formats:
956
+ *
957
+ * * `/complete_path?query#target`
958
+ *
959
+ * i.e.: /index.html?page=1#list
960
+ *
961
+ * * `host:port/complete_path?query#target`
962
+ *
963
+ * i.e.:
964
+ * example.com
965
+ * example.com/index.html
966
+ * user:1234@example.com:8080
967
+ * example.com:8080/index.html
968
+ *
969
+ * * `schema://user:password@host:port/path?query#target`
970
+ *
971
+ * i.e.: http://example.com/index.html?page=1#list
972
+ *
973
+ * Invalid formats might produce unexpected results. No error testing performed.
974
+ */
975
+ http_url_s http_url_parse(const char *url, size_t length);
976
+
977
+ #if DEBUG
978
+ void http_tests(void);
979
+ #endif
980
+
937
981
  /* support C++ */
938
982
  #ifdef __cplusplus
939
983
  }