Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow custom log messages #8

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ There are a few options you can pass in:
* `:label` is the warning label displayed to those with CSS disabled. Defaults to "Don't fill in this field".
* `:input_name` is the name of the form field. Ensure that this is tempting to a spambot if you modify it. Defaults to "email".
* `:input_value` is the value of the form field that would only be modified by a spambot. Defaults to blank.
* `:logger` is the Logger instance you wish to use for logging trapped requests.
* `:log_message` is the string message that is to be logged, or a callable object that returns a string when called with
a `Rack::Request`.

If you want to modify the options used, simply do:

Expand Down
17 changes: 15 additions & 2 deletions lib/rack/honeypot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ def initialize(app, options={})
@input_value = options[:input_value] || ""
@logger = options[:logger]
@always_enabled = options.fetch(:always_enabled, true)
@log_message = options[:log_message] || DEFAULT_LOG_MESSAGE
end

def call(env)
if spambot_submission?(Rack::Request.new(env).params)
@logger.warn("[Rack::Honeypot] Spam bot detected; responded with null") unless @logger.nil?
request = Rack::Request.new(env)

if spambot_submission?(request.params)
@logger.warn("[Rack::Honeypot] " + log_message(request)) unless @logger.nil?
null_response
else
status, headers, body = @app.call(env)
Expand All @@ -35,6 +38,8 @@ def call(env)

private

DEFAULT_LOG_MESSAGE = "Spam bot detected; responded with null"

def spambot_submission?(form_hash)
form_hash && form_hash[@input_name] && form_hash[@input_name] != @input_value
end
Expand All @@ -43,6 +48,14 @@ def honeypot_header_present?(headers)
header = headers.delete(HONEYPOT_HEADER)
header && header.index("enabled")
end

def log_message(request)
if @log_message.respond_to?(:call)
@log_message.call(request)
else
@log_message
end
end

def null_response
[200, {'Content-Type' => 'text/html', "Content-Length" => "0"}, []]
Expand Down
20 changes: 18 additions & 2 deletions test/test_honeypot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ def setup
end

def app
return @app if @app

Rack::Honeypot.new(hello_world_app, :input_name => 'honeypot_email', :logger => @logger, :always_enabled => @always_enabled)
end

def hello_world_app
content = unindent <<-BLOCK
<html>
<head>
Expand All @@ -37,8 +43,6 @@ def app
headers['X-Honeypot'] = @honeypot_header if @honeypot_header

hello_world_app = lambda {|env| [200, headers, [content]] }

Rack::Honeypot.new(hello_world_app, :input_name => 'honeypot_email', :logger => @logger, :always_enabled => @always_enabled)
end

def test_normal_request_should_go_through
Expand All @@ -47,6 +51,18 @@ def test_normal_request_should_go_through
assert_not_equal '', last_response.body
end

def test_custom_logging
Rack::Request.any_instance.stubs(:ip).returns("1.2.3.4")

log_message = proc {|request| "Intercepted request from #{request.ip}" }
@app = Rack::Honeypot.new(hello_world_app, :input_name => 'honeypot_email', :logger => @logger, :log_message => log_message)

@logger.expects(:warn).with("[Rack::Honeypot] Intercepted request from 1.2.3.4")
post '/', :honeypot_email => 'joe@example.com'
assert_equal 200, last_response.status
assert_equal '', last_response.body
end

def test_request_with_form_should_add_honeypot_css
get '/'
assert_equal 200, last_response.status
Expand Down