picohttp 0.1.0 → 0.2.0

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: bba60b163b964308fafcdb14504076d28df6831bb2ebf80c9c3b8676f29f4734
4
- data.tar.gz: 43ac8f3c3273fb49360d55d765c5c3ade646b3c503bb18eb23c211f7e4c4109a
3
+ metadata.gz: 3b357892a265429f3731c5cc68f56aaa3649b1f346a9c86f021bb67be2e601ac
4
+ data.tar.gz: 7a499b9fe596ee583c238956d66f05f3ff6caeabd0594a5db1d0f3c1b6d3e023
5
5
  SHA512:
6
- metadata.gz: 65d914a80ec411ddc53b7e0982f6896f8f1315cd07a8daa01a50cc8d8183fefed315ee51525cef2131a28de00809ed5a1d719cebb5df0785bf03bc218bdc945d
7
- data.tar.gz: 9229f345ba7d0945066dd60b81b3fbfbeb3c04e8e4ab1f7b7edc13636654d9f6be562ead8e1a5b3ac479f744342395e6d65f3e5a833522f7787e8fc161318df4
6
+ metadata.gz: 704efdbcbd2daab576977d4f2857307a7de44a41b5785cc6d215886777b7d97e3e3ba257670e40afd4c0b49f05024c8e1b26f1a8a41864e5b70393736a26fe6a
7
+ data.tar.gz: 7318f991db2981ed09349edfd907141342121fa65f3a45fa0e51dc2503b973b1c83681356eacad29fd1f95c44af130ad1eb0952e52ae04e4a139678bf172d016
@@ -10,4 +10,7 @@ append_cflags("-fvisibility=hidden")
10
10
  # Check for Ractor support
11
11
  have_func("rb_ext_ractor_safe", "ruby.h")
12
12
 
13
+ # Check for rb_hash_new_capa (Ruby 3.2+)
14
+ have_func("rb_hash_new_capa", "ruby.h")
15
+
13
16
  create_makefile("picohttp/picohttp")
@@ -2,6 +2,7 @@
2
2
  #include "picohttpparser.h"
3
3
 
4
4
  #define MAX_HEADER_NAME_LEN 256
5
+ #define MAX_HEADERS 100
5
6
 
6
7
  VALUE rb_mPicohttp;
7
8
  VALUE rb_ePicohttpParseError;
@@ -12,6 +13,30 @@ static VALUE rb_str_server_protocol;
12
13
  static VALUE rb_str_path_info;
13
14
  static VALUE rb_str_query_string;
14
15
  static VALUE rb_str_empty;
16
+ static VALUE rb_str_http_1_0;
17
+ static VALUE rb_str_http_1_1;
18
+
19
+ #include "string_lookup.inc"
20
+
21
+ static VALUE
22
+ http_version_string(int minor_version)
23
+ {
24
+ if (minor_version == 0) {
25
+ return rb_str_http_1_0;
26
+ } else if (minor_version == 1) {
27
+ return rb_str_http_1_1;
28
+ } else {
29
+ return rb_sprintf("HTTP/1.%d", minor_version);
30
+ }
31
+ }
32
+
33
+ static VALUE
34
+ http_method_string(const char *method, size_t method_len)
35
+ {
36
+ VALUE str = lookup_method(method, method_len);
37
+ if (str == Qnil) str = rb_str_new(method, method_len);
38
+ return str;
39
+ }
15
40
 
16
41
  static VALUE
17
42
  header_name_to_env_key(const char *name, size_t name_len)
@@ -20,6 +45,11 @@ header_name_to_env_key(const char *name, size_t name_len)
20
45
  rb_raise(rb_ePicohttpParseError, "Header name too long");
21
46
  }
22
47
 
48
+ VALUE str = lookup_header(name, name_len);
49
+ if (str != Qnil) {
50
+ return str;
51
+ }
52
+
23
53
  char env_name[MAX_HEADER_NAME_LEN + 6]; // "HTTP_" + name + null terminator
