rack-honeypot 0.1.0 → 0.1.1

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.
data/lib/rack/honeypot.rb CHANGED
@@ -16,52 +16,56 @@ module Rack
16
16
  def call(env)
17
17
  if spambot_submission?(Rack::Request.new(env).params)
18
18
  @logger.warn("[Rack::Honeypot] Spam bot detected; responded with null") unless @logger.nil?
19
- send_to_dead_end
19
+ null_response
20
20
  else
21
21
  status, headers, response = @app.call(env)
22
- new_body = insert_honeypot(build_response_body(response))
23
- new_headers = recalculate_body_length(headers, new_body)
22
+ new_body = insert_honeypot(response_body(response))
23
+ new_headers = response_headers(headers, new_body)
24
24
  [status, new_headers, new_body]
25
25
  end
26
26
  end
27
27
 
28
+ private
29
+
28
30
  def spambot_submission?(form_hash)
29
31
  form_hash && form_hash[@input_name] && form_hash[@input_name] != @input_value
30
32
  end
31
33
 
32
- def send_to_dead_end
34
+ def null_response
33
35
  [200, {'Content-Type' => 'text/html', "Content-Length" => "0"}, []]
34
36
  end
35
37
 
36
- def build_response_body(response)
37
- response_body = ""
38
- response.each { |part| response_body += part }
39
- response_body
38
+ def response_body(response)
39
+ response.join("")
40
40
  end
41
41
 
42
- def recalculate_body_length(headers, body)
43
- new_headers = headers
44
- new_headers["Content-Length"] = body.length.to_s
45
- new_headers
42
+ def response_headers(headers, body)
43
+ headers.merge("Content-Length" => body.length.to_s)
46
44
  end
47
45
 
48
46
  def insert_honeypot(body)
49
- css = unindent <<-BLOCK
47
+ body.gsub!(/<\/head>/, css + "\n</head>")
48
+ body.gsub!(/<form(.*)>/, '<form\1>' + "\n" + div)
49
+ body
50
+ end
51
+
52
+ def css
53
+ unindent <<-BLOCK
50
54
  <style type='text/css' media='all'>
51
55
  div.#{@class_name} {
52
56
  display:none;
53
57
  }
54
58
  </style>
55
59
  BLOCK
56
- div = unindent <<-BLOCK
60
+ end
61
+
62
+ def div
63
+ unindent <<-BLOCK
57
64
  <div class='#{@class_name}'>
58
65
  <label for='#{@input_name}'>#{@label}</label>
59
66
  <input type='text' name='#{@input_name}' value='#{@input_value}'/>
60
67
  </div>
61
68
  BLOCK
62
- body.gsub!(/<\/head>/, css + "\n</head>")
63
- body.gsub!(/<form(.*)>/, '<form\1>' + "\n" + div)
64
- body
65
69
  end
66
70
 
67
71
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-honeypot
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Luigi Montanez
@@ -19,24 +19,10 @@ cert_chain: []
19
19
 
20
20
  date: 2011-10-05 00:00:00 Z
21
21
  dependencies:
22
- - !ruby/object:Gem::Dependency
23
- name: rake
24
- prerelease: false
25
- requirement: &id001 !ruby/object:Gem::Requirement
26
- none: false
27
- requirements:
28
- - - ">="
29
- - !ruby/object:Gem::Version
30
- hash: 3
31
- segments:
32
- - 0
33
- version: "0"
34
- type: :runtime
35
- version_requirements: *id001
36
22
  - !ruby/object:Gem::Dependency
37
23
  name: unindentable
38
24
  prerelease: false
39
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ requirement: &id001 !ruby/object:Gem::Requirement
40
26
  none: false
41
27
  requirements:
42
28
  - - "="
@@ -48,25 +34,11 @@ dependencies:
48
34
  - 4
49
35
  version: 0.0.4
50
36
  type: :runtime
51
- version_requirements: *id002
37
+ version_requirements: *id001
52
38
  - !ruby/object:Gem::Dependency
53
39
  name: rack
54
40
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
56
- none: false
57
- requirements:
58
- - - ">="
59
- - !ruby/object:Gem::Version
60
- hash: 3
61
- segments:
62
- - 0
63
- version: "0"
64
- type: :runtime
65
- version_requirements: *id003
66
- - !ruby/object:Gem::Dependency
67
- name: rack-test
68
- prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
41
+ requirement: &id002 !ruby/object:Gem::Requirement
70
42
  none: false
