rack-speling 0.0.1 → 0.0.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.
- 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
|