clogger 0.0.1 → 0.0.2
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.
- data/GNUmakefile +41 -2
- data/History.txt +7 -0
- data/ext/clogger_ext/clogger.c +58 -15
- data/lib/clogger.rb +2 -1
- data/lib/clogger/pure.rb +16 -2
- data/test/test_clogger.rb +27 -0
- metadata +2 -2
data/GNUmakefile
CHANGED
@@ -32,6 +32,45 @@ test: test-ext test-pure
|
|
32
32
|
Manifest.txt:
|
33
33
|
git ls-files > $@+
|
34
34
|
cmp $@+ $@ || mv $@+ $@
|
35
|
-
$(RM)
|
35
|
+
$(RM) $@+
|
36
36
|
|
37
|
-
|
37
|
+
VERSION := $(shell git describe 2>/dev/null | sed 's/^v//')
|
38
|
+
|
39
|
+
ifneq ($(VERSION),)
|
40
|
+
v := /^v$(VERSION)$$/
|
41
|
+
vPREV := $(shell git tag -l 2>/dev/null | sed -n -e '$(v)!h' -e '$(v){x;p;q}')
|
42
|
+
release_notes := release_notes-$(VERSION).txt
|
43
|
+
release_changes := release_changes-$(VERSION).txt
|
44
|
+
$(release_changes): verify
|
45
|
+
git diff --stat $(vPREV) v$(VERSION) > $@+
|
46
|
+
echo >> $@+
|
47
|
+
git log $(vPREV) v$(VERSION) >> $@+
|
48
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
49
|
+
$(release_notes): verify package
|
50
|
+
gem spec pkg/clogger-$(VERSION).gem description | sed -ne '/\w/p' > $@+
|
51
|
+
git cat-file tag v$(VERSION) | awk 'p>1{print $$0}/^$$/{++p}' >> $@+
|
52
|
+
$(VISUAL) $@+ && test -s $@+ && mv $@+ $@
|
53
|
+
verify:
|
54
|
+
@test -n "$(VERSION)" || { echo >&2 VERSION= not defined; exit 1; }
|
55
|
+
git rev-parse --verify refs/tags/v$(VERSION)^{}
|
56
|
+
@test -n "$(VISUAL)" || { echo >&2 VISUAL= not defined; exit 1; }
|
57
|
+
|
58
|
+
package: verify
|
59
|
+
git diff-index --quiet HEAD^0
|
60
|
+
test `git rev-parse --verify HEAD^0` = \
|
61
|
+
`git rev-parse --verify refs/tags/v$(VERSION)^{}`
|
62
|
+
$(RM) -r pkg
|
63
|
+
unset CLOGGER_EXT; rake package VERSION=$(VERSION)
|
64
|
+
CLOGGER_EXT=1 rake package VERSION=$(VERSION)
|
65
|
+
|
66
|
+
# not using Hoe's release system since we release 2 gems but only one tgz
|
67
|
+
release: package Manifest.txt $(release_notes) $(release_changes)
|
68
|
+
rubyforge add_release -f -n $(release_notes) -c $(release_changes) \
|
69
|
+
clogger clogger $(VERSION) pkg/clogger-$(VERSION).gem
|
70
|
+
rubyforge add_file \
|
71
|
+
clogger clogger $(VERSION) pkg/clogger-$(VERSION).tgz
|
72
|
+
rubyforge add_release -f -n $(release_notes) -c $(release_changes) \
|
73
|
+
clogger clogger_ext $(VERSION) pkg/clogger_ext-$(VERSION).gem
|
74
|
+
endif
|
75
|
+
|
76
|
+
.PHONY: test doc Manifest.txt release
|
data/History.txt
CHANGED
data/ext/clogger_ext/clogger.c
CHANGED
@@ -54,7 +54,8 @@ enum clogger_special {
|
|
54
54
|
CL_SP_request_length,
|
55
55
|
CL_SP_response_length,
|
56
56
|
CL_SP_ip,
|
57
|
-
CL_SP_pid
|
57
|
+
CL_SP_pid,
|
58
|
+
CL_SP_request_uri,
|
58
59
|
};
|
59
60
|
|
60
61
|
struct clogger {
|
@@ -92,6 +93,7 @@ static VALUE g_HTTP_X_FORWARDED_FOR;
|
|
92
93
|
static VALUE g_REMOTE_ADDR;
|
93
94
|
static VALUE g_REQUEST_METHOD;
|
94
95
|
static VALUE g_PATH_INFO;
|
96
|
+
static VALUE g_REQUEST_URI;
|
95
97
|
static VALUE g_QUERY_STRING;
|
96
98
|
static VALUE g_HTTP_VERSION;
|
97
99
|
static VALUE g_rack_errors;
|
@@ -102,6 +104,7 @@ static VALUE g_empty;
|
|
102
104
|
static VALUE g_space;
|
103
105
|
static VALUE g_question_mark;
|
104
106
|
static VALUE g_rack_request_cookie_hash;
|
107
|
+
static VALUE g_bad_app_response;
|
105
108
|
|
106
109
|
#define LOG_BUF_INIT_SIZE 128
|
107
110
|
|
@@ -410,30 +413,44 @@ static void append_time_fmt(struct clogger *c, const VALUE *op)
|
|
410
413
|
append_tv(c, op, &now);
|
411
414
|
}
|
412
415
|
|
416
|
+
static void append_request_uri(struct clogger *c)
|
417
|
+
{
|
418
|
+
VALUE tmp;
|
419
|
+
|
420
|
+
tmp = rb_hash_aref(c->env, g_REQUEST_URI);
|
421
|
+
if (NIL_P(tmp)) {
|
422
|
+
tmp = rb_hash_aref(c->env, g_PATH_INFO);
|
423
|
+
if (!NIL_P(tmp))
|
424
|
+
rb_str_buf_append(c->log_buf, byte_xs(tmp));
|
425
|
+
tmp = rb_hash_aref(c->env, g_QUERY_STRING);
|
426
|
+
if (!NIL_P(tmp) && RSTRING_LEN(tmp) != 0) {
|
427
|
+
rb_str_buf_append(c->log_buf, g_question_mark);
|
428
|
+
rb_str_buf_append(c->log_buf, byte_xs(tmp));
|
429
|
+
}
|
430
|
+
} else {
|
431
|
+
rb_str_buf_append(c->log_buf, byte_xs(tmp));
|
432
|
+
}
|
433
|
+
}
|
434
|
+
|
413
435
|
static void append_request(struct clogger *c)
|
414
436
|
{
|
415
437
|
VALUE tmp;
|
416
|
-
VALUE env = c->env;
|
417
438
|
|
418
439
|
/* REQUEST_METHOD doesn't need escaping, Rack::Lint governs it */
|
419
|
-
tmp = rb_hash_aref(env, g_REQUEST_METHOD);
|
420
|
-
|
440
|
+
tmp = rb_hash_aref(c->env, g_REQUEST_METHOD);
|
441
|
+
if (!NIL_P(tmp))
|
442
|
+
rb_str_buf_append(c->log_buf, tmp);
|
443
|
+
|
421
444
|
rb_str_buf_append(c->log_buf, g_space);
|
422
445
|
|
423
|
-
|
424
|
-
tmp = rb_hash_aref(env, g_PATH_INFO);
|
425
|
-
rb_str_buf_append(c->log_buf, NIL_P(tmp) ? g_empty : byte_xs(tmp));
|
446
|
+
append_request_uri(c);
|
426
447
|
|
427
|
-
tmp = rb_hash_aref(env, g_QUERY_STRING);
|
428
|
-
if (RSTRING_LEN(tmp) != 0) {
|
429
|
-
rb_str_buf_append(c->log_buf, g_question_mark);
|
430
|
-
rb_str_buf_append(c->log_buf, byte_xs(tmp));
|
431
|
-
}
|
432
448
|
rb_str_buf_append(c->log_buf, g_space);
|
433
449
|
|
434
450
|
/* HTTP_VERSION can be injected by malicious clients */
|
435
|
-
tmp = rb_hash_aref(env, g_HTTP_VERSION);
|
436
|
-
|
451
|
+
tmp = rb_hash_aref(c->env, g_HTTP_VERSION);
|
452
|
+
if (!NIL_P(tmp))
|
453
|
+
rb_str_buf_append(c->log_buf, byte_xs(tmp));
|
437
454
|
}
|
438
455
|
|
439
456
|
static void append_request_length(struct clogger *c)
|
@@ -538,6 +555,9 @@ static void special_var(struct clogger *c, enum clogger_special var)
|
|
538
555
|
break;
|
539
556
|
case CL_SP_pid:
|
540
557
|
append_pid(c);
|
558
|
+
break;
|
559
|
+
case CL_SP_request_uri:
|
560
|
+
append_request_uri(c);
|
541
561
|
}
|
542
562
|
}
|
543
563
|
|
@@ -703,10 +723,21 @@ static VALUE clogger_fileno(VALUE self)
|
|
703
723
|
|
704
724
|
static void ccall(struct clogger *c, VALUE env)
|
705
725
|
{
|
726
|
+
VALUE rv;
|
727
|
+
|
706
728
|
gettimeofday(&c->tv_start, NULL);
|
707
729
|
c->env = env;
|
708
730
|
c->cookies = Qfalse;
|
709
|
-
|
731
|
+
rv = rb_funcall(c->app, call_id, 1, env);
|
732
|
+
if (TYPE(rv) == T_ARRAY && RARRAY_LEN(rv) == 3) {
|
733
|
+
c->response = rv;
|
734
|
+
} else {
|
735
|
+
c->response = g_bad_app_response;
|
736
|
+
cwrite(c);
|
737
|
+
rb_raise(rb_eTypeError,
|
738
|
+
"app response not a 3 element Array: %s",
|
739
|
+
RSTRING_PTR(rb_inspect(rv)));
|
740
|
+
}
|
710
741
|
}
|
711
742
|
|
712
743
|
/*
|
@@ -763,6 +794,16 @@ static VALUE clogger_init_copy(VALUE clone, VALUE orig)
|
|
763
794
|
|
764
795
|
#define CONST_GLOBAL_STR(val) CONST_GLOBAL_STR2(val, #val)
|
765
796
|
|
797
|
+
static void init_bad_response(void)
|
798
|
+
{
|
799
|
+
g_bad_app_response = rb_ary_new();
|
800
|
+
rb_ary_store(g_bad_app_response, 0, INT2NUM(500));
|
801
|
+
rb_ary_store(g_bad_app_response, 1, rb_obj_freeze(rb_hash_new()));
|
802
|
+
rb_ary_store(g_bad_app_response, 2, rb_obj_freeze(rb_ary_new()));
|
803
|
+
rb_obj_freeze(g_bad_app_response);
|
804
|
+
rb_global_variable(&g_bad_app_response);
|
805
|
+
}
|
806
|
+
|
766
807
|
void Init_clogger_ext(void)
|
767
808
|
{
|
768
809
|
ltlt_id = rb_intern("<<");
|
@@ -788,6 +829,7 @@ void Init_clogger_ext(void)
|
|
788
829
|
CONST_GLOBAL_STR(REQUEST_METHOD);
|
789
830
|
CONST_GLOBAL_STR(PATH_INFO);
|
790
831
|
CONST_GLOBAL_STR(QUERY_STRING);
|
832
|
+
CONST_GLOBAL_STR(REQUEST_URI);
|
791
833
|
CONST_GLOBAL_STR(HTTP_VERSION);
|
792
834
|
CONST_GLOBAL_STR2(rack_errors, "rack.errors");
|
793
835
|
CONST_GLOBAL_STR2(rack_input, "rack.input");
|
@@ -797,4 +839,5 @@ void Init_clogger_ext(void)
|
|
797
839
|
CONST_GLOBAL_STR2(space, " ");
|
798
840
|
CONST_GLOBAL_STR2(question_mark, "?");
|
799
841
|
CONST_GLOBAL_STR2(rack_request_cookie_hash, "rack.request.cookie_hash");
|
842
|
+
init_bad_response();
|
800
843
|
}
|
data/lib/clogger.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
class Clogger
|
3
|
-
VERSION = '0.0.
|
3
|
+
VERSION = '0.0.2'
|
4
4
|
|
5
5
|
OP_LITERAL = 0
|
6
6
|
OP_REQUEST = 1
|
@@ -29,6 +29,7 @@ class Clogger
|
|
29
29
|
:response_length => 4, # like body_bytes_sent, except "-" instead of "0"
|
30
30
|
:ip => 5, # HTTP_X_FORWARDED_FOR || REMOTE_ADDR || -
|
31
31
|
:pid => 6, # getpid()
|
32
|
+
:request_uri => 7
|
32
33
|
}
|
33
34
|
|
34
35
|
private
|
data/lib/clogger/pure.rb
CHANGED
@@ -16,7 +16,12 @@ class Clogger
|
|
16
16
|
|
17
17
|
def call(env)
|
18
18
|
@start = Time.now
|
19
|
-
|
19
|
+
resp = @app.call(env)
|
20
|
+
unless resp.instance_of?(Array) && resp.size == 3
|
21
|
+
log(env, 500, {})
|
22
|
+
raise TypeError, "app response not a 3 element Array: #{resp.inspect}"
|
23
|
+
end
|
24
|
+
status, headers, body = resp
|
20
25
|
if wrap_body?
|
21
26
|
@reentrant = env['rack.multithread']
|
22
27
|
@env, @status, @headers, @body = env, status, headers, body
|
@@ -63,6 +68,13 @@ private
|
|
63
68
|
|
64
69
|
SPECIAL_RMAP = SPECIAL_VARS.inject([]) { |ary, (k,v)| ary[v] = k; ary }
|
65
70
|
|
71
|
+
def request_uri(env)
|
72
|
+
ru = env['REQUEST_URI'] and return byte_xs(ru)
|
73
|
+
qs = env['QUERY_STRING']
|
74
|
+
qs.empty? or qs = "?#{byte_xs(qs)}"
|
75
|
+
"#{byte_xs(env['PATH_INFO'])}#{qs}"
|
76
|
+
end
|
77
|
+
|
66
78
|
def special_var(special_nr, env, status, headers)
|
67
79
|
case SPECIAL_RMAP[special_nr]
|
68
80
|
when :body_bytes_sent
|
@@ -74,8 +86,10 @@ private
|
|
74
86
|
qs = env['QUERY_STRING']
|
75
87
|
qs.empty? or qs = "?#{byte_xs(qs)}"
|
76
88
|
"#{env['REQUEST_METHOD']} " \
|
77
|
-
"#{
|
89
|
+
"#{request_uri(env)} " \
|
78
90
|
"#{byte_xs(env['HTTP_VERSION'])}"
|
91
|
+
when :request_uri
|
92
|
+
request_uri(env)
|
79
93
|
when :request_length
|
80
94
|
env['rack.input'].size.to_s
|
81
95
|
when :response_length
|
data/test/test_clogger.rb
CHANGED
@@ -333,6 +333,22 @@ class TestClogger < Test::Unit::TestCase
|
|
333
333
|
assert_equal expect, str.string
|
334
334
|
end
|
335
335
|
|
336
|
+
def test_request_uri_fallback
|
337
|
+
str = StringIO.new
|
338
|
+
app = lambda { |env| [ 200, {}, [] ] }
|
339
|
+
cl = Clogger.new(app, :logger => str, :format => '$request_uri')
|
340
|
+
status, headers, body = cl.call(@req)
|
341
|
+
assert_equal "/hello?goodbye=true\n", str.string
|
342
|
+
end
|
343
|
+
|
344
|
+
def test_request_uri_set
|
345
|
+
str = StringIO.new
|
346
|
+
app = lambda { |env| [ 200, {}, [] ] }
|
347
|
+
cl = Clogger.new(app, :logger => str, :format => '$request_uri')
|
348
|
+
status, headers, body = cl.call(@req.merge("REQUEST_URI" => '/zzz'))
|
349
|
+
assert_equal "/zzz\n", str.string
|
350
|
+
end
|
351
|
+
|
336
352
|
def test_cookies
|
337
353
|
str = StringIO.new
|
338
354
|
app = lambda { |env|
|
@@ -346,4 +362,15 @@ class TestClogger < Test::Unit::TestCase
|
|
346
362
|
status, headers, body = cl.call(req)
|
347
363
|
assert_equal "bar h&m\n", str.string
|
348
364
|
end
|
365
|
+
|
366
|
+
def test_bogus_app_response
|
367
|
+
str = StringIO.new
|
368
|
+
app = lambda { |env| 302 }
|
369
|
+
cl = Clogger.new(app, :logger => str)
|
370
|
+
assert_raise(TypeError) { cl.call(@req) }
|
371
|
+
str = str.string
|
372
|
+
e = Regexp.quote " \"GET /hello?goodbye=true HTTP/1.0\" 500 -"
|
373
|
+
assert_match %r{#{e}$}m, str
|
374
|
+
end
|
375
|
+
|
349
376
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: clogger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Wong
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-08-
|
12
|
+
date: 2009-08-29 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|