racknga 0.9.2 → 0.9.4
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.
- checksums.yaml +7 -0
- data/Gemfile +3 -12
- data/README.textile +9 -8
- data/Rakefile +19 -272
- data/doc/text/news.textile +20 -0
- data/lib/racknga/access_log_parser.rb +147 -0
- data/lib/racknga/api-keys.rb +40 -0
- data/lib/racknga/cache_database.rb +15 -5
- data/lib/racknga/exception_mail_notifier.rb +6 -6
- data/lib/racknga/log_database.rb +2 -1
- data/lib/racknga/log_entry.rb +85 -0
- data/lib/racknga/middleware/auth/api-key.rb +95 -0
- data/lib/racknga/middleware/cache.rb +22 -8
- data/lib/racknga/middleware/deflater.rb +13 -3
- data/lib/racknga/middleware/exception_notifier.rb +1 -2
- data/lib/racknga/middleware/instance_name.rb +92 -9
- data/lib/racknga/middleware/jsonp.rb +25 -5
- data/lib/racknga/middleware/log.rb +8 -3
- data/lib/racknga/middleware/nginx_raw_uri.rb +65 -0
- data/lib/racknga/middleware/range.rb +1 -1
- data/lib/racknga/reverse_line_reader.rb +1 -1
- data/lib/racknga/utils.rb +1 -1
- data/lib/racknga/version.rb +2 -2
- data/lib/racknga.rb +4 -2
- data/munin/plugins/passenger_application_ +61 -47
- data/munin/plugins/passenger_status +64 -33
- data/test/racknga-test-utils.rb +2 -1
- data/test/run-test.rb +1 -3
- data/test/{test-nginx-log-parser.rb → test-access-log-parser.rb} +115 -26
- data/test/test-api-keys.rb +80 -0
- data/test/test-middleware-auth-api-key.rb +144 -0
- data/test/test-middleware-cache.rb +1 -1
- data/test/test-middleware-instance-name.rb +50 -16
- data/test/test-middleware-jsonp.rb +14 -2
- data/test/test-middleware-nginx-raw-uri.rb +70 -0
- data/test/test-middleware-range.rb +1 -1
- metadata +159 -155
- data/lib/racknga/nginx_access_log_parser.rb +0 -139
- data/lib/racknga/will_paginate.rb +0 -48
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
require 'time'
|
20
20
|
require 'net/smtp'
|
@@ -132,10 +132,10 @@ EOE
|
|
132
132
|
end
|
133
133
|
|
134
134
|
def send_summaries
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
135
|
+
subject = "summaries of #{@summaries.size} notifications"
|
136
|
+
mail = create_mail(:subject => subject,
|
137
|
+
:body => report_body)
|
138
|
+
send(mail)
|
139
139
|
end
|
140
140
|
|
141
141
|
def report_body
|
@@ -149,7 +149,7 @@ Timestamp: #{Time.now.rfc2822}
|
|
149
149
|
--
|
150
150
|
URL: #{request.url}
|
151
151
|
--
|
152
|
-
#{exception.class}: #{exception}
|
152
|
+
#{exception.class}: #{exception.message}
|
153
153
|
EOB
|
154
154
|
end
|
155
155
|
|
data/lib/racknga/log_database.rb
CHANGED
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
require 'fileutils'
|
20
20
|
|
@@ -95,6 +95,7 @@ module Racknga
|
|
95
95
|
table.reference("path", "Paths")
|
96
96
|
table.reference("user_agent", "UserAgents")
|
97
97
|
table.float("runtime")
|
98
|
+
table.float("request_time")
|
98
99
|
table.short_text("message", :compress => :zlib)
|
99
100
|
end
|
100
101
|
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2011 Ryo Onodera <onodera@clear-code.com>
|
4
|
+
# Copyright (C) 2011 Kouhei Sutou <kou@clear-code.com>
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License as published by the Free Software Foundation; either
|
9
|
+
# version 2.1 of the License, or (at your option) any later version.
|
10
|
+
#
|
11
|
+
# This library is distributed in the hope that it will be useful,
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14
|
+
# Lesser General Public License for more details.
|
15
|
+
#
|
16
|
+
# You should have received a copy of the GNU Lesser General Public
|
17
|
+
# License along with this library; if not, write to the Free Software
|
18
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
19
|
+
|
20
|
+
module Racknga
|
21
|
+
class LogEntry
|
22
|
+
ATTRIBUTES = [
|
23
|
+
:remote_address,
|
24
|
+
:remote_user,
|
25
|
+
:time_local,
|
26
|
+
:runtime,
|
27
|
+
:request_time,
|
28
|
+
:request,
|
29
|
+
:status,
|
30
|
+
:body_bytes_sent,
|
31
|
+
:http_referer,
|
32
|
+
:http_user_agent,
|
33
|
+
]
|
34
|
+
|
35
|
+
attr_reader(*ATTRIBUTES)
|
36
|
+
def initialize(options=nil)
|
37
|
+
options ||= {}
|
38
|
+
@remote_address = options[:remote_address]
|
39
|
+
@remote_user = normalize_string_value(options[:remote_user])
|
40
|
+
@time_local = options[:time_local] || Time.at(0)
|
41
|
+
@runtime = normalize_float_value(options[:runtime])
|
42
|
+
@request_time = normalize_float_value(options[:request_time])
|
43
|
+
@request = options[:request]
|
44
|
+
@status = options[:status]
|
45
|
+
@body_bytes_sent = normalize_int_value(options[:body_bytes_sent])
|
46
|
+
@http_referer = normalize_string_value(options[:http_referer])
|
47
|
+
@http_user_agent = normalize_string_value(options[:http_user_agent])
|
48
|
+
end
|
49
|
+
|
50
|
+
def attributes
|
51
|
+
ATTRIBUTES.collect do |attribute|
|
52
|
+
__send__(attribute)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def ==(other)
|
57
|
+
other.is_a?(self.class) and attributes == other.attributes
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def normalize_string_value(value)
|
62
|
+
if value.nil? or value == "-"
|
63
|
+
nil
|
64
|
+
else
|
65
|
+
value.to_s
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def normalize_float_value(value)
|
70
|
+
if value.nil?
|
71
|
+
value
|
72
|
+
else
|
73
|
+
value.to_f
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def normalize_int_value(value)
|
78
|
+
if value.nil? or value == "-"
|
79
|
+
nil
|
80
|
+
else
|
81
|
+
value.to_i
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
# Copyright (C) 2012 Haruka Yoshihara <yoshihara@clear-code.com>
|
4
|
+
#
|
5
|
+
# This library is free software; you can redistribute it and/or
|
6
|
+
# modify it under the terms of the GNU Lesser General Public
|
7
|
+
# License as published by the Free Software Foundation; either
|
8
|
+
# version 2.1 of the License, or (at your option) any later version.
|
9
|
+
#
|
10
|
+
# This library is distributed in the hope that it will be useful,
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
# Lesser General Public License for more details.
|
14
|
+
#
|
15
|
+
# You should have received a copy of the GNU Lesser General Public
|
16
|
+
# License along with this library; if not, write to the Free Software
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
|
19
|
+
module Racknga
|
20
|
+
module Middleware
|
21
|
+
module Auth
|
22
|
+
# This is a middleware that provides an authentication of API key.
|
23
|
+
# This middleware checks whether a URL requests API and
|
24
|
+
# whether API key in its request is authorized.
|
25
|
+
# When a URL requests API with unauthorized API key,
|
26
|
+
# this middleware returns json response with :error_message.
|
27
|
+
# Racknga::APIKeys is used as authorized API keys.
|
28
|
+
# Usage:
|
29
|
+
# require 'racknga'
|
30
|
+
#
|
31
|
+
# authorized_api_keys =
|
32
|
+
# Racknga::APIKeys.new("api-query-parameter", ["key1", "key2"])
|
33
|
+
# error_response =
|
34
|
+
# api_key_options = {
|
35
|
+
# :api_url_prefixes => ["/api"],
|
36
|
+
# :authorized_api_keys => authorized_api_keys,
|
37
|
+
# :error_response => {"error" => "this api key is not authorized"}
|
38
|
+
# }
|
39
|
+
# use Racknga::Middleware::Auth::APIKey, api_key_options
|
40
|
+
# run YourApplication
|
41
|
+
class APIKey
|
42
|
+
def initialize(application, options={})
|
43
|
+
@application = application
|
44
|
+
@authorized_api_keys = options[:authorized_api_keys]
|
45
|
+
url_prefixes_option = options[:api_url_prefixes]
|
46
|
+
@api_url_prefixes = url_prefixes_option.collect do |url|
|
47
|
+
/\A#{Regexp.escape(url)}/
|
48
|
+
end
|
49
|
+
@error_response = options[:error_response].to_json
|
50
|
+
@disable_authorization = options[:disable_authorization]
|
51
|
+
end
|
52
|
+
|
53
|
+
# For Rack.
|
54
|
+
def call(environment)
|
55
|
+
if api_url?(environment) and not authorized?(environment)
|
56
|
+
unauthorized_access_response
|
57
|
+
else
|
58
|
+
@application.call(environment)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
def api_url?(environment)
|
64
|
+
@api_url_prefixes.any? do |prefix|
|
65
|
+
environment["PATH_INFO"] =~ prefix
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def authorized?(environment)
|
70
|
+
if disable_authorization?
|
71
|
+
true
|
72
|
+
else
|
73
|
+
if @authorized_api_keys
|
74
|
+
@authorized_api_keys.include?(environment)
|
75
|
+
else
|
76
|
+
false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def disable_authorization?
|
82
|
+
@disable_authorization
|
83
|
+
end
|
84
|
+
|
85
|
+
def unauthorized_access_response
|
86
|
+
[
|
87
|
+
401,
|
88
|
+
{"Content-Type" => "application/json; charset=utf-8"},
|
89
|
+
[@error_response],
|
90
|
+
]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -14,10 +14,11 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
require 'digest'
|
20
20
|
require 'yaml'
|
21
|
+
require 'zlib'
|
21
22
|
require 'racknga/cache_database'
|
22
23
|
|
23
24
|
module Racknga
|
@@ -168,13 +169,15 @@ module Racknga
|
|
168
169
|
now = Time.now
|
169
170
|
headers = Rack::Utils::HeaderHash.new(headers)
|
170
171
|
headers["Last-Modified"] ||= now.httpdate
|
171
|
-
|
172
|
+
encoded_body = ''.force_encoding("ASCII-8BIT")
|
173
|
+
deflater = ::Zlib::Deflate.new
|
172
174
|
body.each do |data|
|
173
|
-
|
175
|
+
encoded_body << deflater.deflate(data)
|
174
176
|
end
|
177
|
+
body.close if body.respond_to?(:close)
|
178
|
+
encoded_body << deflater.finish
|
175
179
|
headers = headers.to_hash
|
176
180
|
encoded_headers = headers.to_yaml
|
177
|
-
encoded_body = stringified_body.force_encoding("ASCII-8BIT")
|
178
181
|
cache[key] = {
|
179
182
|
:status => status,
|
180
183
|
:headers => encoded_headers,
|
@@ -183,7 +186,7 @@ module Racknga
|
|
183
186
|
:age => age,
|
184
187
|
:created_at => now,
|
185
188
|
}
|
186
|
-
body =
|
189
|
+
body = Inflater.new(encoded_body)
|
187
190
|
log("store", request)
|
188
191
|
[status, headers, body]
|
189
192
|
end
|
@@ -199,7 +202,7 @@ module Racknga
|
|
199
202
|
end
|
200
203
|
|
201
204
|
log("hit", request)
|
202
|
-
[status, YAML.load(headers),
|
205
|
+
[status, YAML.load(headers), Inflater.new(body)]
|
203
206
|
end
|
204
207
|
|
205
208
|
def compute_checksum(status, encoded_headers, encoded_body)
|
@@ -221,12 +224,23 @@ module Racknga
|
|
221
224
|
def log(tag, request)
|
222
225
|
return unless Middleware.const_defined?(:Log)
|
223
226
|
env = request.env
|
224
|
-
logger = env[Middleware::Log::
|
227
|
+
logger = env[Middleware::Log::LOGGER]
|
225
228
|
return if logger.nil?
|
226
|
-
start_time = env[
|
229
|
+
start_time = env[START_TIME]
|
227
230
|
runtime = Time.now - start_time
|
228
231
|
logger.log("cache-#{tag}", request.fullpath, :runtime => runtime)
|
229
232
|
end
|
233
|
+
|
234
|
+
# @private
|
235
|
+
class Inflater
|
236
|
+
def initialize(deflated_string)
|
237
|
+
@deflated_string = deflated_string
|
238
|
+
end
|
239
|
+
|
240
|
+
def each
|
241
|
+
yield ::Zlib::Inflate.inflate(@deflated_string)
|
242
|
+
end
|
243
|
+
end
|
230
244
|
end
|
231
245
|
end
|
232
246
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
|
3
|
+
# Copyright (C) 2010-2011 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
module Racknga
|
20
20
|
module Middleware
|
@@ -63,7 +63,7 @@ module Racknga
|
|
63
63
|
|
64
64
|
# For Rack.
|
65
65
|
def call(environment)
|
66
|
-
if ie6?(environment)
|
66
|
+
if ie6?(environment) or not valid_accept_encoding?(environment)
|
67
67
|
@application.call(environment)
|
68
68
|
else
|
69
69
|
@deflater.call(environment)
|
@@ -74,6 +74,16 @@ module Racknga
|
|
74
74
|
def ie6?(environment)
|
75
75
|
/MSIE 6.0;/ =~ (environment["HTTP_USER_AGENT"] || '')
|
76
76
|
end
|
77
|
+
|
78
|
+
def valid_accept_encoding?(environment)
|
79
|
+
request = Rack::Request.new(environment)
|
80
|
+
begin
|
81
|
+
request.accept_encoding
|
82
|
+
true
|
83
|
+
rescue
|
84
|
+
false
|
85
|
+
end
|
86
|
+
end
|
77
87
|
end
|
78
88
|
end
|
79
89
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
require 'racknga/exception_mail_notifier'
|
20
20
|
|
@@ -26,7 +26,6 @@ module Racknga
|
|
26
26
|
#
|
27
27
|
# Usage:
|
28
28
|
# require "racknga"
|
29
|
-
# require "racknga/middleware/exception_notifier"
|
30
29
|
#
|
31
30
|
# notifier_options = {
|
32
31
|
# :subject_label => "[YourApplication]",
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
3
|
# Copyright (C) 2011 Ryo Onodera <onodera@clear-code.com>
|
4
|
+
# Copyright (C) 2012 Kouhei Sutou <kou@clear-code.com>
|
4
5
|
#
|
5
6
|
# This library is free software; you can redistribute it and/or
|
6
7
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -14,7 +15,7 @@
|
|
14
15
|
#
|
15
16
|
# You should have received a copy of the GNU Lesser General Public
|
16
17
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
18
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
19
|
|
19
20
|
module Racknga
|
20
21
|
module Middleware
|
@@ -23,12 +24,18 @@ module Racknga
|
|
23
24
|
# server when your Rack applications are deployed behind
|
24
25
|
# load balancers.
|
25
26
|
#
|
26
|
-
#
|
27
|
+
# @example A simple usage
|
27
28
|
# require "racknga"
|
28
29
|
# use Racknga::Middleware::InstanceName
|
29
30
|
# run YourApplication
|
30
31
|
class InstanceName
|
31
32
|
attr_reader :header
|
33
|
+
# @param [application] application rack application.
|
34
|
+
# @param [Hash] options options to create header.
|
35
|
+
# @option options [String] :header_name ("Responsed-By") header name.
|
36
|
+
# @option options [String] :application_name (application.class.name)
|
37
|
+
# application name.
|
38
|
+
# @option options [Integer] :version application version.
|
32
39
|
def initialize(application, options={})
|
33
40
|
@application = application
|
34
41
|
@options = options
|
@@ -57,7 +64,14 @@ module Racknga
|
|
57
64
|
end
|
58
65
|
|
59
66
|
def revision
|
60
|
-
|
67
|
+
case using_scm_name
|
68
|
+
when :git
|
69
|
+
`git describe --abbrev=7 HEAD`.strip
|
70
|
+
when :subversion
|
71
|
+
`LANG=C svn info | grep Revision`.strip
|
72
|
+
else
|
73
|
+
nil
|
74
|
+
end
|
61
75
|
end
|
62
76
|
|
63
77
|
def server
|
@@ -68,6 +82,21 @@ module Racknga
|
|
68
82
|
`id --user --name`.strip
|
69
83
|
end
|
70
84
|
|
85
|
+
def branch
|
86
|
+
case using_scm_name
|
87
|
+
when :git
|
88
|
+
git_branch_name
|
89
|
+
when :subversion
|
90
|
+
subversion_branch_name
|
91
|
+
else
|
92
|
+
nil
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def ruby
|
97
|
+
RUBY_DESCRIPTION
|
98
|
+
end
|
99
|
+
|
71
100
|
private
|
72
101
|
DEFAULT_HEADER_NAME = "X-Responsed-By"
|
73
102
|
def header_name
|
@@ -83,9 +112,10 @@ module Racknga
|
|
83
112
|
def construct_header
|
84
113
|
format_header(format_application_name(application_name),
|
85
114
|
format_version(version),
|
86
|
-
format_revision(revision),
|
115
|
+
format_revision(branch, revision),
|
87
116
|
format_server(server),
|
88
|
-
format_user(user)
|
117
|
+
format_user(user),
|
118
|
+
format_ruby(ruby))
|
89
119
|
end
|
90
120
|
|
91
121
|
def format_header(*arguments)
|
@@ -104,9 +134,15 @@ module Racknga
|
|
104
134
|
end
|
105
135
|
end
|
106
136
|
|
107
|
-
def format_revision(revision)
|
137
|
+
def format_revision(branch, revision)
|
108
138
|
format_if_possible(revision) do
|
109
|
-
"(at #{revision})"
|
139
|
+
"(at #{revision}#{format_branch(branch)})"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def format_branch(branch)
|
144
|
+
format_if_possible(branch) do
|
145
|
+
" (#{branch})"
|
110
146
|
end
|
111
147
|
end
|
112
148
|
|
@@ -122,12 +158,59 @@ module Racknga
|
|
122
158
|
end
|
123
159
|
end
|
124
160
|
|
161
|
+
def format_ruby(ruby)
|
162
|
+
format_if_possible(ruby) do
|
163
|
+
"with #{ruby}"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
125
167
|
def format_if_possible(data)
|
126
168
|
if data and (data.respond_to?(:to_s) and not data.to_s.empty?)
|
127
|
-
|
169
|
+
yield
|
170
|
+
else
|
171
|
+
nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
SVN_URL_KEY = /\AURL:.*/
|
176
|
+
SVN_REPOSITORY_ROOT_KEY = /\ARepository Root:.*/
|
177
|
+
SVN_KEY = /\A.*:/
|
178
|
+
SVN_BRANCHES_NAME = /\A\/branches\//
|
179
|
+
def subversion_branch_name
|
180
|
+
url = ""
|
181
|
+
repository_root = ""
|
182
|
+
|
183
|
+
`LANG=C svn info`.each_line do |line|
|
184
|
+
case line
|
185
|
+
when SVN_URL_KEY
|
186
|
+
url = line.sub(SVN_KEY, "").strip
|
187
|
+
when SVN_REPOSITORY_ROOT_KEY
|
188
|
+
repository_root = line.sub(SVN_KEY, "").strip
|
189
|
+
end
|
128
190
|
end
|
191
|
+
base_path = url.sub(/#{Regexp.escape(repository_root)}/, "")
|
192
|
+
base_path.sub(SVN_BRANCHES_NAME, "")
|
193
|
+
end
|
129
194
|
|
130
|
-
|
195
|
+
GIT_CURRENT_BRANCH_MARKER = /\A\* /
|
196
|
+
def git_branch_name
|
197
|
+
`git branch -a`.each_line do |line|
|
198
|
+
case line
|
199
|
+
when GIT_CURRENT_BRANCH_MARKER
|
200
|
+
return line.sub(GIT_CURRENT_BRANCH_MARKER, "").strip
|
201
|
+
end
|
202
|
+
end
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
|
206
|
+
def using_scm_name
|
207
|
+
if File.exist?(".git")
|
208
|
+
:git
|
209
|
+
elsif File.exist?(".svn")
|
210
|
+
:subversion
|
211
|
+
else
|
212
|
+
nil
|
213
|
+
end
|
131
214
|
end
|
132
215
|
end
|
133
216
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
#
|
3
|
-
# Copyright (C) 2010 Kouhei Sutou <kou@clear-code.com>
|
3
|
+
# Copyright (C) 2010-2012 Kouhei Sutou <kou@clear-code.com>
|
4
4
|
#
|
5
5
|
# This library is free software; you can redistribute it and/or
|
6
6
|
# modify it under the terms of the GNU Lesser General Public
|
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
module Racknga
|
20
20
|
module Middleware
|
@@ -91,7 +91,7 @@ module Racknga
|
|
91
91
|
header_hash = Rack::Utils::HeaderHash.new(headers)
|
92
92
|
return [status, headers, body] unless json_response?(header_hash)
|
93
93
|
body = Writer.new(callback, body)
|
94
|
-
|
94
|
+
update_header_hash(header_hash, body)
|
95
95
|
[status, header_hash, body]
|
96
96
|
end
|
97
97
|
|
@@ -122,26 +122,46 @@ module Racknga
|
|
122
122
|
media_type == "text/javascript"
|
123
123
|
end
|
124
124
|
|
125
|
+
def update_header_hash(header_hash, body)
|
126
|
+
update_content_type(header_hash)
|
127
|
+
update_content_length(header_hash, body)
|
128
|
+
end
|
129
|
+
|
125
130
|
def update_content_type(header_hash)
|
126
131
|
content_type = header_hash["Content-Type"]
|
127
132
|
media_type, parameters = content_type.split(/\s*;\s*/, 2)
|
133
|
+
_ = media_type # FIXME: suppress a warning. :<
|
128
134
|
# We should use application/javascript not
|
129
135
|
# text/javascript when all IE <= 8 are deprecated. :<
|
130
136
|
updated_content_type = ["text/javascript", parameters].compact.join("; ")
|
131
137
|
header_hash["Content-Type"] = updated_content_type
|
132
138
|
end
|
133
139
|
|
140
|
+
def update_content_length(header_hash, body)
|
141
|
+
return unless header_hash["Content-Length"]
|
142
|
+
|
143
|
+
content_length = header_hash["Content-Length"].to_i
|
144
|
+
updated_content_length = content_length + body.additional_content_length
|
145
|
+
header_hash["Content-Length"] = updated_content_length.to_s
|
146
|
+
end
|
147
|
+
|
134
148
|
# @private
|
135
149
|
class Writer
|
136
150
|
def initialize(callback, body)
|
137
151
|
@callback = callback
|
138
152
|
@body = body
|
153
|
+
@header = "#{@callback}("
|
154
|
+
@footer = ");"
|
139
155
|
end
|
140
156
|
|
141
157
|
def each(&block)
|
142
|
-
block.call(
|
158
|
+
block.call(@header)
|
143
159
|
@body.each(&block)
|
144
|
-
block.call(
|
160
|
+
block.call(@footer)
|
161
|
+
end
|
162
|
+
|
163
|
+
def additional_content_length
|
164
|
+
@header.bytesize + @footer.bytesize
|
145
165
|
end
|
146
166
|
end
|
147
167
|
end
|
@@ -14,7 +14,7 @@
|
|
14
14
|
#
|
15
15
|
# You should have received a copy of the GNU Lesser General Public
|
16
16
|
# License along with this library; if not, write to the Free Software
|
17
|
-
# Foundation, Inc.,
|
17
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
18
|
|
19
19
|
require 'racknga/log_database'
|
20
20
|
|
@@ -70,9 +70,12 @@ module Racknga
|
|
70
70
|
private
|
71
71
|
def log(start_time, end_time, request, status, headers, body)
|
72
72
|
request_time = end_time - start_time
|
73
|
+
runtime = headers["X-Runtime"]
|
74
|
+
runtime_in_float = nil
|
75
|
+
runtime_in_float = runtime.to_f if runtime
|
73
76
|
length = headers["Content-Length"] || "-"
|
74
77
|
length = "-" if length == "0"
|
75
|
-
format = "%s - %s [%s] \"%s %s %s\" %s %s \"%s\" \"%s\" %0.8f"
|
78
|
+
format = "%s - %s [%s] \"%s %s %s\" %s %s \"%s\" \"%s\" %s %0.8f"
|
76
79
|
message = format % [request.ip || "-",
|
77
80
|
request.env["REMOTE_USER"] || "-",
|
78
81
|
end_time.dup.utc.strftime("%d/%b/%Y:%H:%M:%S %z"),
|
@@ -83,12 +86,14 @@ module Racknga
|
|
83
86
|
length,
|
84
87
|
request.env["HTTP_REFERER"] || "-",
|
85
88
|
request.user_agent || "-",
|
89
|
+
runtime || "-",
|
86
90
|
request_time]
|
87
91
|
@logger.log("access",
|
88
92
|
request.fullpath,
|
89
93
|
:message => message,
|
90
94
|
:user_agent => request.user_agent,
|
91
|
-
:runtime =>
|
95
|
+
:runtime => runtime_in_float,
|
96
|
+
:request_time => request_time)
|
92
97
|
end
|
93
98
|
|
94
99
|
# @private
|