rack-speling 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +3 -0
- data/Rakefile +1 -37
- data/lib/rack/speling.rb +57 -0
- data/lib/rack/speling/sp_dist.rb +81 -0
- data/lib/{rack-speling → rack/speling}/version.rb +1 -1
- data/rack-speling.gemspec +1 -2
- data/test/all.rb +3 -0
- data/test/helper.rb +4 -4
- data/test/test_rack-speling.rb +34 -9
- metadata +9 -6
- data/lib/rack-speling.rb +0 -19
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -1,45 +1,9 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
# vim:ft=ruby:fileencoding=utf-8
|
3
3
|
|
4
|
-
# # enable trace to get better error output
|
5
|
-
# Rake.application.options.trace = true
|
6
|
-
|
7
|
-
# # documentation tasks
|
8
|
-
# begin
|
9
|
-
# %w[ rake/rdoctask sdoc ].each { |lib| require lib }
|
10
|
-
# Rake::RDocTask.new do |rdoc|
|
11
|
-
# version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
12
|
-
#
|
13
|
-
# rdoc.rdoc_dir = 'doc/rdoc'
|
14
|
-
# rdoc.title = "to_pass #{version}"
|
15
|
-
# rdoc.options << '--fmt=shtml'
|
16
|
-
# rdoc.options << '--all'
|
17
|
-
# rdoc.options << '--charset=utf-8'
|
18
|
-
# rdoc.template = 'direct'
|
19
|
-
# rdoc.rdoc_files.include('README*')
|
20
|
-
# rdoc.rdoc_files.include('LICENSE')
|
21
|
-
# rdoc.rdoc_files.include('TODO')
|
22
|
-
# rdoc.rdoc_files.include('lib/**/*.rb')
|
23
|
-
# rdoc.rdoc_files.include('data/**/*.rb')
|
24
|
-
# end
|
25
|
-
# rescue LoadError
|
26
|
-
# end
|
27
|
-
|
28
4
|
desc "run tests"
|
29
5
|
task :test do
|
30
|
-
|
31
|
-
%w[ redgreen ].each do |lib|
|
32
|
-
begin
|
33
|
-
require lib
|
34
|
-
rescue LoadError
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
require 'test/unit'
|
39
|
-
|
40
|
-
( ['test/helper'] + Dir['test/test_*.rb'] ).each do |file|
|
41
|
-
require File.expand_path("../#{file}", __FILE__)
|
42
|
-
end
|
6
|
+
require File.expand_path("../test/all", __FILE__)
|
43
7
|
end
|
44
8
|
|
45
9
|
task :default => :test
|
data/lib/rack/speling.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# vim:ft=ruby:fileencoding=utf-8
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Speling
|
5
|
+
attr_reader :app, :lookup, :env, :response
|
6
|
+
|
7
|
+
# remember the application as we need to call before or after this
|
8
|
+
# an lookup-object may be supplied for further 404-handling
|
9
|
+
def initialize(app, options = {})
|
10
|
+
@app = app
|
11
|
+
@lookup = options[:lookup] || {}
|
12
|
+
end
|
13
|
+
|
14
|
+
# downcase PATH_INFO and REQUEST_URI
|
15
|
+
# furthermore, try to lookup 404s to react with a redirect
|
16
|
+
def call(env)
|
17
|
+
@env = env
|
18
|
+
|
19
|
+
downcase_path
|
20
|
+
|
21
|
+
@response = app.call(env)
|
22
|
+
|
23
|
+
if response[0] == 404 && path_lookup
|
24
|
+
correct_response
|
25
|
+
else
|
26
|
+
response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def correct_response
|
33
|
+
headers = response[1].merge({
|
34
|
+
'Location' => new_location
|
35
|
+
})
|
36
|
+
|
37
|
+
[302, headers, "Moved: #{headers['Location']}"]
|
38
|
+
end
|
39
|
+
|
40
|
+
def new_location
|
41
|
+
path_lookup.start_with?('http:') ? path_lookup : "http://#{env['HTTP_HOST']}#{path_lookup}"
|
42
|
+
end
|
43
|
+
|
44
|
+
def path_lookup
|
45
|
+
@path_lookup ||= lookup[path]
|
46
|
+
end
|
47
|
+
|
48
|
+
def path
|
49
|
+
env['PATH_INFO']
|
50
|
+
end
|
51
|
+
|
52
|
+
def downcase_path
|
53
|
+
env['PATH_INFO'] = env['PATH_INFO'].downcase
|
54
|
+
env['REQUEST_URI'] = env['REQUEST_URI'].downcase
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Rack
|
2
|
+
module Speling
|
3
|
+
class SpDist
|
4
|
+
def lookup(url)
|
5
|
+
check_speling(url)
|
6
|
+
end
|
7
|
+
|
8
|
+
# taken from apaches mod_speling
|
9
|
+
#
|
10
|
+
# we only want to worry about GET
|
11
|
+
# We've already got a file of some kind or another
|
12
|
+
def check_speling
|
13
|
+
raise NotImplentedError, "TODO: Complete port of apaches mod_speling into #{__FILE__}"
|
14
|
+
end
|
15
|
+
|
16
|
+
# return values of spdist(s,t)
|
17
|
+
SP_IDENTICAL = 0
|
18
|
+
SP_MISCAPITALIZED = 1
|
19
|
+
SP_TRANSPOSITION = 2
|
20
|
+
SP_MISSINGCHAR = 3
|
21
|
+
SP_EXTRACHAR = 4
|
22
|
+
SP_SIMPLETYPO = 5
|
23
|
+
SP_VERYDIFFERENT = 6
|
24
|
+
|
25
|
+
# spdist() is taken from Kernighan & Pike,
|
26
|
+
# _The_UNIX_Programming_Environment_
|
27
|
+
# and adapted somewhat to correspond better to psychological reality.
|
28
|
+
# (Note the changes to the return values)
|
29
|
+
#
|
30
|
+
# According to Pollock and Zamora, CACM April 1984 (V. 27, No. 4),
|
31
|
+
# page 363, the correct order for this is:
|
32
|
+
# OMISSION = TRANSPOSITION > INSERTION > SUBSTITUTION
|
33
|
+
# thus, it was exactly backwards in the old version. -- PWP
|
34
|
+
#
|
35
|
+
# This routine was taken out of tcsh's spelling correction code
|
36
|
+
# (tcsh-6.07.04) and re-converted to apache data types ("char" type
|
37
|
+
# instead of tcsh's NLS'ed "Char"). Plus it now ignores the case
|
38
|
+
# during comparisons, so is a "approximate strcasecmp()".
|
39
|
+
# NOTE that is still allows only _one_ real "typo",
|
40
|
+
# it does NOT try to correct multiple errors.
|
41
|
+
#
|
42
|
+
# This version is taken from mod_speling.c, httpd-2.2.16 and
|
43
|
+
# adapted to ruby
|
44
|
+
# /Users/matthias/Projects/httpd-2.2.16/modules/mappers/mod_speling.c
|
45
|
+
# FIXME This won't work, yet
|
46
|
+
def spdist(s, t)
|
47
|
+
# exact match (sans case)
|
48
|
+
if s.downcase == t.downcase
|
49
|
+
return SP_MISCAPITALIZED
|
50
|
+
end
|
51
|
+
|
52
|
+
unless s.nil?
|
53
|
+
unless t.nil?
|
54
|
+
# transposition
|
55
|
+
if s[1] && t[1] && s.downcase == t[1].downcase && t.downcase == s[1].downcase && (s + 2).casecmp(t + 2) == 0
|
56
|
+
return SP_TRANSPOSITION
|
57
|
+
end
|
58
|
+
|
59
|
+
# char mismatch
|
60
|
+
if (s + 1).casecmp(t + 1) == 0
|
61
|
+
return SP_SIMPLETYPO
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# extra character
|
66
|
+
if (s + 1).casecmp(t) == 0
|
67
|
+
return SP_EXTRACHAR
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# missing character
|
72
|
+
if !t.nil? && s.casecmp(t+1) == 0
|
73
|
+
return SP_MISSINGCHAR
|
74
|
+
end
|
75
|
+
|
76
|
+
# distance too large to fix
|
77
|
+
return SP_VERYDIFFERENT
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/rack-speling.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# vim:ft=ruby:fileencoding=utf-8
|
2
|
-
require 'lib/rack
|
2
|
+
require 'lib/rack/speling/version.rb'
|
3
3
|
|
4
4
|
spec = Gem::Specification.new do |s|
|
5
5
|
s.name = 'rack-speling'
|
@@ -18,6 +18,5 @@ spec = Gem::Specification.new do |s|
|
|
18
18
|
|
19
19
|
s.files = `git ls-files`.split("\n")
|
20
20
|
s.test_files = `git ls-files test`.split("\n")
|
21
|
-
# s.executables = `git ls-files bin`.split("\\n")
|
22
21
|
s.require_path = 'lib'
|
23
22
|
end
|
data/test/all.rb
ADDED
data/test/helper.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# vim:ft=ruby:fileencoding=utf-8
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'test/unit'
|
3
|
+
require 'redgreen' rescue LoadError
|
4
|
+
require 'test/unit'
|
5
5
|
|
6
6
|
base_path = ( File.expand_path(File.dirname(__FILE__)+'/..') )
|
7
7
|
lib_path = "#{base_path}/lib"
|
8
|
-
if File.exist?(base_path + '/lib/rack
|
8
|
+
if File.exist?(base_path + '/lib/rack/speling')
|
9
9
|
$LOAD_PATH << base_path unless $LOAD_PATH.include?(base_path)
|
10
10
|
end
|
11
11
|
if File.exist?( lib_path )
|
12
12
|
$LOAD_PATH << lib_path unless $LOAD_PATH.include?(lib_path)
|
13
13
|
end
|
14
14
|
|
15
|
-
require 'rack
|
15
|
+
require 'rack/speling'
|
data/test/test_rack-speling.rb
CHANGED
@@ -1,27 +1,52 @@
|
|
1
1
|
require File.expand_path("../helper", __FILE__)
|
2
2
|
|
3
3
|
class SpelingTest < Test::Unit::TestCase
|
4
|
-
def sut
|
5
|
-
|
6
|
-
include Rack::Speling
|
7
|
-
end
|
8
|
-
app = lambda { |arg| return arg }
|
9
|
-
|
10
|
-
speling.new(app)
|
4
|
+
def sut(*args)
|
5
|
+
Rack::Speling.new(*args)
|
11
6
|
end
|
12
7
|
|
13
8
|
def env
|
14
9
|
{ 'PATH_INFO' => '/somepath', 'REQUEST_URI' => '/somepath' }
|
15
10
|
end
|
16
11
|
|
12
|
+
def status_app(status)
|
13
|
+
lambda { |env|
|
14
|
+
[status, env, '']
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def echo_app
|
19
|
+
lambda { |arg| return arg }
|
20
|
+
end
|
21
|
+
|
17
22
|
def test_downcasing_path_info
|
18
|
-
result = sut.call( env.merge('PATH_INFO' => '/SOMEPATH') )
|
23
|
+
result = sut(echo_app).call( env.merge('PATH_INFO' => '/SOMEPATH') )
|
19
24
|
|
20
25
|
assert_equal env, result
|
21
26
|
end
|
22
27
|
|
23
28
|
def test_downcasing_request_uri
|
24
|
-
result = sut.call( env.merge('REQUEST_URI' => '/SOMEPATH') )
|
29
|
+
result = sut(echo_app).call( env.merge('REQUEST_URI' => '/SOMEPATH') )
|
25
30
|
assert_equal env, result
|
26
31
|
end
|
32
|
+
|
33
|
+
def test_does_not_touch_200s
|
34
|
+
result = sut(status_app(200)).call(env)
|
35
|
+
assert_equal 200, result[0], result.inspect
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_does_accept_an_optional_lookup_object
|
39
|
+
assert_nothing_raised do
|
40
|
+
sut(echo_app)
|
41
|
+
sut(echo_app, :lookup => {})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_redirect_on_successful_lookup
|
46
|
+
result = sut(status_app(404), :lookup => {
|
47
|
+
'/somepath' => 'http://example.com/newpath'
|
48
|
+
}).call(env)
|
49
|
+
assert_equal 302, result[0]
|
50
|
+
assert_equal 'http://example.com/newpath', result[1]['Location']
|
51
|
+
end
|
27
52
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-speling
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Matthias Viehweger
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-09-
|
18
|
+
date: 2010-09-16 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -33,9 +33,11 @@ files:
|
|
33
33
|
- Gemfile
|
34
34
|
- README.txt
|
35
35
|
- Rakefile
|
36
|
-
- lib/rack
|
37
|
-
- lib/rack
|
36
|
+
- lib/rack/speling.rb
|
37
|
+
- lib/rack/speling/sp_dist.rb
|
38
|
+
- lib/rack/speling/version.rb
|
38
39
|
- rack-speling.gemspec
|
40
|
+
- test/all.rb
|
39
41
|
- test/helper.rb
|
40
42
|
- test/test_rack-speling.rb
|
41
43
|
has_rdoc: true
|
@@ -75,5 +77,6 @@ signing_key:
|
|
75
77
|
specification_version: 3
|
76
78
|
summary: Simple Speling corretor in Rack
|
77
79
|
test_files:
|
80
|
+
- test/all.rb
|
78
81
|
- test/helper.rb
|
79
82
|
- test/test_rack-speling.rb
|
data/lib/rack-speling.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
# vim:ft=ruby:fileencoding=utf-8
|
2
|
-
|
3
|
-
module Rack
|
4
|
-
module Speling
|
5
|
-
# remember the application as we need to call it later on
|
6
|
-
# (this is just a before-filter)
|
7
|
-
def initialize(app)
|
8
|
-
@app = app
|
9
|
-
end
|
10
|
-
|
11
|
-
# downcase PATH_INFO and REQUEST_URI
|
12
|
-
def call(env)
|
13
|
-
env['PATH_INFO'] = env['PATH_INFO'].downcase
|
14
|
-
env['REQUEST_URI'] = env['REQUEST_URI'].downcase
|
15
|
-
|
16
|
-
@app.call(env)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|