1 #ifndef common_field_optimization
2 #define common_field_optimization
13 * A list of common HTTP headers we expect to receive.
14 * This allows us to avoid repeatedly creating identical string
15 * objects to be used with rb_hash_aset().
17 static struct common_field common_http_fields
[] = {
18 # define f(N) { (sizeof(N) - 1), N, Qnil }
27 f("CONTENT_ENCODING"),
36 f("IF_MODIFIED_SINCE"),
39 f("IF_UNMODIFIED_SINCE"),
40 f("KEEP_ALIVE"), /* Firefox sends this */
43 f("PROXY_AUTHORIZATION"),
48 f("TRANSFER_ENCODING"),
52 f("X_FORWARDED_FOR"), /* common for proxies */
53 f("X_FORWARDED_PROTO"), /* common for proxies */
54 f("X_REAL_IP"), /* common for proxies */
59 #define HTTP_PREFIX "HTTP_"
60 #define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
62 /* this function is not performance-critical, called only at load time */
63 static void init_common_fields(void)
66 struct common_field
*cf
= common_http_fields
;
68 memcpy(tmp
, HTTP_PREFIX
, HTTP_PREFIX_LEN
);
70 for(i
= ARRAY_SIZE(common_http_fields
); --i
>= 0; cf
++) {
71 /* Rack doesn't like certain headers prefixed with "HTTP_" */
72 if (!strcmp("CONTENT_LENGTH", cf
->name
) ||
73 !strcmp("CONTENT_TYPE", cf
->name
)) {
74 cf
->value
= rb_str_new(cf
->name
, cf
->len
);
76 memcpy(tmp
+ HTTP_PREFIX_LEN
, cf
->name
, cf
->len
+ 1);
77 cf
->value
= rb_str_new(tmp
, HTTP_PREFIX_LEN
+ cf
->len
);
79 cf
->value
= rb_obj_freeze(cf
->value
);
80 rb_global_variable(&cf
->value
);
84 /* this function is called for every header set */
85 static VALUE
find_common_field(const char *field
, size_t flen
)
88 struct common_field
*cf
= common_http_fields
;
90 for(i
= ARRAY_SIZE(common_http_fields
); --i
>= 0; cf
++) {
91 if (cf
->len
== (long)flen
&& !memcmp(cf
->name
, field
, flen
))
98 * We got a strange header that we don't have a memoized value for.
99 * Fallback to creating a new string to use as a hash key.
101 static VALUE
uncommon_field(const char *field
, size_t flen
)
103 VALUE f
= rb_str_new(NULL
, HTTP_PREFIX_LEN
+ flen
);
104 memcpy(RSTRING_PTR(f
), HTTP_PREFIX
, HTTP_PREFIX_LEN
);
105 memcpy(RSTRING_PTR(f
) + HTTP_PREFIX_LEN
, field
, flen
);
106 assert(*(RSTRING_PTR(f
) + RSTRING_LEN(f
)) == '\0' &&
107 "string didn't end with \\0"); /* paranoia */
108 return rb_obj_freeze(f
);
111 #endif /* common_field_optimization_h */