unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help
 help / color / Atom feed
0659fc7f7d1ad1381400e43481265b6c450f30b0 blob 3383 bytes (raw)

  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
 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
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
 
#ifndef common_field_optimization
#define common_field_optimization
#include "ruby.h"
#include "c_util.h"

struct common_field {
  const signed long len;
  const char *name;
  VALUE value;
};

/*
 * A list of common HTTP headers we expect to receive.
 * This allows us to avoid repeatedly creating identical string
 * objects to be used with rb_hash_aset().
 */
static struct common_field common_http_fields[] = {
# define f(N) { (sizeof(N) - 1), N, Qnil }
  f("ACCEPT"),
  f("ACCEPT_CHARSET"),
  f("ACCEPT_ENCODING"),
  f("ACCEPT_LANGUAGE"),
  f("ALLOW"),
  f("AUTHORIZATION"),
  f("CACHE_CONTROL"),
  f("CONNECTION"),
  f("CONTENT_ENCODING"),
  f("CONTENT_LENGTH"),
  f("CONTENT_TYPE"),
  f("COOKIE"),
  f("DATE"),
  f("EXPECT"),
  f("FROM"),
  f("HOST"),
  f("IF_MATCH"),
  f("IF_MODIFIED_SINCE"),
  f("IF_NONE_MATCH"),
  f("IF_RANGE"),
  f("IF_UNMODIFIED_SINCE"),
  f("KEEP_ALIVE"), /* Firefox sends this */
  f("MAX_FORWARDS"),
  f("PRAGMA"),
  f("PROXY_AUTHORIZATION"),
  f("RANGE"),
  f("REFERER"),
  f("TE"),
  f("TRAILER"),
  f("TRANSFER_ENCODING"),
  f("UPGRADE"),
  f("USER_AGENT"),
  f("VIA"),
  f("X_FORWARDED_FOR"), /* common for proxies */
  f("X_FORWARDED_PROTO"), /* common for proxies */
  f("X_REAL_IP"), /* common for proxies */
  f("WARNING")
# undef f
};

#define HTTP_PREFIX "HTTP_"
#define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
static ID id_uminus;

/* this dedupes under Ruby 2.5+ (December 2017) */
static VALUE str_dd_freeze(VALUE str)
{
  if (STR_UMINUS_DEDUPE)
    return rb_funcall(str, id_uminus, 0);

  /* freeze,since it speeds up older MRI slightly */
  OBJ_FREEZE(str);
  return str;
}

static VALUE str_new_dd_freeze(const char *ptr, long len)
{
  return str_dd_freeze(rb_str_new(ptr, len));
}

/* this function is not performance-critical, called only at load time */
static void init_common_fields(void)
{
  int i;
  struct common_field *cf = common_http_fields;
  char tmp[64];

  id_uminus = rb_intern("-@");
  memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);

  for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
    /* Rack doesn't like certain headers prefixed with "HTTP_" */
    if (!strcmp("CONTENT_LENGTH", cf->name) ||
        !strcmp("CONTENT_TYPE", cf->name)) {
      cf->value = str_new_dd_freeze(cf->name, cf->len);
    } else {
      memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
      cf->value = str_new_dd_freeze(tmp, HTTP_PREFIX_LEN + cf->len);
    }
    rb_gc_register_mark_object(cf->value);
  }
}

/* this function is called for every header set */
static VALUE find_common_field(const char *field, size_t flen)
{
  int i;
  struct common_field *cf = common_http_fields;

  for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
    if (cf->len == (long)flen && !memcmp(cf->name, field, flen))
      return cf->value;
  }
  return Qnil;
}

/*
 * We got a strange header that we don't have a memoized value for.
 * Fallback to creating a new string to use as a hash key.
 */
static VALUE uncommon_field(const char *field, size_t flen)
{
  VALUE f = rb_str_new(NULL, HTTP_PREFIX_LEN + flen);
  memcpy(RSTRING_PTR(f), HTTP_PREFIX, HTTP_PREFIX_LEN);
  memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
  assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0' &&
         "string didn't end with \\0"); /* paranoia */
  return HASH_ASET_DEDUPE ? f : str_dd_freeze(f);
}

#endif /* common_field_optimization_h */
debug log:

solving 0659fc7 ...
found 0659fc7 in https://bogomips.org/unicorn.git

unicorn Ruby/Rack server user+dev discussion/patches/pulls/bugs/help

Archives are clonable:
	git clone --mirror https://bogomips.org/unicorn-public
	git clone --mirror http://ou63pmih66umazou.onion/unicorn-public

Example config snippet for mirrors

Newsgroups are available over NNTP:
	nntp://news.public-inbox.org/inbox.comp.lang.ruby.unicorn
	nntp://ou63pmih66umazou.onion/inbox.comp.lang.ruby.unicorn

 note: .onion URLs require Tor: https://www.torproject.org/

AGPL code for this site: git clone https://public-inbox.org/public-inbox.git