24
54
  strcpy(env_name, "HTTP_");
25
55
 
@@ -48,7 +78,7 @@ picohttp_parse_request(VALUE self, VALUE str)
48
78
 
49
79
  const char *method, *path;
50
80
  int minor_version;
51
- struct phr_header headers[100];
81
+ struct phr_header headers[MAX_HEADERS];
52
82
  size_t method_len, path_len, num_headers = sizeof(headers) / sizeof(headers[0]);
53
83
 
54
84
  int result = phr_parse_request(buf, len, &method, &method_len, &path, &path_len,
@@ -89,7 +119,7 @@ picohttp_parse_request_env(VALUE self, VALUE str)
89
119
 
90
120
  const char *method, *path;
91
121
  int minor_version;
92
- struct phr_header headers[100];
122
+ struct phr_header headers[MAX_HEADERS];
93
123
  size_t method_len, path_len, num_headers = sizeof(headers) / sizeof(headers[0]);
94
124
 
95
125
  int result = phr_parse_request(buf, len, &method, &method_len, &path, &path_len,
@@ -102,22 +132,33 @@ picohttp_parse_request_env(VALUE self, VALUE str)
102
132
  rb_raise(rb_ePicohttpParseError, "Invalid HTTP request");
103
133
  }
104
134
 
105
- VALUE env = rb_hash_new();
135
+ VALUE header_values[MAX_HEADERS * 2];
136
+ int idx = 0;
106
137
 
107
138
  // Standard CGI/Rack environment variables
108
- rb_hash_aset(env, rb_str_request_method, rb_str_new(method, method_len));
109
- rb_hash_aset(env, rb_str_server_protocol, rb_sprintf("HTTP/1.%d", minor_version));
139
+ header_values[idx++] = rb_str_request_method;
140
+ header_values[idx++] = http_method_string(method, method_len);
141
+
142
+ header_values[idx++] = rb_str_server_protocol;
143
+ header_values[idx++] = http_version_string(minor_version);
110
144
 
111
145
  // Parse path and query string in C
112
146
  const char *query_start = memchr(path, '?', path_len);
113
147
  if (query_start) {
114
148
  size_t path_info_len = query_start - path;
115
149
  size_t query_len = path_len - path_info_len - 1;
116
- rb_hash_aset(env, rb_str_path_info, rb_str_new(path, path_info_len));
117
- rb_hash_aset(env, rb_str_query_string, rb_str_new(query_start + 1, query_len));
150
+
151
+ header_values[idx++] = rb_str_path_info;
152
+ header_values[idx++] = rb_str_new(path, path_info_len);
153
+
154
+ header_values[idx++] = rb_str_query_string;
155
+ header_values[idx++] = rb_str_new(query_start + 1, query_len);
118
156
  } else {
119
- rb_hash_aset(env, rb_str_path_info, rb_str_new(path, path_len));
120
- rb_hash_aset(env, rb_str_query_string, rb_str_empty);
157
+ header_values[idx++] = rb_str_path_info;
158
+ header_values[idx++] = rb_str_new(path, path_len);
159
+
160
+ header_values[idx++] = rb_str_query_string;
161
+ header_values[idx++] = rb_str_empty;
121
162
  }
122
163
 
123
164
  // Convert headers to HTTP_ prefixed environment variables
@@ -126,11 +167,18 @@ picohttp_parse_request_env(VALUE self, VALUE str)
126
167
  rb_raise(rb_ePicohttpParseError, "HTTP line folding not supported");
127
168
  }
128
169
 
129
- VALUE header_name = header_name_to_env_key(headers[i].name, headers[i].name_len);
130
- VALUE header_value = rb_str_new(headers[i].value, headers[i].value_len);
131
- rb_hash_aset(env, header_name, header_value);
170
+ header_values[idx++] = header_name_to_env_key(headers[i].name, headers[i].name_len);
171
+ header_values[idx++] = rb_str_new(headers[i].value, headers[i].value_len);
132
172
  }
