public
Description: New and ultra-turbo-crazy-fast backend for Thin
Homepage: http://code.macournoyer.com/thin/
Clone URL: git://github.com/macournoyer/thin-turbo.git
Handle multiple response headers with the same name
macournoyer (author)
Wed Apr 30 13:26:37 -0700 2008
commit  27e1ec0dc404092affefa8f67f43e1325e28931d
tree    96bae9d0881bca4237d8fced47526b7c4e566f70
parent  445efc50a4cbe9b54fc044d5a35f80e1145e1f94
0
...
1
2
3
4
...
1
 
2
3
0
@@ -1,3 +1,2 @@
0
 * Set timeout from Ruby
0
-* Allow duplicate values for some headers, eg.: cookies
0
 * BUG: hangs on file upload 1 time out of 2
0
\ No newline at end of file
...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
...
65
66
67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
69
70
...
1
2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
4
5
...
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
0
@@ -1,40 +1,5 @@
0
 #include "thin.h"
0
 
0
-static void response_send_status(connection_t *c, const int status)
0
-{
0
- buffer_t *buf = &c->write_buffer;
0
- char *status_line = get_status_line(status);
0
- #define RESP_HTTP_VERSION "HTTP/1.1 "
0
-
0
- buffer_append(buf, RESP_HTTP_VERSION, sizeof(RESP_HTTP_VERSION) - 1);
0
- buffer_append(buf, status_line, strlen(status_line));
0
- buffer_append(buf, CRLF, sizeof(CRLF) - 1);
0
-}
0
-
0
-static void response_send_headers(connection_t *c, VALUE headers)
0
-{
0
- buffer_t *buf = &c->write_buffer;
0
- VALUE hash, keys, key, value;
0
- size_t i, n = 0;
0
- #define HEADER_SEP ": "
0
-
0
- keys = rb_funcall(headers, sInternedKeys, 0);
0
-
0
- /* FIXME very big response header will cause buffer to be stored in tmpfile */
0
-
0
- for (i = 0; i < RARRAY_LEN(keys); ++i) {
0
- key = RARRAY_PTR(keys)[i];
0
- value = rb_hash_aref(headers, key);
0
-
0
- buffer_append(buf, RSTRING_PTR(key), RSTRING_LEN(key));
0
- buffer_append(buf, HEADER_SEP, sizeof(HEADER_SEP) - 1);
0
- buffer_append(buf, RSTRING_PTR(value), RSTRING_LEN(value));
0
- buffer_append(buf, CRLF, sizeof(CRLF) - 1);
0
- }
0
-
0
- buffer_append(buf, CRLF, sizeof(CRLF) - 1);
0
-}
0
-
0
 static void response_send_chunk(connection_t *c, const char *ptr, size_t len)
0
 {
0
   /* chunk too big, split it in smaller chunks and send each separately */
0
@@ -65,6 +30,54 @@ static void response_send_chunk(connection_t *c, const char *ptr, size_t len)
0
   }
0
 }
0
 
0
+static void response_send_status(connection_t *c, const int status)
0
+{
0
+ buffer_t *buf = &c->write_buffer;
0
+ char *status_line = get_status_line(status);
0
+
0
+ buffer_append(buf, RESP_HTTP_VERSION, sizeof(RESP_HTTP_VERSION) - 1);
0
+ buffer_append(buf, status_line, strlen(status_line));
0
+ buffer_append(buf, CRLF, sizeof(CRLF) - 1);
0
+}
0
+
0
+static VALUE iter_header(VALUE value, VALUE *args)
0
+{
0
+ connection_t *c = (connection_t *) args[0];
0
+ VALUE key = (VALUE) args[1];
0
+
0
+ response_send_chunk(c, RSTRING_PTR(key), RSTRING_LEN(key));
0
+ response_send_chunk(c, HEADER_SEP, sizeof(HEADER_SEP) - 1);
0
+
0
+ /* if value ends w/ line break w/ chomp it! */
0
+ size_t len = RSTRING_LEN(value);
0
+ if (RSTRING_PTR(value)[RSTRING_LEN(value) - 1] == '\n')
0
+ len--;
0
+
0
+ response_send_chunk(c, RSTRING_PTR(value), len);
0
+ response_send_chunk(c, CRLF, sizeof(CRLF) - 1);
0
+
0
+ return Qnil;
0
+}
0
+
0
+static void response_send_headers(connection_t *c, VALUE headers)
0
+{
0
+ VALUE hash, keys, key, value;
0
+ size_t i;
0
+
0
+ keys = rb_funcall(headers, sInternedKeys, 0);
0
+
0
+ for (i = 0; i < RARRAY_LEN(keys); ++i) {
0
+ key = RARRAY_PTR(keys)[i];
0
+ value = rb_hash_aref(headers, key);
0
+
0
+ VALUE args[2] = { (VALUE) c, key };
0
+
0
+ rb_iterate(rb_each, value, iter_header, (VALUE) args);
0
+ }
0
+
0
+ response_send_chunk(c, CRLF, sizeof(CRLF) - 1);
0
+}
0
+
0
 static VALUE iter_body(VALUE chunk, VALUE *val_conn)
0
 {
0
   connection_t *c = (connection_t *) val_conn;
...
47
48
49
50
51
52
 
 
 
53
54
55
...
47
48
49
 
 
 
50
51
52
53
54
55
0
@@ -47,9 +47,9 @@
0
 #define RACK_VERSION INT2FIX(3), INT2FIX(0)
0
 
0
 
0
-#define LF (u_char) 10
0
-#define CR (u_char) 13
0
-#define CRLF "\x0d\x0a"
0
+#define HEADER_SEP ": "
0
+#define RESP_HTTP_VERSION "HTTP/1.1 "
0
+#define CRLF "\x0d\x0a"
0
 
0
 typedef struct backend_s backend_t;
0
 typedef struct connection_s connection_t;
...
66
67
68
 
69
70
71
...
77
78
79
 
80
81
82
...
93
94
95
96
 
 
 
 
 
 
97
98
99
...
66
67
68
69
70
71
72
...
78
79
80
81
82
83
84
...
95
96
97
 
98
99
100
101
102
103
104
105
106
0
@@ -66,6 +66,7 @@ module ThinTurboServer
0
   end
0
   
0
   def request(data)
0
+ puts data if Thin::Logging.trace?
0
     socket = TCPSocket.new(ADDRESS, PORT)
0
     Array(data).each do |chunk|
0
       socket.write(chunk)
0
@@ -77,6 +78,7 @@ module ThinTurboServer
0
     end
0
   ensure
0
     socket.close
0
+ puts out if Thin::Logging.trace?
0
     out
0
   end
0
 end
0
@@ -93,7 +95,12 @@ class HttpResponse
0
     
0
     @headers = {}
0
     data.scan(/^([^\(|\)\<\>@,;:\\\"\/\[\]\?=\{\}\s\t]+): (.*)\r$/).each do |name, value|
0
- @headers[name] = value
0
+ if @headers.has_key?(name)
0
+ @headers[name] = [@headers[name]].flatten
0
+ @headers[name] << value
0
+ else
0
+ @headers[name] = value
0
+ end
0
     end
0
     
0
     @body = data.split("\r\n\r\n")[1..-1].join("\r\n\r\n") if data.include?("\r\n\r\n")

Comments

    No one has commented yet.