agoo 2.12.1 → 2.14.1

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: 90300e7360e69307918af1de597ef316750dfe9b1970c5f92ff57913bd971401
4
- data.tar.gz: dba7a5bda4f9d1405d17f738e84d049a8a9d32b79336581d0b7f11f190ec11ea
3
+ metadata.gz: 0fbaa8a1e2f42cda657178256643bcf0161f93d9be09e90512084eb877b12aa9
4
+ data.tar.gz: e33135684316f9e0244f0cc2e781561f99374888c7756866e0d2ed33db1c0446
5
5
  SHA512:
6
- metadata.gz: faccbdb3de3a337fd54106bacf060cac12aec30171f9401b3f672b8f3c49a0a968decdd7cf2c4726be00810f2d788ab14bdaa1479b8b148017211db78a5f2d08
7
- data.tar.gz: 8fbff6ad71237aa796d00cde0eeb6a5b1600a6a188c53af7319bee74ff1f146df8e78ed2cfdff33404c3dd38de568654fe5e8dad2427e3ff780378bba2cbb74b
6
+ metadata.gz: 630cf6226a74119dbb5417a8a33df2893e08e61acd6037f61d6d6a1d424c22a7bb61bfa59c65420b3e4026a421764b128b36ca9ae5dc2087722f338228f2e732
7
+ data.tar.gz: 6798931eaa91d29ccc0e6abe701cc62cc44b129b22e34f0f0dc53e26f409ca27c7a001424197f9c4c2f02820a8a670e38609e408ca4b6e5069957c9981a6b49f
data/CHANGELOG.md CHANGED
@@ -2,6 +2,48 @@
2
2
 
3
3
  All changes to the Agoo gem are documented here. Releases follow semantic versioning.
4
4
 
5
+ ## [2.14.1] - 2021-06-09
6
+
7
+ ### Fixed
8
+ - Evaluating an empty GraphQL request with comments only no longer crashes.
9
+ - JSON parser bug fixed.
10
+
11
+ ## [2.14.0] - 2020-11-07
12
+
13
+ ### Added
14
+
15
+ - REMOTE_ADDR element added to requests/env argument to `call()`.
16
+
17
+ - Added check for multiple Content-Length headers.
18
+
19
+ - Multiple occurrances of a header are now passed to the Rack `call()` method as an array.
20
+
21
+ ## [2.13.0] - 2020-07-05
22
+
23
+ ### Added
24
+
25
+ - Agoo::Server.use() added. It works similar to the Rack use() function.
26
+
27
+ ### Fixed
28
+
29
+ - Header checks are now case insensitive to comply with RFC 7230.
30
+
31
+ ## [2.12.3] - 2020-03-28
32
+
33
+ rb_rescue2 termination
34
+
35
+ ### Fixed
36
+
37
+ - rb_rescue2 must be terminated by a (VALUE)0 and not simply 0.
38
+
39
+ ## [2.12.2] - 2020-03-22
40
+
41
+ Stub generator
42
+
43
+ ### Added
44
+
45
+ - GraphQL stub generator to generate Ruby class file corresponding to GraphQL schema type. The generator is `bin/agoo_stubs`.
46
+
5
47
  ## [2.12.1] - 2020-03-17
6
48
 
7
49
  Check SO_REUSEPORT
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # agoo
1
+ # [![{}j](misc/agoo_128.svg)](http://www.ohler.com/agoo) Agoo
2
2
 
