racknga 0.9.1 → 0.9.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.
@@ -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"