iodine 0.7.58 → 0.7.59

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 322c256e46337fbbb04715a5076984dda9e00ffa35e75bac7882fb8e95b17dea
4
- data.tar.gz: 91390ce111e21fbf39f40e010bc059acab48d13a92b90f04d0a1a4b5738b87f8
3
+ metadata.gz: b701f0b79a433993d53684b5ce564356f1317e0a23060a0a9c7f729d8857d3bb
4
+ data.tar.gz: 1abd95637405ccc2990d00d771e61c25cc075e8d819da47205879e151099d546
5
5
  SHA512:
6
- metadata.gz: 78c783b0457ff798146af5c3040ccf86e3449dc33c53677986d58b7cd585745288bffcbf19f2427b8353c51507140b307209f33df2b4598d21d875c5203ab3a5
7
- data.tar.gz: 257bbacb1c902bfa2202cd649b0d842f366963a528a00e115bc923a381d47bbe93e7c38c42cc21976f839d7a042873b107dc2fa8dd7ecc3703a61cecbe65e301
6
+ metadata.gz: 4d35fb80524542d8dbaf5a9d0b8c36fbe2b8a82801d3957559573d6141bd109537ea64f4d1bee905b16b37b6b80bc998403e5da8476aaeee2c19cb009f23b9cd
7
+ data.tar.gz: d7ddbe875e12102ab71557391c8be4eedd9d0735d9734bfddfcbf600af0a3867ab1f0ea159f1a2ad61f823772d300732a0907e20cc1f30941e5ec211d3268068
data/README.md CHANGED
@@ -33,7 +33,7 @@ Iodine includes native support for:
33
33
 