3
3
  [![Build Status](https://img.shields.io/travis/ohler55/agoo/master.svg)](http://travis-ci.org/ohler55/agoo?branch=master)
4
4
  [![Gem Version](https://badge.fury.io/rb/agoo.svg)](https://badge.fury.io/rb/agoo)
@@ -68,6 +68,31 @@ sleep
68
68
  gem install agoo
69
69
  ```
70
70
 
71
+ ## Using agoo as server for rails
72
+
73
+ As agoo supports rack compatible apps you can use it for rails applications:
74
+
75
+ Add agoo to the Gemfile:
76
+
77
+ ```
78
+ # Gemfile
79
+ gem 'agoo'
80
+ ```
81
+
82
+ Install bundle:
83
+
84
+ ```
85
+ $ bundle install
86
+ ```
87
+
88
+ Start rails with agoo as server:
89
+
90
+ ```
91
+ $ rails server -u agoo
92
+ ```
93
+
94
+ Enjoy the increased performance!
95
+
71
96
  ## What Is This?
72
97
 
73
98
  Agoo is Japanese for a type of flying fish. This gem flies. It is a high
@@ -139,4 +164,3 @@ the develop branch. Pull requests should be made against the develop branch.
139
164
 
140
165
  - *Perfer* *repo*: https://github.com/ohler55/perfer
141
166
 
142
- Follow [@peterohler on Twitter](http://twitter.com/#!/peterohler) for announcements and news about the Agoo gem.
data/bin/agoo_stubs ADDED
@@ -0,0 +1,166 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ while (index = ARGV.index('-I'))
4
+ _, path = ARGV.slice!(index, 2)
5
+ $LOAD_PATH << path
6
+ end
7
+
8
+ require 'optparse'
9
+
10
+ require 'agoo'
11
+
12
+ usage = %{
13
+ Usage: agoo_stubs [options] <graphql_schema>
14
+
15
+ version #{Agoo::VERSION}
16
+
17
+ Generates Ruby files that match the types in the GraphQL schema file specified.
18
+
19
+ Example:
20
+
21
+ agoo_stubs --module Data --dir lib schema.graphql
22
+
23
+ }
24
+
25
+ @verbose = false
26
+ @single = nil
27
+ @dir = nil
28
+ @mod = nil
29
+
30
+ @opts = OptionParser.new(usage)
31
+ @opts.on('-h', '--help', 'show this display') { puts @opts.help; Process.exit!(0) }
32
+ @opts.on('-v', '--verbose', 'verbose output') { @verbose = true }
33
+ @opts.on('-s', '--single PATH', String, 'path to file for all stubs') { |s| @single = s }
34
+ @opts.on('-d', '--dir PATH', String, 'directory to write files into') { |d| @dir = d }
35
+ @opts.on('-m', '--module STRING', String, 'module for the stub classes') { |m| @mod = m }
36
+
37
+ @files = @opts.parse(ARGV)
38
+
39
+ if @files.empty?
40
+ puts "A schema file must be specified."
41
+ puts @opts.help
42
+ Process.exit!(0)
43
+ elsif 1 < @files.size
44
+ puts "Only one schema file can be specified."
45
+ puts @opts.help
46
+ Process.exit!(0)
47
+ end
48
+
49
+ Agoo::GraphQL.schema(nil) {
50
+ Agoo::GraphQL.load_file(@files[0])
51
+ }
52
+
53
+ def write_type_stub(f, t, depth)
54
+ indent = ' ' * depth
55
+ f.puts "#{indent}# #{t.description}" unless t.description.nil?
56
+ f.puts "#{indent}class #{t.name}"
57
+ t.fields.each { |field|
58
+ next unless field.args.nil?
59
+ f.puts "#{indent} # #{field.description}" unless field.description.nil?
60
+ f.puts "#{indent} attr_accessor :#{field.name}"
61
+ }
62
+ f.puts
63
+ f.puts "#{indent} def initialize"
64
+ f.puts "#{indent} end"
65
+ t.fields.each { |field|
66
+ next if field.args.nil?
67
+ f.puts
68
+ f.puts "#{indent} # #{field.description}" unless field.description.nil?
69
+ f.puts "#{indent} # args: #{field.args.map { |a| a.name }.join(', ')}"
70
+ f.puts "#{indent} def #{field.name}(args={})"
71
+ f.puts "#{indent} end"
72
+ }
73
+ f.puts "#{indent}end"
74
+ end
75
+
76
+ def calc_filepath(t)
77
+ path = @dir
78
+ path += '/' + @mod.split('::').map { |m| m.downcase }.join('/') unless @mod.nil?
79
+ path + '/' + t.name.downcase + '.rb'
80
+ end
81
+
82
+ def assure_parent_dir(path)
83
+ dirs = path.split('/')[0..-2]
84
+ dirs.each_index { |i|
85
+ path = dirs[0..i].join('/')
86
+ Dir.mkdir(path) unless Dir.exist?(path)
87
+ }
88
+ end
89
+
90
+ def write_type_stub_file(t)
91
+ path = calc_filepath(t)
92
+ assure_parent_dir(path)
93
+ File.open(path, 'w') { |f|
94
+ f.puts "# #{t.name} class for schema file #{@files[0]}"
95
+ f.puts
96
+ depth = 0
97
+ unless @mod.nil?
98
+ @mod.split('::').each { |m|
99
+ f.puts("#{' ' * depth}module #{m}")
100
+ depth += 1
101
+ }
102
+ f.puts
103
+ end
104
+ write_type_stub(f, t, depth)
105
+ f.puts
106
+ unless @mod.nil?
107
+ @mod.split('::').size.times {
108
+ depth -= 1
109
+ f.puts("#{' ' * depth}end")
110
+ }
111
+ end
112
+ }
113
+ end
114
+
115
+ @out = nil
116
+
117
+ if @dir.nil?
118
+ if @single.nil?
119
+ @out = STDOUT
120
+ else @single
121
+ @out = File.new(@single, 'w')
122
+ end
123
+ end
124
+
125
+ unless @out.nil?
126
+ @out.puts "# Classes for schema file #{@files[0]}"
127
+ @out.puts
128
+ depth = 0
129
+ unless @mod.nil?
130
+ @mod.split('::').each { |m|
131
+ @out.puts("#{' ' * depth}module #{m}")
132
+ depth += 1
133
+ }
134
+ @out.puts
135
+ end
136
+ Agoo::GraphQL.sdl_types.sort { |a,b| a.name <=> b.name }.each { |t|
137
+ write_type_stub(@out, t, depth)
138
+ @out.puts
139
+ }
140
+ unless @mod.nil?
141
+ @mod.split('::').size.times {
142
+ depth -= 1
143
+ @out.puts("#{' ' * depth}end")
144
+ }
145
+ end
146
+ @out.close unless STDOUT == @out
147
+ else
148
+ Agoo::GraphQL.sdl_types.each { |t|
149
+ write_type_stub_file(t)
150
+ }
151
+ unless @mod.nil?
152
+ path = @dir
153
+ path += '/' + @mod.split('::').map { |m| m.downcase }.join('/')
154
+ assure_parent_dir(path)
155
+ m = path.split('/')[-1]
156
+ path += '.rb'
157
+
158
+ File.open(path, 'w') { |f|
159
+ f.puts "# Classes for schema file #{@files[0]}"
160
+ f.puts
161
+ Agoo::GraphQL.sdl_types.sort { |a,b| a.name <=> b.name }.each { |t|
162
+ f.puts "require_relative '#{m}/#{t.name.downcase}'"
163
+ }
164
+ }
165
+ end
166
+ end
data/ext/agoo/bind.c CHANGED
@@ -223,25 +223,25 @@ url_ssl(agooErr err, const char *url) {
223
223
 
224
224
  agooBind
225
225
  agoo_bind_url(agooErr err, const char *url) {
226
- if (0 == strncmp("tcp://", url, 6)) {
226
+ if (0 == strncasecmp("tcp://", url, 6)) {
227
227
  if ('[' == url[6]) {
228
228
  return url_tcp6(err, url + 6, "tcp");
229
229
  }
230
230
  return url_tcp(err, url + 6, "tcp");
231
231
  }
232
- if (0 == strncmp("http://", url, 7)) {
232
+ if (0 == strncasecmp("http://", url, 7)) {
233
233
  if ('[' == url[7]) {
234
234
  return url_tcp6(err, url + 7, "http");
235
235
  }
236
236
  return url_tcp(err, url + 7, "http");
237
237
  }
238
- if (0 == strncmp("unix://", url, 7)) {
238
+ if (0 == strncasecmp("unix://", url, 7)) {
239
239
  return url_named(err, url + 7);
240
240
  }
241
- if (0 == strncmp("https://", url, 8)) {
241
+ if (0 == strncasecmp("https://", url, 8)) {
242
242
  return url_ssl(err, url + 8);
243
243
  }
244
- if (0 == strncmp("ssl://", url, 6)) {
244
+ if (0 == strncasecmp("ssl://", url, 6)) {
245
245
  return url_ssl(err, url + 6);
246
246
  }
247
247
  // All others assume http
data/ext/agoo/con.c CHANGED
@@ -63,6 +63,22 @@ agoo_con_create(agooErr err, int sock, uint64_t id, agooBind b) {
63
63
  if (NULL == (c = (agooCon)AGOO_CALLOC(1, sizeof(struct _agooCon)))) {
64
64
  AGOO_ERR_MEM(err, "Connection");
65
65
  } else {
66
+ // It would be better to get this information in server.c after
67
+ // accept() but that does not work on macOS so instead a call to
68
+ // getpeername() is used instead.
69
+ struct sockaddr_storage addr;
70
+ socklen_t len = sizeof(addr);
71
+
72
+ getpeername(sock, (struct sockaddr*)&addr, &len);
73
+ if (addr.ss_family == AF_INET) {
74
+ struct sockaddr_in *s = (struct sockaddr_in*)&addr;
75
+
76
+ inet_ntop(AF_INET, &s->sin_addr, c->remote, sizeof(c->remote));
77
+ } else {
78
+ struct sockaddr_in6 *s = (struct sockaddr_in6*)&addr;
79
+
80
+ inet_ntop(AF_INET6, &s->sin6_addr, c->remote, sizeof(c->remote));
81
+ }
66
82
  c->sock = sock;
67
83
  c->id = id;
68
84
  c->timeout = dtime() + CON_TIMEOUT;
@@ -173,7 +189,7 @@ agoo_con_header_value(const char *header, int hlen, const char *key, int *vlen)
173
189
  int klen = (int)strlen(key);
174
190
 
175
191
  while (h < hend) {
176
- if (0 == strncmp(key, h, klen) && ':' == h[klen]) {
192
+ if (0 == strncasecmp(key, h, klen) && ':' == h[klen]) {
177
193
  h += klen + 1;
178
194
  for (; ' ' == *h; h++) {
179
195
  }
@@ -437,6 +453,7 @@ con_header_read(agooCon c, size_t *mlenp) {
437
453
  c->req->method = method;
438
454
  c->req->upgrade = AGOO_UP_NONE;
439
455
  c->req->up = NULL;
456
+ memcpy(c->req->remote, c->remote, sizeof(c->remote));
440
457
  c->req->path.start = c->req->msg + (path.start - c->buf);
441
458
  c->req->path.len = (int)(path.end - path.start);
442
459
  c->req->query.start = c->req->msg + (query - c->buf);
data/ext/agoo/con.h CHANGED
@@ -3,6 +3,7 @@
3
3
  #ifndef AGOO_CON_H
4
4
  #define AGOO_CON_H
5
5
 
6
+ #include <arpa/inet.h>
6
7
  #include <poll.h>
7
8
  #include <pthread.h>
8
9
  #include <stdbool.h>
@@ -45,6 +46,7 @@ typedef struct _agooCon {
45
46
  struct _agooBind *bind;
46
47
  struct pollfd *pp;
47
48
  uint64_t id;
49
+ char remote[INET6_ADDRSTRLEN];
48
50
  char buf[MAX_HEADER_SIZE];
49
51
  size_t bcnt;
50
52
 
data/ext/agoo/gqleval.c CHANGED
@@ -551,11 +551,11 @@ eval_post(agooErr err, agooReq req) {
551
551
  agoo_err_set(err, AGOO_ERR_TYPE, "required Content-Type not in the HTTP header");
552
552
  return NULL;
553
553
  }
554
- if (0 == strncmp(graphql_content_type, s, sizeof(graphql_content_type) - 1)) {
554
+ if (0 == strncasecmp(graphql_content_type, s, sizeof(graphql_content_type) - 1)) {
555
555
  if (NULL == (doc = sdl_parse_doc(err, req->body.start, req->body.len, vars, GQL_QUERY))) {
556
556
  return NULL;
557
557
  }
558
- } else if (0 == strncmp(json_content_type, s, sizeof(json_content_type) - 1)) {
558
+ } else if (0 == strncasecmp(json_content_type, s, sizeof(json_content_type) - 1)) {
559
559
  gqlLink m;
560
560
 
561
561
  if (NULL != (j = gql_json_parse(err, req->body.start, req->body.len))) {
@@ -620,7 +620,7 @@ eval_post(agooErr err, agooReq req) {
620
620
  } else {
621
621
  result = gql_doc_eval_func(err, doc);
622
622
  }
623
- if (GQL_SUBSCRIPTION == doc->op->kind) {
623
+ if (NULL != doc->op && GQL_SUBSCRIPTION == doc->op->kind) {
624
624
  result = NULL;
625
625
  }
626
626
  DONE:
data/ext/agoo/gqljson.c CHANGED
@@ -307,6 +307,7 @@ parse_object(agooErr err, agooDoc doc) {
307
307
  agoo_doc_skip_jwhite(doc);
308
308
  if ('}' != *doc->cur) {
309
309
  for (; doc->cur < doc->end; doc->cur++) {
310
+ agoo_doc_skip_jwhite(doc);
310
311
  if ('"' != *doc->cur) {
311
312
  return return_parse_err(err, doc, "expected an object key as a string", value);
312
313
  }
data/ext/agoo/http.c CHANGED
@@ -26,7 +26,7 @@ typedef struct _cache {
26
26
  struct _cache key_cache;
27
27
 
28
28
  // The rack spec indicates the characters (),/:;<=>?@[]{} are invalid which
29
- // clearly is not consisten with RFC7230 so stick with the RFC.
29
+ // clearly is not consistent with RFC7230 so stick with the RFC.
30
30
  static char header_value_chars[256] = "\
31
31
  xxxxxxxxxxoxxxxxxxxxxxxxxxxxxxxx\
32
32
  oooooooooooooooooooooooooooooooo\
@@ -50,7 +50,6 @@ static const char *header_keys[] = {
50
50
  "Accept-Encoding",
51
51
  "Accept-Features",
52
52
  "Accept-Language",
53
- "Accept-Language",
54
53
  "Accept-Patch",
55
54
  "Accept-Post",
56
55
  "Accept-Ranges",
@@ -74,7 +73,6 @@ static const char *header_keys[] = {
74
73
  "Approved",
75
74
  "Archive",
76
75
  "Archived-At",
77
- "Archived-At",
78
76
  "Article-Names",
79
77
  "Article-Updates",
80
78
  "Authentication-Control",
@@ -99,36 +97,27 @@ static const char *header_keys[] = {
99
97
  "Cc",
100
98
  "Close",
101
99
  "Comments",
102
- "Comments",
103
100
  "Compliance",
104
101
  "Connection",
105
102
  "Content-Alternative",
106
103
  "Content-Base",
107
- "Content-Base",
108
104
  "Content-Description",
109
105
  "Content-Disposition",
110
- "Content-Disposition",
111
106
  "Content-Duration",
112
107
  "Content-Encoding",
113
108
  "Content-ID",
114
- "Content-ID",
115
109
  "Content-Identifier",
116
110
  "Content-Language",
117
- "Content-Language",
118
111
  "Content-Length",
119
112
  "Content-Location",
120
- "Content-Location",
121
- "Content-MD5",
122
113
  "Content-MD5",
123
114
  "Content-Range",
124
115
  "Content-Return",
125
116
  "Content-Script-Type",
126
117
  "Content-Style-Type",
127
118
  "Content-Transfer-Encoding",
128
- "Content-Transfer-Encoding",
129
119
  "Content-Translation-Type",
130
120
  "Content-Type",
131
- "Content-Type",
132
121
  "Content-Version",
133
122
  "Content-features",
134
123
  "Control",
@@ -141,8 +130,7 @@ static const char *header_keys[] = {
141
130
  "DAV",
142
131
  "DKIM-Signature",
143
132
  "DL-Expansion-History",
144
- "Date",
145
- "Date",
133
+ "DNT",
146
134
  "Date",
147
135
  "Date-Received",
148
136
  "Default-Style",
@@ -182,7 +170,6 @@ static const char *header_keys[] = {
182
170
  "Downgraded-Sender",
183
171
  "Downgraded-To",
184
172
  "EDIINT-Features",
185
- "EDIINT-Features",
186
173
  "ETag",
187
174
  "Eesst-Version",
188
175
  "Encoding",
@@ -190,16 +177,13 @@ static const char *header_keys[] = {
190
177
  "Errors-To",
191
178
  "Expect",
192
179
  "Expires",
193
- "Expires",
194
- "Expires",
195
180
  "Expiry-Date",
196
181
  "Ext",
197
182
  "Followup-To",
198
183
  "Form-Sub",
199
184
  "Forwarded",
200
185
  "From",
201
- "From",
202
- "From",
186
+ "Front-End-Https",
203
187
  "Generate-Delivery-Report",
204
188
  "GetProfile",
205
189
  "HTTP2-Settings",
@@ -219,10 +203,8 @@ static const char *header_keys[] = {
219
203
  "Injection-Date",
220
204
  "Injection-Info",
221
205
  "Jabber-ID",
222
- "Jabber-ID",
223
206
  "Keep-Alive",
224
207
  "Keywords",
225
- "Keywords",
226
208
  "Label",
227
209
  "Language",
228
210
  "Last-Modified",
@@ -240,7 +222,6 @@ static const char *header_keys[] = {
240
222
  "Location",
241
223
  "Lock-Token",
242
224
  "MIME-Version",
243
- "MIME-Version",
244
225
  "MMHS-Acp127-Message-Identifier",
245
226
  "MMHS-Authorizing-Users",
246
227
  "MMHS-Codress-Message-Indicator",
@@ -262,8 +243,6 @@ static const char *header_keys[] = {
262
243
  "Memento-Datetime",
263
244
  "Message-Context",
264
245
  "Message-ID",
265
- "Message-ID",
266
- "Message-ID",
267
246
  "Message-Type",
268
247
  "Meter",
269
248
  "Method-Check",
@@ -279,7 +258,6 @@ static const char *header_keys[] = {
279
258
  "Optional-WWW-Authenticate",
280
259
  "Ordering-Type",
281
260
  "Organization",
282
- "Organization",
283
261
  "Origin",
284
262
  "Original-Encoded-Information-Types",
285
263
  "Original-From",
@@ -292,7 +270,6 @@ static const char *header_keys[] = {
292
270
  "P3P",
293
271
  "PEP",
294
272
  "PICS-Label",
295
- "PICS-Label",
296
273
  "Path",
297
274
  "Pep-Info",
298
275
  "Position",
@@ -311,6 +288,7 @@ static const char *header_keys[] = {
311
288
  "Proxy-Authenticate",
312
289
  "Proxy-Authentication-Info",
313
290
  "Proxy-Authorization",
291
+ "Proxy-Connection",
314
292
  "Proxy-Features",
315
293
  "Proxy-Instruction",
316
294
  "Public",
@@ -321,13 +299,11 @@ static const char *header_keys[] = {
321
299
  "Received-SPF",
322
300
  "Redirect-Ref",
323
301
  "References",
324
- "References",
325
302
  "Referer",
326
303
  "Referer-Root",
327
304
  "Relay-Version",
328
305
  "Reply-By",
329
306
  "Reply-To",
330
- "Reply-To",
331
307
  "Require-Recipient-Valid-Since",
332
308
  "Resent-Bcc",
333
309
  "Resent-Cc",
@@ -345,6 +321,7 @@ static const char *header_keys[] = {
345
321
  "SIO-Label-History",
346
322
  "SLUG",
347
323
  "Safe",
324
+ "Save-Data",
348
325
  "Schedule-Reply",
349
326
  "Schedule-Tag",
350
327
  "Sec-WebSocket-Accept",
@@ -367,11 +344,9 @@ static const char *header_keys[] = {
367
344
  "Strict-Transport-Security",
368
345
  "SubOK",
369
346
  "Subject",
370
- "Subject",
371
347
  "Subst",
372
348
  "Summary",
373
349
  "Supersedes",
374
- "Supersedes",
375
350
  "Surrogate-Capability",
376
351
  "Surrogate-Control",
377
352
  "TCN",
@@ -390,9 +365,9 @@ static const char *header_keys[] = {
390
365
  "UA-Windowpixels",
391
366
  "URI",
392
367
  "Upgrade",
368
+ "Upgrade-Insecure-Requests",
393
369
  "Urgency",
394
370
  "User-Agent",
395
- "User-Agent",
396
371
  "VBR-Info",
397
372
  "Variant-Vary",
398
373
  "Vary",
@@ -401,22 +376,32 @@ static const char *header_keys[] = {
401
376
  "WWW-Authenticate",
402
377
  "Want-Digest",
403
378
  "Warning",
404
- "X-Archived-At",
379
+ "X-ATT-DeviceId",
405
380
  "X-Archived-At",
406
381
  "X-Content-Type-Options",
382
+ "X-Correlation-ID",
383
+ "X-Csrf-Token",
407
384
  "X-Device-Accept",
408
385
  "X-Device-Accept-Charset",
409
386
  "X-Device-Accept-Encoding",
410
387
  "X-Device-Accept-Language",
411
388
  "X-Device-User-Agent",
389
+ "X-Forwarded-For",
390
+ "X-Forwarded-Host",
391
+ "X-Forwarded-Proto",
412
392
  "X-Frame-Options",
393
+ "X-Http-Method-Override",
413
394
  "X-Mittente",
414
395
  "X-PGP-Sig",
396
+ "X-Request-ID",
397
+ "X-Requested-With",
415
398
  "X-Ricevuta",
416
399
  "X-Riferimento-Message-ID",
417
400
  "X-TipoRicevuta",
418
401
  "X-Trasporto",
402
+ "X-UIDH",
419
403
  "X-VerificaSicurezza",
404
+ "X-Wap-Profile",
420
405
  "X-XSS-Protection",
421
406
  "X400-Content-Identifier",
422
407
  "X400-Content-Return",
@@ -469,7 +454,7 @@ key_set(const char *key) {
469
454
  int64_t h = calc_hash(key, &len);
470
455
  Slot *bucket = get_bucketp(h);
471
456
  Slot s;
472
-
457
+
473
458
  if (NULL != (s = (Slot)AGOO_MALLOC(sizeof(struct _slot)))) {
474
459
  s->hash = h;
475
460
  s->klen = len;
@@ -482,7 +467,7 @@ key_set(const char *key) {
482
467
  void
483
468
  agoo_http_init() {
484
469
  const char **kp = header_keys;
485
-
470
+
486
471
  memset(&key_cache, 0, sizeof(struct _cache));
487
472
  for (; NULL != *kp; kp++) {
488
473
  key_set(*kp);
@@ -550,7 +535,7 @@ agoo_http_header_ok(agooErr err, const char *key, int klen, const char *value, i
550
535
  const char*
551
536
  agoo_http_code_message(int code) {
552
537
  const char *msg = "";
553
-
538
+
554
539
  switch (code) {
555
540
  case 100: msg = "Continue"; break;
556
541
  case 101: msg = "Switching Protocols"; break;