clogger 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|