34
34
  Since iodine wraps much of the [C facil.io framework](https://github.com/boazsegev/facil.io) for Ruby:
35
35
 
36
- * Iodine can handle **thousands of concurrent connections** (tested with more then 20K connections on Linux)!
36
+ * Iodine can handle **thousands of concurrent connections** (tested with more than 20K connections on Linux)!
37
37
 
38
38
  * Iodine is ideal for **Linux/Unix** based systems (i.e. macOS, Ubuntu, FreeBSD etc'), which are ideal for evented IO (while Windows and Solaris are better at IO *completion* events, which are very different).
39
39
 
@@ -45,7 +45,7 @@ Iodine is a C extension for Ruby, developed and optimized for Ruby MRI 2.3 and u
45
45
 
46
46
  Iodine includes a light and fast HTTP and Websocket server written in C that was written according to the [Rack interface specifications](http://www.rubydoc.info/github/rack/rack/master/file/SPEC) and the [Websocket draft extension](./SPEC-Websocket-Draft.md).
47
47
 
48
- With `Iodine.listen service: :http` it's possible to run multiple HTTP applications (but please remember not to set more than a single application on a single TCP/IP port).
48
+ With `Iodine.listen service: :http` it's possible to run multiple HTTP applications (but please remember not to set more than a single application on a single TCP/IP port).
49
49
 
50
50
  Iodine also supports native process cluster Pub/Sub and a native RedisEngine to easily scale iodine's Pub/Sub horizontally.
51
51
 
@@ -278,11 +278,11 @@ module WebsocketChat
278
278
  extend self
279
279
  end
280
280
  APP = Proc.new do |env|
281
- if env['rack.upgrade?'.freeze] == :websocket
282
- env['rack.upgrade'.freeze] = WebsocketChat
281
+ if env['rack.upgrade?'.freeze] == :websocket
282
+ env['rack.upgrade'.freeze] = WebsocketChat
283
283
  [0,{}, []] # It's possible to set cookies for the response.
284
284
  elsif env['rack.upgrade?'.freeze] == :sse
285
- puts "SSE connections can only receive data from the server, the can't write."
285
+ puts "SSE connections can only receive data from the server, the can't write."
286
286
  env['rack.upgrade'.freeze] = WebsocketChat
287
287
  [0,{}, []] # It's possible to set cookies for the response.
288
288
  else
@@ -556,7 +556,7 @@ Iodine is written in C and allows some compile-time customizations, such as:
556
556
  * `FIO_MAX_SOCK_CAPACITY` - limits iodine's maximum client capacity. Defaults to 131,072 clients.
557
557
 
558
558
  * `FIO_USE_RISKY_HASH` - replaces SipHash with RiskyHash for iodine's internal hash maps.
559
-
559
+
560
560
  Since iodine hash maps have internal protection against collisions and hash flooding attacks, it's possible for iodine to leverage RiskyHash, which is faster than SipHash.
561
561
 
562
562
  By default, SipHash will be used. This is a community related choice, since the community seems to believe a hash function should protect the hash map rather than it being enough for a hash map implementation to be attack resistance.
@@ -611,7 +611,7 @@ end
611
611
 
612
612
  In pure Ruby (without using C extensions or Java), it's possible to do the same by using `select`... and although `select` has some issues, it could work well for lighter loads.
613
613
 
614
- The server events are fairly fast and fragmented (longer code is fragmented across multiple events), so one thread is enough to run the server including it's static file service and everything...
614
+ The server events are fairly fast and fragmented (longer code is fragmented across multiple events), so one thread is enough to run the server including it's static file service and everything...
615
615
 
616
616
  ...but single threaded mode should probably be avoided.
617
617
 
@@ -642,7 +642,7 @@ If you have the development headers but still can't compile the iodine extension
642
642
 
643
643
  ## Mr. Sandman, write me a server
644
644
 
645
- Iodine allows custom TCP/IP server authoring, for those cases where we need raw TCP/IP (UDP isn't supported just yet).
645
+ Iodine allows custom TCP/IP server authoring, for those cases where we need raw TCP/IP (UDP isn't supported just yet).
646
646
 
647
647
  Here's a short and sweet echo server - No HTTP, just use `telnet`:
648
648
 
data/SECURITY.md ADDED
@@ -0,0 +1,32 @@
1
+ # Security Policy
2
+
3
+ Please report any security issues you discover on GitHub using the [`Security and quality`](https://github.com/boazsegev/iodine/security) reporting form.
4
+
5
+ Please remember that this is an open source project that I work on in my free time. Take it as is, I don't promise anything.
6
+
7
+ ## Supported Versions
8
+
9
+ I support what I have time to support, with my main focus being:
10
+
11
+ | Version | Support |
12
+ | ------- | ------------------ |
13
+ | 0.8.x | :green_circle: |
14
+ | 0.7.x | :orange_circle: |
15
+ | < 0.7.0 | :red_circle: |
16
+
17
+
18
+
19
+ ### [facil.io](https://facil.io) Security Issues
20
+
21
+
22
+ | Version | facil.io link |
23
+ | ------- | ------------------ |
24
+ | 0.8.x | https://github.com/facil-io/cstl/security |
25
+ | 0.7.x | https://github.com/boazsegev/facil.io/security |
26
+ | < 0.7.0 | :red_circle: |
27
+
28
+ ## Reporting a Vulnerability
29
+
30
+ Please report any security issues you discover on GitHub using the [`Security and quality`](https://github.com/boazsegev/iodine/security) reporting form or privately using email.
31
+
32
+ Usually I implement a security patch for the version reported before porting to the current developer version. Please note that it's usually possible to port the patch manually if you don't want to upgrade an older version.
data/ext/iodine/fio.c CHANGED
@@ -3385,7 +3385,7 @@ read_error:
3385
3385
  static int fio_sock_sendfile_from_fd(int fd, fio_packet_s *packet) {
3386
3386
  ssize_t sent;
3387
3387
  sent =
3388
- sendfile64(fd, packet->data.fd, (off_t *)&packet->offset, packet->length);
3388
+ sendfile(fd, packet->data.fd, (off_t *)&packet->offset, packet->length);
3389
3389
  if (sent < 0)
3390
3390
  return -1;
3391
3391
  packet->length -= sent;
data/ext/iodine/fio.h CHANGED
@@ -109,7 +109,7 @@ Version and helper macros
109
109
 
110
110
  #define FIO_VERSION_MAJOR 0
111
111
  #define FIO_VERSION_MINOR 7
112
- #define FIO_VERSION_PATCH 4
112
+ #define FIO_VERSION_PATCH 7
113
113
  #define FIO_VERSION_BETA 0
114
114
 
115
115
  /* Automatically convert version data to a string constant - ignore these two */
@@ -221,6 +221,7 @@ Version and helper macros
221
221
  #include <unistd.h>
222
222
  #ifdef __MINGW32__
223
223
  #include <winsock2.h>
224
+
224
225
  #include <winsock.h>
225
226
  #include <ws2tcpip.h>
226
227
  #endif
@@ -251,10 +252,10 @@ Version and helper macros
251
252
  #endif
252
253
 
253
254
  #ifdef __MINGW32__
254
- #define __S_IFMT 0170000
255
- #define __S_IFLNK 0120000
256
- #define __S_ISTYPE(mode, mask) (((mode) & __S_IFMT) == (mask))
257
- #define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
255
+ #define __S_IFMT 0170000
256
+ #define __S_IFLNK 0120000
257
+ #define __S_ISTYPE(mode, mask) (((mode)&__S_IFMT) == (mask))
258
+ #define S_ISLNK(mode) __S_ISTYPE((mode), __S_IFLNK)
258
259
 
259
260
  #define SIGKILL 9
260
261
  #define SIGTERM 15
@@ -4743,14 +4744,11 @@ static FIO_ARY_TYPE const FIO_NAME(s___const_invalid_object);
4743
4744
  /* minimizes allocation "dead space" by alligning allocated length to 16bytes */
4744
4745
  #undef FIO_ARY_SIZE2WORDS
4745
4746
  #define FIO_ARY_SIZE2WORDS(size) \
4746
- ((sizeof(FIO_ARY_TYPE) & 1) \
4747
- ? (((size) & (~15)) + 16) \
4748
- : (sizeof(FIO_ARY_TYPE) & 2) \
4749
- ? (((size) & (~7)) + 8) \
4750
- : (sizeof(FIO_ARY_TYPE) & 4) \
4751
- ? (((size) & (~3)) + 4) \
4752
- : (sizeof(FIO_ARY_TYPE) & 8) ? (((size) & (~1)) + 2) \
4753
- : (size))
4747
+ ((sizeof(FIO_ARY_TYPE) & 1) ? (((size) & (~15)) + 16) \
4748
+ : (sizeof(FIO_ARY_TYPE) & 2) ? (((size) & (~7)) + 8) \
4749
+ : (sizeof(FIO_ARY_TYPE) & 4) ? (((size) & (~3)) + 4) \
4750
+ : (sizeof(FIO_ARY_TYPE) & 8) ? (((size) & (~1)) + 2) \
4751
+ : (size))
4754
4752
 
4755
4753
  /* *****************************************************************************
4756
4754
  Array API
@@ -6048,7 +6046,7 @@ FIO_NAME(_insert_or_overwrite_)(FIO_NAME(s) * set, FIO_SET_HASH_TYPE hash_value,
6048
6046
  pos->hash = hash_value;
6049
6047
  pos->pos->hash = hash_value;
6050
6048
  FIO_SET_COPY(pos->pos->obj, obj);
6051
-
6049
+
6052
6050
  return pos->pos->obj;
6053
6051
  }
6054
6052
 
@@ -393,7 +393,7 @@ fio_json_parse(json_parser_s *parser, const char *buffer, size_t length) {
393
393
  goto error;
394
394
  break;
395
395
  case ']':
396
- if ((parser->dict & 1))
396
+ if ((parser->dict & 1) || !parser->depth)
397
397
  goto error;
398
398
  --parser->depth;
399
399
  ++pos;
@@ -453,12 +453,12 @@ fio_json_parse(json_parser_s *parser, const char *buffer, size_t length) {
453
453
  long long i = fio_atol((char **)&tmp);
454
454
  if (tmp > limit)
455
455
  goto stop;
456
- if (!tmp || JSON_NUMERAL[*tmp]) {
456
+ if (!tmp || tmp == pos || JSON_NUMERAL[*tmp]) {
457
457
  tmp = pos;
458
458
  double f = fio_atof((char **)&tmp);
459
459
  if (tmp > limit)
460
460
  goto stop;
461
- if (!tmp || JSON_NUMERAL[*tmp])
461
+ if (!tmp || tmp == pos || JSON_NUMERAL[*tmp])
462
462
  goto error;
463
463
  fio_json_on_float(parser, f);
464
464
  pos = tmp;
@@ -481,8 +481,9 @@ fio_json_parse(json_parser_s *parser, const char *buffer, size_t length) {
481
481
  if (pos[1] == '*') {
482
482
  if (pos + 4 > limit)
483
483
  goto stop;
484
- uint8_t *tmp = pos + 3; /* avoid this: /*/
484
+ uint8_t *tmp = pos + 2; /* avoid this: /*/
485
485
  do {
486
+ ++tmp;
486
487
  tmp = memchr(tmp, '/', (uintptr_t)(limit - tmp));
487
488
  } while (tmp && tmp[-1] != '*');
488
489
  if (!tmp)
@@ -63,6 +63,17 @@ Object required VTable and functions
63
63
  } \
64
64
  } while (0)
65
65
 
66
+ static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
67
+ struct stat stat;
68
+ retry:
69
+ if (fstat(obj2io(o)->fd, &stat)) {
70
+ if (errno == EINTR)
71
+ goto retry;
72
+ return -1;
73
+ }
74
+ return stat.st_size;
75
+ }
76
+
66
77
  static void fiobj_data_copy_buffer(FIOBJ o) {
67
78
  obj2io(o)->capa = (((obj2io(o)->len) >> 12) + 1) << 12;
68
79
  void *tmp = fio_malloc(obj2io(o)->capa);
@@ -145,17 +156,6 @@ static inline void fiobj_data_pre_write(FIOBJ o, uintptr_t length) {
145
156
  REQUIRE_MEM(obj2io(o)->buffer);
146
157
  }
147
158
 
148
- static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
149
- struct stat stat;
150
- retry:
151
- if (fstat(obj2io(o)->fd, &stat)) {
152
- if (errno == EINTR)
153
- goto retry;
154
- return -1;
155
- }
156
- return stat.st_size;
157
- }
158
-
159
159
  static FIOBJ fiobj_data_alloc(void *buffer, int fd) {
160
160
  fiobj_data_s *io = fio_malloc(sizeof(*io));
161
161
  REQUIRE_MEM(io);
@@ -963,6 +963,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
963
963
  /* Unslice slices */
964
964
  if (obj2io(io)->fd == -2)
965
965
  fiobj_data_assert_dynamic(io);
966
+
966
967
  if (obj2io(io)->fd == -1) {
967
968
  /* String Code */
968
969
  fiobj_data_pre_write(io, length + 1);
@@ -971,6 +972,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
971
972
  obj2io(io)->buffer[obj2io(io)->len] = 0;
972
973
  return length;
973
974
  }
975
+
974
976
  /* File Code */
975
977
  return pwrite(obj2io(io)->fd, buffer, length, fiobj_data_get_fd_size(io));
976
978
  }
@@ -38,7 +38,7 @@ static inline __attribute__((unused)) FIOBJ fiobj_str_copy(FIOBJ src) {
38
38
  /**
39
39
  * Creates a String object. Remember to use `fiobj_free`.
40
40
  *
41
- * It's possible to wrap a previosly allocated memory block in a FIOBJ String
41
+ * It's possible to wrap a previously allocated memory block in a FIOBJ String
42
42
  * object, as long as it was allocated using `fio_malloc`.
43
43
  *
44
44
  * The ownership of the memory indicated by `str` will "move" to the object and
@@ -147,10 +147,10 @@ FIO_INLINE double fiobj_obj2float(const FIOBJ obj);
147
147
  /**
148
148
  * Returns a C String (NUL terminated) using the `fio_str_info_s` data type.
149
149
  *
150
- * The Sting in binary safe and might contain NUL bytes in the middle as well as
151
- * a terminating NUL.
150
+ * The String is binary safe and might contain NUL bytes in the middle as well
151
+ * as a terminating NUL.
152
152
  *
153
- * If a a Number or a Float are passed to the function, they
153
+ * If a Number or a Float are passed to the function, they
154
154
  * will be parsed as a *temporary*, thread-safe, String.
155
155
  *
156
156
  * Numbers will be represented in base 10 numerical data.
@@ -270,7 +270,8 @@ FIO_INLINE size_t fiobj_type_is(FIOBJ o, fiobj_type_enum type) {
270
270
  switch (type) {
271
271
  case FIOBJ_T_NUMBER:
272
272
  return (o & FIOBJECT_NUMBER_FLAG) ||
273
- ((fiobj_type_enum *)o)[0] == FIOBJ_T_NUMBER;
273
+ (o && !(o & FIOBJECT_PRIMITIVE_FLAG) &&
274
+ ((fiobj_type_enum *)o)[0] == FIOBJ_T_NUMBER);
274
275
  case FIOBJ_T_NULL:
275
276
  return !o || o == fiobj_null();
276
277
  case FIOBJ_T_TRUE:
data/ext/iodine/http1.c CHANGED
@@ -45,6 +45,8 @@ inline static void h1_reset(http1pr_s *p) { p->header_size = 0; }
45
45
  #define http1_pr2handle(pr) (((http1pr_s *)(pr))->request)
46
46
  #define handle2pr(h) ((http1pr_s *)h->private_data.flag)
47
47
 
48
+ static fio_str_info_s http1pr_status2str(uintptr_t status);
49
+
48
50
  /* cleanup an HTTP/1.1 handler object */
49
51
  static inline void http1_after_finish(http_s *h) {
50
52
  http1pr_s *p = handle2pr(h);
@@ -110,10 +112,8 @@ static FIOBJ headers2str(http_s *h, uintptr_t padding) {
110
112
  http1pr_s *p = handle2pr(h);
111
113
 
112
114
  if (p->is_client == 0) {
113
- fio_str_info_s t = http_status2str(h->status);
114
- fiobj_str_write(w.dest, "HTTP/1.1 ", 9);
115
+ fio_str_info_s t = http1pr_status2str(h->status);
115
116
  fiobj_str_write(w.dest, t.data, t.len);
116
- fiobj_str_write(w.dest, "\r\n", 2);
117
117
  FIOBJ tmp = fiobj_hash_get2(h->private_data.out_headers, connection_hash);
118
118
  if (tmp) {
119
119
  t = fiobj_obj2cstr(tmp);
@@ -787,8 +787,7 @@ fio_protocol_s *http1_new(uintptr_t uuid, http_settings_s *settings,
787
787
  if (unread_data && unread_length > HTTP_MAX_HEADER_LENGTH)
788
788
  return NULL;
789
789
  http1pr_s *p = fio_malloc(sizeof(*p) + HTTP_MAX_HEADER_LENGTH);
790
- // FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol %p(%d)=>%p", (void *)uuid,
791
- // (int)fio_uuid2fd(uuid), (void *)p);
790
+ // FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol at. %p", (void *)p);
792
791
  FIO_ASSERT_ALLOC(p);
793
792
  *p = (http1pr_s){
794
793
  .p.protocol =
@@ -819,7 +818,93 @@ void http1_destroy(fio_protocol_s *pr) {
819
818
  http1pr_s *p = (http1pr_s *)pr;
820
819
  http1_pr2handle(p).status = 0;
821
820
  http_s_destroy(&http1_pr2handle(p), 0);
822
- // FIO_LOG_DEBUG("Deallocating HTTP/1.1 protocol %p(%d)=>%p", (void
823
- // *)p->p.uuid, (int)fio_uuid2fd(p->p.uuid), (void *)p);
824
821
  fio_free(p); // occasional Windows crash bug
822
+ // FIO_LOG_DEBUG("Deallocated HTTP/1.1 protocol at. %p", (void *)p);
823
+ }
824
+
825
+ /* *****************************************************************************
826
+ Protocol Data
827
+ ***************************************************************************** */
828
+
829
+ // clang-format off
830
+ #define HTTP_SET_STATUS_STR(status, str) [((status)-100)] = { .data = (char*)("HTTP/1.1 " #status " " str "\r\n"), .len = (sizeof("HTTP/1.1 " #status " " str "\r\n") - 1) }
831
+ // #undef HTTP_SET_STATUS_STR
832
+ // clang-format on
833
+
834
+ static fio_str_info_s http1pr_status2str(uintptr_t status) {
835
+ static fio_str_info_s status2str[] = {
836
+ HTTP_SET_STATUS_STR(100, "Continue"),
837
+ HTTP_SET_STATUS_STR(101, "Switching Protocols"),
838
+ HTTP_SET_STATUS_STR(102, "Processing"),
839
+ HTTP_SET_STATUS_STR(103, "Early Hints"),
840
+ HTTP_SET_STATUS_STR(200, "OK"),
841
+ HTTP_SET_STATUS_STR(201, "Created"),
842
+ HTTP_SET_STATUS_STR(202, "Accepted"),
843
+ HTTP_SET_STATUS_STR(203, "Non-Authoritative Information"),
844
+ HTTP_SET_STATUS_STR(204, "No Content"),
845
+ HTTP_SET_STATUS_STR(205, "Reset Content"),
846
+ HTTP_SET_STATUS_STR(206, "Partial Content"),
847
+ HTTP_SET_STATUS_STR(207, "Multi-Status"),
848
+ HTTP_SET_STATUS_STR(208, "Already Reported"),
849
+ HTTP_SET_STATUS_STR(226, "IM Used"),
850
+ HTTP_SET_STATUS_STR(300, "Multiple Choices"),
851
+ HTTP_SET_STATUS_STR(301, "Moved Permanently"),
852
+ HTTP_SET_STATUS_STR(302, "Found"),
853
+ HTTP_SET_STATUS_STR(303, "See Other"),
854
+ HTTP_SET_STATUS_STR(304, "Not Modified"),
855
+ HTTP_SET_STATUS_STR(305, "Use Proxy"),
856
+ HTTP_SET_STATUS_STR(306, "(Unused), "),
857
+ HTTP_SET_STATUS_STR(307, "Temporary Redirect"),
858
+ HTTP_SET_STATUS_STR(308, "Permanent Redirect"),
859
+ HTTP_SET_STATUS_STR(400, "Bad Request"),
860
+ HTTP_SET_STATUS_STR(403, "Forbidden"),
861
+ HTTP_SET_STATUS_STR(404, "Not Found"),
862
+ HTTP_SET_STATUS_STR(401, "Unauthorized"),
863
+ HTTP_SET_STATUS_STR(402, "Payment Required"),
864
+ HTTP_SET_STATUS_STR(405, "Method Not Allowed"),
865
+ HTTP_SET_STATUS_STR(406, "Not Acceptable"),
866
+ HTTP_SET_STATUS_STR(407, "Proxy Authentication Required"),
867
+ HTTP_SET_STATUS_STR(408, "Request Timeout"),
868
+ HTTP_SET_STATUS_STR(409, "Conflict"),
869
+ HTTP_SET_STATUS_STR(410, "Gone"),
870
+ HTTP_SET_STATUS_STR(411, "Length Required"),
871
+ HTTP_SET_STATUS_STR(412, "Precondition Failed"),
872
+ HTTP_SET_STATUS_STR(413, "Payload Too Large"),
873
+ HTTP_SET_STATUS_STR(414, "URI Too Long"),
874
+ HTTP_SET_STATUS_STR(415, "Unsupported Media Type"),
875
+ HTTP_SET_STATUS_STR(416, "Range Not Satisfiable"),
876
+ HTTP_SET_STATUS_STR(417, "Expectation Failed"),
877
+ HTTP_SET_STATUS_STR(421, "Misdirected Request"),
878
+ HTTP_SET_STATUS_STR(422, "Unprocessable Entity"),
879
+ HTTP_SET_STATUS_STR(423, "Locked"),
880
+ HTTP_SET_STATUS_STR(424, "Failed Dependency"),
881
+ HTTP_SET_STATUS_STR(425, "Unassigned"),
882
+ HTTP_SET_STATUS_STR(426, "Upgrade Required"),
883
+ HTTP_SET_STATUS_STR(427, "Unassigned"),
884
+ HTTP_SET_STATUS_STR(428, "Precondition Required"),
885
+ HTTP_SET_STATUS_STR(429, "Too Many Requests"),
886
+ HTTP_SET_STATUS_STR(430, "Unassigned"),
887
+ HTTP_SET_STATUS_STR(431, "Request Header Fields Too Large"),
888
+ HTTP_SET_STATUS_STR(500, "Internal Server Error"),
889
+ HTTP_SET_STATUS_STR(501, "Not Implemented"),
890
+ HTTP_SET_STATUS_STR(502, "Bad Gateway"),
891
+ HTTP_SET_STATUS_STR(503, "Service Unavailable"),
892
+ HTTP_SET_STATUS_STR(504, "Gateway Timeout"),
893
+ HTTP_SET_STATUS_STR(505, "HTTP Version Not Supported"),
894
+ HTTP_SET_STATUS_STR(506, "Variant Also Negotiates"),
895
+ HTTP_SET_STATUS_STR(507, "Insufficient Storage"),
896
+ HTTP_SET_STATUS_STR(508, "Loop Detected"),
897
+ HTTP_SET_STATUS_STR(509, "Unassigned"),
898
+ HTTP_SET_STATUS_STR(510, "Not Extended"),
899
+ HTTP_SET_STATUS_STR(511, "Network Authentication Required"),
900
+ };
901
+ fio_str_info_s ret = (fio_str_info_s){.len = 0, .data = NULL};
902
+ if (status >= 100 &&
903
+ (status - 100) < sizeof(status2str) / sizeof(status2str[0]))
904
+ ret = status2str[status - 100];
905
+ if (!ret.data) {
906
+ ret = status2str[400];
907
+ }
908
+ return ret;
825
909
  }
910
+ #undef HTTP_SET_STATUS_STR