71
43
  requirements:
72
44
  - - ">="
@@ -76,7 +48,7 @@ dependencies:
76
48
  - 0
77
49
  version: "0"
78
50
  type: :runtime
79
- version_requirements: *id004
51
+ version_requirements: *id002
80
52
  description: This middleware acts as a spam trap. It inserts, into every outputted <form>, a text field that a spambot will really want to fill in, but is actually not used by the app. The field is hidden to humans via CSS, and includes a warning label for screenreading software.
81
53
  email: luigi.montanez@gmail.com
82
54
  executables: []
@@ -87,13 +59,10 @@ extra_rdoc_files:
87
59
  - LICENSE.md
88
60
  - README.md
89
61
  files:
90
- - Gemfile
91
62
  - LICENSE.md
92
63
  - README.md
93
- - Rakefile
94
64
  - VERSION
95
65
  - lib/rack/honeypot.rb
96
- - test/test_honeypot.rb
97
66
  homepage: http://github.com/sunlightlabs/rack-honeypot
98
67
  licenses: []
99
68
 
data/Gemfile DELETED
@@ -1,7 +0,0 @@
1
- source 'http://rubygems.org/'
2
-
3
- gem 'rake'
4
- gem 'unindentable', '0.0.4'
5
- gem 'rack'
6
- gem 'mocha'
7
- gem 'rack-test'
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
-
2
- require 'rake/testtask'
3
-
4
- Rake::TestTask.new do |task|
5
- task.test_files = FileList['test/test_*.rb']
6
- end
@@ -1,87 +0,0 @@
1
- require 'rack/test'
2
- require 'test/unit'
3
- require 'mocha'
4
- require 'unindentable'
5
-
6
- require File.expand_path(File.dirname(__FILE__) + '/../lib/rack/honeypot')
7
-
8
- # To run this test, you need to have rack-test gem installed: sudo gem install rack-test
9
-
10
- class HoneypotTest < Test::Unit::TestCase
11
- include Rack::Test::Methods
12
- include Unindentable
13
-
14
- def setup
15
- @logger = stub("logger", :warn => nil)
16
- end
17
-
18
- def app
19
- content = unindent <<-BLOCK
20
- <html>
21
- <head>
22
- </head>
23
- <body>
24
- <form></form>
25
- Hello World!
26
- </body>
27
- </html>
28
- BLOCK
29
-
30
- hello_world_app = lambda do |env|
31
- [
32
- 200,
33
- {
34
- 'Content-Type' => 'text/plain',
35
- 'Content-Length' => content.length.to_s
36
- },
37
- [content]
38
- ]
39
- end
40
-
41
- Rack::Honeypot.new(hello_world_app, :input_name => 'honeypot_email', :logger => @logger)
42
- end
43
-
44
- def test_normal_request_should_go_through
45
- get '/'
46
- assert_equal 200, last_response.status
47
- assert_not_equal '', last_response.body
48
- end
49
-
50
- def test_request_with_form_should_add_honeypot_css
51
- get '/'
52
- assert_equal 200, last_response.status
53
- css = unindent <<-BLOCK
54
- <style type='text/css' media='all'>
55
- div.phonetoy {
56
- display:none;
57
- }
58
- </style>
59
- BLOCK
60
- assert last_response.body.index(css)
61
- end
62
-
63
- def test_request_with_form_should_add_honeypot_div
64
- get '/'
65
- assert_equal 200, last_response.status
66
-
67
- div = unindent <<-BLOCK
68
- <div class='phonetoy'>
69
- <label for='honeypot_email'>Don't fill in this field</label>
70
- <input type='text' name='honeypot_email' value=''/>
71
- </div>
72
- BLOCK
73
- assert last_response.body.index(div)
74
- end
75
-
76
- def test_spam_request_should_be_sent_to_dead_end
77
- post '/', :honeypot_email => 'joe@example.com'
78
- assert_equal 200, last_response.status
79
- assert_equal '', last_response.body
80
- end
81
-
82
- def test_spam_request_should_be_logged
83
- @logger.expects(:warn).with("[Rack::Honeypot] Spam bot detected; responded with null")
84
- post '/', :honeypot_email => 'joe@example.com'
85
- end
86
-
87
- end