racknga 0.9.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -20,9 +20,20 @@ require 'racknga/log_database'
20
20
 
21
21
  module Racknga
22
22
  module Middleware
23
+ # This is a middleware that puts access logs to groonga
24
+ # database. It may useful for OLAP (OnLine Analytical
25
+ # Processing).
26
+ #
27
+ # Usage:
28
+ # use Racnkga::Middleware::Log, :database_path => "var/log/db"
29
+ # run YourApplication
30
+ #
31
+ # @see Racknga::LogDatabase
23
32
  class Log
24
- LOGGER_KEY = "racknga.logger"
33
+ LOGGER = "racknga.logger"
25
34
 
35
+ # @option options [String] :database_path the
36
+ # database path to be stored caches.
26
37
  def initialize(application, options={})
27
38
  @application = application
28
39
  @options = Utils.normalize_options(options || {})
@@ -32,8 +43,9 @@ module Racknga
32
43
  @logger = Logger.new(@database)
33
44
  end
34
45
 
46
+ # For Rack.
35
47
  def call(environment)
36
- environment[LOGGER_KEY] = @logger
48
+ environment[LOGGER] = @logger
37
49
 
38
50
  start_time = Time.now
39
51
  status, headers, body = @application.call(environment)
@@ -45,10 +57,12 @@ module Racknga
45
57
  [status, headers, body]
46
58
  end
47
59
 
60
+ # ensures creating cache database.
48
61
  def ensure_database
49
62
  @database.ensure_database
50
63
  end
51
64
 
65
+ # close the cache database.
52
66
  def close_database
53
67
  @database.close_database
54
68
  end
@@ -77,6 +91,7 @@ module Racknga
77
91
  :runtime => request_time)
78
92
  end
79
93
 
94
+ # @private
80
95
  class Logger
81
96
  def initialize(database)
82
97
  @database = database
@@ -20,11 +20,20 @@ require 'time'
20
20
 
21
21
  module Racknga
22
22
  module Middleware
23
+ # This is a middleware that provides HTTP range request
24
+ # (partial request) support. For example, HTTP range
25
+ # request is used for playing a video on the way.
26
+ #
27
+ # Usage:
28
+ # require "racknga"
29
+ # use Racknga::Middleware::Range
30
+ # run YourApplication
23
31
  class Range
24
32
  def initialize(application)
25
33
  @application = application
26
34
  end
27
35
 
36
+ # For Rack.
28
37
  def call(environment)
29
38
  status, headers, body = @application.call(environment)
30
39
  return [status, headers, body] if status != 200
@@ -109,6 +118,7 @@ module Racknga
109
118
  nil
110
119
  end
111
120
 
121
+ # @private
112
122
  class RangeStream
113
123
  def initialize(body, first_byte, length)
114
124
  @body = body