133
173
 
174
+ #ifdef HAVE_RB_HASH_NEW_CAPA
175
+ VALUE env = rb_hash_new_capa(idx / 2);
176
+ #else
177
+ VALUE env = rb_hash_new();
178
+ #endif
179
+
180
+ rb_hash_bulk_insert(idx, header_values, env);
181
+
134
182
  return env;
135
183
  }
136
184
 
@@ -147,11 +195,14 @@ Init_picohttp(void)
147
195
  rb_define_module_function(rb_mPicohttp, "parse_request_env", picohttp_parse_request_env, 1);
148
196
 
149
197
  // Initialize interned string constants
198
+ init_string_lookup();
150
199
  rb_str_request_method = rb_interned_str_cstr("REQUEST_METHOD");
151
200
  rb_str_server_protocol = rb_interned_str_cstr("SERVER_PROTOCOL");
152
201
  rb_str_path_info = rb_interned_str_cstr("PATH_INFO");
153
202
  rb_str_query_string = rb_interned_str_cstr("QUERY_STRING");
154
203
  rb_str_empty = rb_interned_str_cstr("");
204
+ rb_str_http_1_0 = rb_interned_str_cstr("HTTP/1.0");
205
+ rb_str_http_1_1 = rb_interned_str_cstr("HTTP/1.1");
155
206
 
156
207
  // Prevent garbage collection of constants
157
208
  rb_gc_register_address(&rb_str_request_method);
@@ -159,4 +210,6 @@ Init_picohttp(void)
159
210
  rb_gc_register_address(&rb_str_path_info);
160
211
  rb_gc_register_address(&rb_str_query_string);
161
212
  rb_gc_register_address(&rb_str_empty);
213
+ rb_gc_register_address(&rb_str_http_1_0);
214
+ rb_gc_register_address(&rb_str_http_1_1);
162
215
  }
@@ -0,0 +1,120 @@
1
+ /* This file is auto-generated by tool/generate_lookup.rb */
2
+
3
+ static VALUE rb_s_HTTP_HOST; /* "HTTP_HOST" */
4
+ static VALUE rb_s_HTTP_ACCEPT; /* "HTTP_ACCEPT" */
5
+ static VALUE rb_s_HTTP_COOKIE; /* "HTTP_COOKIE" */
6
+ static VALUE rb_s_HTTP_REFERER; /* "HTTP_REFERER" */
7
+ static VALUE rb_s_HTTP_USER_AGENT; /* "HTTP_USER_AGENT" */
8
+ static VALUE rb_s_HTTP_CONNECTION; /* "HTTP_CONNECTION" */
9
+ static VALUE rb_s_CONTENT_TYPE; /* "CONTENT_TYPE" */
10
+ static VALUE rb_s_HTTP_CACHE_CONTROL; /* "HTTP_CACHE_CONTROL" */
11
+ static VALUE rb_s_HTTP_AUTHORIZATION; /* "HTTP_AUTHORIZATION" */
12
+ static VALUE rb_s_CONTENT_LENGTH; /* "CONTENT_LENGTH" */
13
+ static VALUE rb_s_HTTP_ACCEPT_ENCODING; /* "HTTP_ACCEPT_ENCODING" */
14
+ static VALUE rb_s_HTTP_ACCEPT_LANGUAGE; /* "HTTP_ACCEPT_LANGUAGE" */
15
+ static VALUE rb_s_GET; /* "GET" */
16
+ static VALUE rb_s_PUT; /* "PUT" */
17
+ static VALUE rb_s_POST; /* "POST" */
18
+ static VALUE rb_s_HEAD; /* "HEAD" */
19
+ static VALUE rb_s_PATCH; /* "PATCH" */
20
+ static VALUE rb_s_DELETE; /* "DELETE" */
21
+ static VALUE rb_s_OPTIONS; /* "OPTIONS" */
22
+
23
+ static VALUE lookup_header(const char *s, size_t len) {
24
+ switch (len) {
25
+ case 4:
26
+ if ((s[0] | 32) == 'h' && (s[1] | 32) == 'o' && (s[2] | 32) == 's' && (s[3] | 32) == 't') return rb_s_HTTP_HOST;
27
+ break;
28
+ case 6:
29
+ if ((s[0] | 32) == 'a' && (s[1] | 32) == 'c' && (s[2] | 32) == 'c' && (s[3] | 32) == 'e' && (s[4] | 32) == 'p' && (s[5] | 32) == 't') return rb_s_HTTP_ACCEPT;
30
+ if ((s[0] | 32) == 'c' && (s[1] | 32) == 'o' && (s[2] | 32) == 'o' && (s[3] | 32) == 'k' && (s[4] | 32) == 'i' && (s[5] | 32) == 'e') return rb_s_HTTP_COOKIE;
31
+ break;
32
+ case 7:
33
+ if ((s[0] | 32) == 'r' && (s[1] | 32) == 'e' && (s[2] | 32) == 'f' && (s[3] | 32) == 'e' && (s[4] | 32) == 'r' && (s[5] | 32) == 'e' && (s[6] | 32) == 'r') return rb_s_HTTP_REFERER;
34
+ break;
35
+ case 10:
36
+ if ((s[0] | 32) == 'u' && (s[1] | 32) == 's' && (s[2] | 32) == 'e' && (s[3] | 32) == 'r' && (s[4] | 32) == '-' && (s[5] | 32) == 'a' && (s[6] | 32) == 'g' && (s[7] | 32) == 'e' && (s[8] | 32) == 'n' && (s[9] | 32) == 't') return rb_s_HTTP_USER_AGENT;
37
+ if ((s[0] | 32) == 'c' && (s[1] | 32) == 'o' && (s[2] | 32) == 'n' && (s[3] | 32) == 'n' && (s[4] | 32) == 'e' && (s[5] | 32) == 'c' && (s[6] | 32) == 't' && (s[7] | 32) == 'i' && (s[8] | 32) == 'o' && (s[9] | 32) == 'n') return rb_s_HTTP_CONNECTION;
38
+ break;
39
+ case 12:
40
+ if ((s[0] | 32) == 'c' && (s[1] | 32) == 'o' && (s[2] | 32) == 'n' && (s[3] | 32) == 't' && (s[4] | 32) == 'e' && (s[5] | 32) == 'n' && (s[6] | 32) == 't' && (s[7] | 32) == '-' && (s[8] | 32) == 't' && (s[9] | 32) == 'y' && (s[10] | 32) == 'p' && (s[11] | 32) == 'e') return rb_s_CONTENT_TYPE;
41
+ break;
42
+ case 13:
43
+ if ((s[0] | 32) == 'c' && (s[1] | 32) == 'a' && (s[2] | 32) == 'c' && (s[3] | 32) == 'h' && (s[4] | 32) == 'e' && (s[5] | 32) == '-' && (s[6] | 32) == 'c' && (s[7] | 32) == 'o' && (s[8] | 32) == 'n' && (s[9] | 32) == 't' && (s[10] | 32) == 'r' && (s[11] | 32) == 'o' && (s[12] | 32) == 'l') return rb_s_HTTP_CACHE_CONTROL;
44
+ if ((s[0] | 32) == 'a' && (s[1] | 32) == 'u' && (s[2] | 32) == 't' && (s[3] | 32) == 'h' && (s[4] | 32) == 'o' && (s[5] | 32) == 'r' && (s[6] | 32) == 'i' && (s[7] | 32) == 'z' && (s[8] | 32) == 'a' && (s[9] | 32) == 't' && (s[10] | 32) == 'i' && (s[11] | 32) == 'o' && (s[12] | 32) == 'n') return rb_s_HTTP_AUTHORIZATION;
45
+ break;
46
+ case 14:
47
+ if ((s[0] | 32) == 'c' && (s[1] | 32) == 'o' && (s[2] | 32) == 'n' && (s[3] | 32) == 't' && (s[4] | 32) == 'e' && (s[5] | 32) == 'n' && (s[6] | 32) == 't' && (s[7] | 32) == '-' && (s[8] | 32) == 'l' && (s[9] | 32) == 'e' && (s[10] | 32) == 'n' && (s[11] | 32) == 'g' && (s[12] | 32) == 't' && (s[13] | 32) == 'h') return rb_s_CONTENT_LENGTH;
48
+ break;
49
+ case 15:
50
+ if ((s[0] | 32) == 'a' && (s[1] | 32) == 'c' && (s[2] | 32) == 'c' && (s[3] | 32) == 'e' && (s[4] | 32) == 'p' && (s[5] | 32) == 't' && (s[6] | 32) == '-' && (s[7] | 32) == 'e' && (s[8] | 32) == 'n' && (s[9] | 32) == 'c' && (s[10] | 32) == 'o' && (s[11] | 32) == 'd' && (s[12] | 32) == 'i' && (s[13] | 32) == 'n' && (s[14] | 32) == 'g') return rb_s_HTTP_ACCEPT_ENCODING;
51
+ if ((s[0] | 32) == 'a' && (s[1] | 32) == 'c' && (s[2] | 32) == 'c' && (s[3] | 32) == 'e' && (s[4] | 32) == 'p' && (s[5] | 32) == 't' && (s[6] | 32) == '-' && (s[7] | 32) == 'l' && (s[8] | 32) == 'a' && (s[9] | 32) == 'n' && (s[10] | 32) == 'g' && (s[11] | 32) == 'u' && (s[12] | 32) == 'a' && (s[13] | 32) == 'g' && (s[14] | 32) == 'e') return rb_s_HTTP_ACCEPT_LANGUAGE;
52
+ break;
53
+ }
54
+ return Qnil;
55
+ }
56
+
57
+ static VALUE lookup_method(const char *s, size_t len) {
58
+ switch (len) {
59
+ case 3:
60
+ if (s[0] == 'G' && s[1] == 'E' && s[2] == 'T') return rb_s_GET;
61
+ if (s[0] == 'P' && s[1] == 'U' && s[2] == 'T') return rb_s_PUT;
62
+ break;
63
+ case 4:
64
+ if (s[0] == 'P' && s[1] == 'O' && s[2] == 'S' && s[3] == 'T') return rb_s_POST;
65
+ if (s[0] == 'H' && s[1] == 'E' && s[2] == 'A' && s[3] == 'D') return rb_s_HEAD;
66
+ break;
67
+ case 5:
68
+ if (s[0] == 'P' && s[1] == 'A' && s[2] == 'T' && s[3] == 'C' && s[4] == 'H') return rb_s_PATCH;
69
+ break;
70
+ case 6:
71
+ if (s[0] == 'D' && s[1] == 'E' && s[2] == 'L' && s[3] == 'E' && s[4] == 'T' && s[5] == 'E') return rb_s_DELETE;
72
+ break;
73
+ case 7:
74
+ if (s[0] == 'O' && s[1] == 'P' && s[2] == 'T' && s[3] == 'I' && s[4] == 'O' && s[5] == 'N' && s[6] == 'S') return rb_s_OPTIONS;
75
+ break;
76
+ }
77
+ return Qnil;
78
+ }
79
+
80
+ static void init_string_lookup(void) {
81
+ rb_gc_register_address(&rb_s_HTTP_HOST);
82
+ rb_s_HTTP_HOST = rb_interned_str_cstr("HTTP_HOST");
83
+ rb_gc_register_address(&rb_s_HTTP_ACCEPT);
84
+ rb_s_HTTP_ACCEPT = rb_interned_str_cstr("HTTP_ACCEPT");
85
+ rb_gc_register_address(&rb_s_HTTP_COOKIE);
86
+ rb_s_HTTP_COOKIE = rb_interned_str_cstr("HTTP_COOKIE");
87
+ rb_gc_register_address(&rb_s_HTTP_REFERER);
88
+ rb_s_HTTP_REFERER = rb_interned_str_cstr("HTTP_REFERER");
89
+ rb_gc_register_address(&rb_s_HTTP_USER_AGENT);
90
+ rb_s_HTTP_USER_AGENT = rb_interned_str_cstr("HTTP_USER_AGENT");
91
+ rb_gc_register_address(&rb_s_HTTP_CONNECTION);
92
+ rb_s_HTTP_CONNECTION = rb_interned_str_cstr("HTTP_CONNECTION");
93
+ rb_gc_register_address(&rb_s_CONTENT_TYPE);
94
+ rb_s_CONTENT_TYPE = rb_interned_str_cstr("CONTENT_TYPE");
95
+ rb_gc_register_address(&rb_s_HTTP_CACHE_CONTROL);
96
+ rb_s_HTTP_CACHE_CONTROL = rb_interned_str_cstr("HTTP_CACHE_CONTROL");
97
+ rb_gc_register_address(&rb_s_HTTP_AUTHORIZATION);
98
+ rb_s_HTTP_AUTHORIZATION = rb_interned_str_cstr("HTTP_AUTHORIZATION");
99
+ rb_gc_register_address(&rb_s_CONTENT_LENGTH);
100
+ rb_s_CONTENT_LENGTH = rb_interned_str_cstr("CONTENT_LENGTH");
101
+ rb_gc_register_address(&rb_s_HTTP_ACCEPT_ENCODING);
102
+ rb_s_HTTP_ACCEPT_ENCODING = rb_interned_str_cstr("HTTP_ACCEPT_ENCODING");
103
+ rb_gc_register_address(&rb_s_HTTP_ACCEPT_LANGUAGE);
104
+ rb_s_HTTP_ACCEPT_LANGUAGE = rb_interned_str_cstr("HTTP_ACCEPT_LANGUAGE");
105
+ rb_gc_register_address(&rb_s_GET);
106
+ rb_s_GET = rb_interned_str_cstr("GET");
107
+ rb_gc_register_address(&rb_s_PUT);
108
+ rb_s_PUT = rb_interned_str_cstr("PUT");
109
+ rb_gc_register_address(&rb_s_POST);
110
+ rb_s_POST = rb_interned_str_cstr("POST");
111
+ rb_gc_register_address(&rb_s_HEAD);
112
+ rb_s_HEAD = rb_interned_str_cstr("HEAD");
113
+ rb_gc_register_address(&rb_s_PATCH);
114
+ rb_s_PATCH = rb_interned_str_cstr("PATCH");
115
+ rb_gc_register_address(&rb_s_DELETE);
116
+ rb_s_DELETE = rb_interned_str_cstr("DELETE");
117
+ rb_gc_register_address(&rb_s_OPTIONS);
118
+ rb_s_OPTIONS = rb_interned_str_cstr("OPTIONS");
119
+ }
120
+
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Picohttp
4
- VERSION = "0.1.0"
4
+ VERSION = "0.2.0"
5
5
  end
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Generates fast C lookup code for known string sets
5
+
6
+ puts "/* This file is auto-generated by #{__FILE__} */"
7
+ puts
8
+
9
+ class StringLookup
10
+ def initialize
11
+ @string_table = Hash.new do |h, k|
12
+ h[k] = name_for_string(k)
13
+ end
14
+ @functions = []
15
+ end
16
+
17
+ def generate
18
+ @string_table.each do |v, name|
19
+ puts "static VALUE #{name}; /* #{v.inspect} */"
20
+ end
21
+ puts
22
+
23
+ @functions.each do |code|
24
+ puts code
25
+ puts
26
+ end
27
+
28
+ puts "static void init_string_lookup(void) {"
29
+ @string_table.each do |v, name|
30
+ puts " rb_gc_register_address(&#{name});"
31
+ puts " #{name} = rb_interned_str_cstr(#{v.dump});"
32
+ end
33
+ puts "}"
34
+ puts
35
+ end
36
+
37
+ def name_for_string(string)
38
+ "rb_s_#{string.gsub(/[^a-z0-9]/i, "_")}"
39
+ end
40
+
41
+ def generate_comparison(var, string, ignore_case: false)
42
+ 0.upto(string.length - 1).map do |i|
43
+ if ignore_case
44
+ "(#{var}[#{i}] | 32) == '#{string[i].downcase}'"
45
+ else
46
+ "#{var}[#{i}] == '#{string[i]}'"
47
+ end
48
+ end.join(" && ")
49
+ end
50
+
51
+ def add_function(function, mapping, ignore_case: false)
52
+ if mapping.is_a?(Array)
53
+ mapping = mapping.map do |str|
54
+ [str, str]
55
+ end.to_h
56
+ end
57
+ by_length = mapping.group_by do |(k,v)|
58
+ k.length
59
+ end
60
+
61
+ code = []
62
+ code << "static VALUE lookup_#{function}(const char *s, size_t len) {"
63
+ code << " switch (len) {"
64
+
65
+ by_length.sort.each do |len, strs|
66
+ code << " case #{len}:"
67
+ strs.each do |match, target|
68
+ name = @string_table[target]
69
+ code << " if (#{generate_comparison("s", match, ignore_case:)}) return #{name};"
70
+ end
71
+ code << " break;"
72
+ end
73
+
74
+ code << " }"
75
+ code << " return Qnil;"
76
+ code << "}"
77
+
78
+ @functions << code.join("\n")
79
+ end
80
+ end
81
+
82
+ HEADERS = %w[Content-Type Content-Length Host User-Agent Accept Accept-Encoding
83
+ Accept-Language Connection Cache-Control Cookie Authorization Referer]
84
+
85
+ METHODS = %w[GET POST PUT DELETE HEAD OPTIONS PATCH]
86
+
87
+ lookup = StringLookup.new
88
+ header_mapping = HEADERS.map do |header|
89
+ header = header.downcase
90
+ rack_key = header.upcase.gsub("-", "_")
91
+ unless header == "content-type" || header == "content-length"
92
+ rack_key = "HTTP_#{rack_key}"
93
+ end
94
+ [header, rack_key]
95
+ end.to_h
96
+ lookup.add_function("header", header_mapping, ignore_case: true)
97
+ lookup.add_function("method", METHODS)
98
+ lookup.generate
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: picohttp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - John Hawthorn
@@ -27,8 +27,10 @@ files:
27
27
  - ext/picohttp/picohttp.h
28
28
  - ext/picohttp/picohttpparser.c
29
29
  - ext/picohttp/picohttpparser.h
30
+ - ext/picohttp/string_lookup.inc
30
31
  - lib/picohttp.rb
31
32
  - lib/picohttp/version.rb
33
+ - tool/generate_lookup.rb
32
34
  homepage: https://github.com/jhawthorn/picohttp
33
35
  licenses:
34
36
  - MIT
@@ -52,7 +54,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
54
  - !ruby/object:Gem::Version
53
55
  version: '0'
54
56
  requirements: []
55
- rubygems_version: 3.6.9
57
+ rubygems_version: 4.0.2
56
58
  specification_version: 4
57
59
  summary: Fast HTTP request parser using picohttpparser
58
60
  test_files: []