@@ -0,0 +1,139 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Ryo Onodera <onodera@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+
19
+ require "racknga/reverse_line_reader"
20
+
21
+ module Racknga
22
+ # Supported formats:
23
+ # * combined (default format)
24
+ # * combined_with_time (custom format for Passenger)
25
+ #
26
+ # Configurations in nginx:
27
+ # * combined
28
+ # log_format combined '$remote_addr - $remote_user [$time_local] '
29
+ # '"$request" $status $body_bytes_sent '
30
+ # '"$http_referer" "$http_user_agent"';
31
+ # access_log log/access.log combined
32
+ #
33
+ # * combined_with_time
34
+ # log_format combined_with_time '$remote_addr - $remote_user '
35
+ # '[$time_local, $upstream_http_x_runtime, $request_time] '
36
+ # '"$request" $status $body_bytes_sent '
37
+ # '"$http_referer" "$http_user_agent"';
38
+ # access_log log/access.log combined_with_time
39
+ class NginxAccessLogParser
40
+ include Enumerable
41
+
42
+ class FormatError < StandardError
43
+ end
44
+
45
+ def initialize(line_reader)
46
+ @line_reader = line_reader
47
+ end
48
+
49
+ def each
50
+ @line_reader.each do |line|
51
+ line.force_encoding("UTF-8")
52
+ yield(parse_line(line)) if line.valid_encoding?
53
+ end
54
+ end
55
+
56
+ REMOTE_ADDRESS = '(?:\d{1,3}\.){3}\d{1,3}'
57
+ REMOTE_USER = '[^ ]+'
58
+ TIME_LOCAL = '[^ ]+ \+\d{4}'
59
+ RUNTIME = '(?:[\d.]+|-)'
60
+ REQUEST_TIME = '[\d.]+'
61
+ REQUEST = '.*?'
62
+ STATUS = '\d{3}'
63
+ BODY_BYTES_SENT = '\d+'
64
+ HTTP_REFERER = '.*?'
65
+ HTTP_USER_AGENT = '(?:\\"|[^\"])*?' # '
66
+ LOG_FORMAT =
67
+ /\A(#{REMOTE_ADDRESS}) - (#{REMOTE_USER}) \[(#{TIME_LOCAL})(?:, (#{RUNTIME}), (#{REQUEST_TIME}))?\] "(#{REQUEST})" (#{STATUS}) (#{BODY_BYTES_SENT}) "(#{HTTP_REFERER})" "(#{HTTP_USER_AGENT})"\n\z/
68
+ def parse_line(line)
69
+ if line =~ LOG_FORMAT
70
+ last_match = Regexp.last_match
71
+ options = {}
72
+ options[:remote_address] = last_match[1]
73
+ options[:remote_user] = last_match[2]
74
+ parse_time_local(last_match[3], options)
75
+ options[:runtime] = last_match[4].to_f
76
+ options[:request_time] = last_match[5].to_f
77
+ options[:request] = last_match[6]
78
+ options[:status] = last_match[7].to_i
79
+ options[:body_bytes_sent] = last_match[8].to_i
80
+ options[:http_referer] = last_match[9]
81
+ options[:http_user_agent] = last_match[10]
82
+ LogEntry.new(options)
83
+ else
84
+ raise FormatError.new("ill-formatted log entry: #{line.inspect} !~ #{LOG_FORMAT}")
85
+ end
86
+ end
87
+
88
+ def parse_time_local(token, options)
89
+ day, month, year, hour, minute, second, _time_zone = token.split(/[\/: ]/)
90
+ options[:time_local] = Time.local(year, month, day, hour, minute, second)
91
+ end
92
+ end
93
+
94
+ class ReversedNginxAccessLogParser < NginxAccessLogParser
95
+ def initialize(line_reader)
96
+ @line_reader = ReverseLineReader.new(line_reader)
97
+ end
98
+ end
99
+
100
+ class LogEntry
101
+ ATTRIBUTES = [
102
+ :remote_address,
103
+ :remote_user,
104
+ :time_local,
105
+ :runtime,
106
+ :request_time,
107
+ :request,
108
+ :status,
109
+ :body_bytes_sent,
110
+ :http_referer,
111
+ :http_user_agent,
112
+ ]
113
+
114
+ attr_reader(*ATTRIBUTES)
115
+ def initialize(options=nil)
116
+ options ||= {}
117
+ @remote_address = options[:remote_address]
118
+ @remote_user = options[:remote_user]
119
+ @time_local = options[:time_local] || Time.at(0)
120
+ @runtime = options[:runtime] || 0.0
121
+ @request_time = options[:request_time] || 0.0
122
+ @request = options[:request]
123
+ @status = options[:status]
124
+ @body_bytes_sent = options[:body_bytes_sent]
125
+ @http_referer = options[:http_referer]
126
+ @http_user_agent = options[:http_user_agent]
127
+ end
128
+
129
+ def attributes
130
+ ATTRIBUTES.collect do |attribute|
131
+ __send__(attribute)
132
+ end
133
+ end
134
+
135
+ def ==(other)
136
+ attributes == other.attributes
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,73 @@
1
+ # -*- coding: utf-8 -*-
2
+ #
3
+ # Copyright (C) 2011 Ryo Onodera <onodera@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
+
19
+ module Racknga
20
+ class ReverseLineReader
21
+ def initialize(io)
22
+ @io = io
23
+ @io.seek(0, IO::SEEK_END)
24
+ @buffer = ""
25
+ @data = ""
26
+ end
27
+
28
+ def each
29
+ separator = $/
30
+ separator_length = separator.length
31
+ while read_to_buffer
32
+ loop do
33
+ index = @buffer.rindex(separator, @buffer.length - 1 - separator_length)
34
+ break if index.nil? or index.zero?
35
+ last_line = @buffer.slice!((index + separator_length)..-1)
36
+ yield(last_line)
37
+ end
38
+ end
39
+ yield(@buffer) unless @buffer.empty?
40
+ end
41
+
42
+ private
43
+ BYTES_PER_READ = 4096
44
+ def read
45
+ position = @io.pos
46
+ if position < BYTES_PER_READ
47
+ bytes_per_read = position
48
+ else
49
+ bytes_per_read = BYTES_PER_READ
50
+ end
51
+
52
+ if bytes_per_read.zero?
53
+ @data.replace("")
54
+ else
55
+ @io.seek(-bytes_per_read, IO::SEEK_CUR)
56
+ @io.read(bytes_per_read, @data)
57
+ @io.seek(-bytes_per_read, IO::SEEK_CUR)
58
+ end
59
+
60
+ @data
61
+ end
62
+
63
+ def read_to_buffer
64
+ data = read.force_encoding("BINARY")
65
+ if data.empty?
66
+ false
67
+ else
68
+ @buffer.insert(0, data)
69
+ true
70
+ end
71
+ end
72
+ end
73
+ 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
@@ -17,5 +17,5 @@
17
17
  # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
 
19
19
  module Racknga
20
- VERSION = '0.9.1'
20
+ VERSION = '0.9.2'
21
21
  end
@@ -19,6 +19,7 @@
19
19
  require "groonga"
20
20
 
21
21
  module Groonga
22
+ # @deprecated since 0.9.2. Use Kaminari instead of will_paginate.
22
23
  module WillPaginateAPI
23
24
  def total_pages
24
25
  n_pages
data/lib/racknga.rb CHANGED
@@ -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
@@ -20,7 +20,9 @@ require 'rack'
20
20
 
21
21
  require 'racknga/version'
22
22
  require 'racknga/utils'
23
+ require "racknga/nginx_access_log_parser"
23
24
  require 'racknga/middleware/deflater'
24
25
  require 'racknga/middleware/exception_notifier'
25
26
  require 'racknga/middleware/jsonp'
26
27
  require 'racknga/middleware/range'
28
+ require "racknga/middleware/instance_name"