rack-noncache 0.0.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.pryrc +6 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/README.md +36 -52
- data/Rakefile +16 -1
- data/features/cache_control.feature +22 -0
- data/features/step_definitions/steps.rb +46 -0
- data/features/support/continous_integration.rb +47 -0
- data/features/support/coverage.rb +18 -0
- data/features/support/env.rb +9 -0
- data/features/support/helpers.rb +13 -0
- data/features/support/web_app/application.rb +70 -0
- data/features/support/web_app/config_blacklist.ru +13 -0
- data/features/support/web_app/config_whitelist.ru +13 -0
- data/features/support/web_app/public/app/collections/todos.js +17 -0
- data/features/support/web_app/public/app/config.js +18 -0
- data/features/support/web_app/public/app/main.js +21 -0
- data/features/support/web_app/public/app/models/todo.js +33 -0
- data/features/support/web_app/public/app/templates/todo-add.html +3 -0
- data/features/support/web_app/public/app/templates/todo-editor.html +1 -0
- data/features/support/web_app/public/app/templates/todo-item.html +2 -0
- data/features/support/web_app/public/app/templates/todo-list-empty.html +1 -0
- data/features/support/web_app/public/app/templates/todo-stats.html +4 -0
- data/features/support/web_app/public/app/views/stats.js +26 -0
- data/features/support/web_app/public/app/views/todo.js +55 -0
- data/features/support/web_app/public/app/views/todoadd.js +48 -0
- data/features/support/web_app/public/app/views/todoedit.js +70 -0
- data/features/support/web_app/public/app/views/todolist.js +69 -0
- data/features/support/web_app/public/assets/css/bootstrap.css +3990 -0
- data/features/support/web_app/public/assets/css/style.css +82 -0
- data/features/support/web_app/public/assets/js/libs/backbone.js +1428 -0
- data/features/support/web_app/public/assets/js/libs/jquery-1.7.2.js +9404 -0
- data/features/support/web_app/public/assets/js/libs/require.js +2053 -0
- data/features/support/web_app/public/assets/js/libs/underscore.js +1008 -0
- data/features/support/web_app/public/assets/js/plugins/text.js +288 -0
- data/features/support/web_app/public/test/SpecRunner.html +42 -0
- data/features/support/web_app/public/test/lib/jasmine-1.2.0.rc3/MIT.LICENSE +20 -0
- data/features/support/web_app/public/test/lib/jasmine-1.2.0.rc3/jasmine-html.js +616 -0
- data/features/support/web_app/public/test/lib/jasmine-1.2.0.rc3/jasmine.css +81 -0
- data/features/support/web_app/public/test/lib/jasmine-1.2.0.rc3/jasmine.js +2530 -0
- data/features/support/web_app/public/test/lib/jasmine-jquery.js +306 -0
- data/features/support/web_app/public/test/spec/models/todo.coffee +37 -0
- data/features/support/web_app/public/test/spec/models/todo.js +48 -0
- data/features/support/web_app/public/test/spec/spec_helper.coffee +20 -0
- data/features/support/web_app/public/test/spec/spec_helper.js +17 -0
- data/features/support/web_app/public/test/spec/views/stats.coffee +9 -0
- data/features/support/web_app/public/test/spec/views/stats.js +13 -0
- data/features/support/web_app/public/test/spec/views/todo.coffee +22 -0
- data/features/support/web_app/public/test/spec/views/todo.js +26 -0
- data/features/support/web_app/public/test/spec/views/todoadd.coffee +22 -0
- data/features/support/web_app/public/test/spec/views/todoadd.js +29 -0
- data/features/support/web_app/public/test/spec/views/todoedit.coffee +59 -0
- data/features/support/web_app/public/test/spec/views/todoedit.js +72 -0
- data/features/support/web_app/public/test/spec/views/todolist.coffee +28 -0
- data/features/support/web_app/public/test/spec/views/todolist.js +39 -0
- data/features/support/web_app/views/details.erb +14 -0
- data/features/support/web_app/views/index.erb +43 -0
- data/lib/rack/noncache.rb +5 -7
- data/lib/rack/noncache/engine.rb +10 -26
- data/lib/rack/noncache/filters.rb +75 -0
- data/lib/rack/noncache/version.rb +1 -1
- data/rack-noncache.gemspec +32 -10
- metadata +382 -7
@@ -0,0 +1,22 @@
|
|
1
|
+
define ["views/todo"], (TodoView) ->
|
2
|
+
describe "TodoView", ->
|
3
|
+
beforeEach ->
|
4
|
+
@view = new TodoView(@viewOptions)
|
5
|
+
@view.render()
|
6
|
+
|
7
|
+
it "should render itself", ->
|
8
|
+
expect(@view.$el.text()).toMatch /new todo/
|
9
|
+
|
10
|
+
it "should remove itself when clicking on 'done'", ->
|
11
|
+
spyOn(@view.$el, "remove")
|
12
|
+
@view.$(".btn").click()
|
13
|
+
expect(@view.$el.remove).toHaveBeenCalled()
|
14
|
+
|
15
|
+
it "should update itself when the text of the model changes", ->
|
16
|
+
@view.model.setText "changed"
|
17
|
+
expect(@view.$el.text()).toMatch /changed/
|
18
|
+
|
19
|
+
it "should enter edit mode when dbl clicking the element", ->
|
20
|
+
spyOn(@view.editor, "attach")
|
21
|
+
@view.$el.click()
|
22
|
+
expect(@view.editor.attach).toHaveBeenCalled()
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
define(["views/todo"], function(TodoView) {
|
3
|
+
return describe("TodoView", function() {
|
4
|
+
beforeEach(function() {
|
5
|
+
this.view = new TodoView(this.viewOptions);
|
6
|
+
return this.view.render();
|
7
|
+
});
|
8
|
+
it("should render itself", function() {
|
9
|
+
return expect(this.view.$el.text()).toMatch(/new todo/);
|
10
|
+
});
|
11
|
+
it("should remove itself when clicking on 'done'", function() {
|
12
|
+
spyOn(this.view.$el, "remove");
|
13
|
+
this.view.$(".btn").click();
|
14
|
+
return expect(this.view.$el.remove).toHaveBeenCalled();
|
15
|
+
});
|
16
|
+
it("should update itself when the text of the model changes", function() {
|
17
|
+
this.view.model.setText("changed");
|
18
|
+
return expect(this.view.$el.text()).toMatch(/changed/);
|
19
|
+
});
|
20
|
+
return it("should enter edit mode when dbl clicking the element", function() {
|
21
|
+
spyOn(this.view.editor, "attach");
|
22
|
+
this.view.$el.click();
|
23
|
+
return expect(this.view.editor.attach).toHaveBeenCalled();
|
24
|
+
});
|
25
|
+
});
|
26
|
+
});
|
@@ -0,0 +1,22 @@
|
|
1
|
+
define ["views/todoadd"], (TodoAddView) ->
|
2
|
+
describe "TodoAddView", ->
|
3
|
+
beforeEach ->
|
4
|
+
@view = new TodoAddView(@viewOptions)
|
5
|
+
@view.render()
|
6
|
+
|
7
|
+
it "should create a new todo on add button click", ->
|
8
|
+
spyOn(@view.collection, "create")
|
9
|
+
@view.$(".btn").click()
|
10
|
+
expect(@view.collection.create).toHaveBeenCalled()
|
11
|
+
|
12
|
+
it "should create a new todo on pressing the enter key", ->
|
13
|
+
spyOn(@view.collection, "create")
|
14
|
+
keyPress = jQuery.Event("keypress", {keyCode:13})
|
15
|
+
@view.$("input").trigger(keyPress)
|
16
|
+
expect(@view.collection.create).toHaveBeenCalled()
|
17
|
+
|
18
|
+
it "should clear the input after creating a todo", ->
|
19
|
+
spyOn(@view, "getValue").andReturn("text")
|
20
|
+
spyOn(@view, "clearInput")
|
21
|
+
@view.add()
|
22
|
+
expect(@view.clearInput).toHaveBeenCalled()
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
define(["views/todoadd"], function(TodoAddView) {
|
3
|
+
return describe("TodoAddView", function() {
|
4
|
+
beforeEach(function() {
|
5
|
+
this.view = new TodoAddView(this.viewOptions);
|
6
|
+
return this.view.render();
|
7
|
+
});
|
8
|
+
it("should create a new todo on add button click", function() {
|
9
|
+
spyOn(this.view.collection, "create");
|
10
|
+
this.view.$(".btn").click();
|
11
|
+
return expect(this.view.collection.create).toHaveBeenCalled();
|
12
|
+
});
|
13
|
+
it("should create a new todo on pressing the enter key", function() {
|
14
|
+
var keyPress;
|
15
|
+
spyOn(this.view.collection, "create");
|
16
|
+
keyPress = jQuery.Event("keypress", {
|
17
|
+
keyCode: 13
|
18
|
+
});
|
19
|
+
this.view.$("input").trigger(keyPress);
|
20
|
+
return expect(this.view.collection.create).toHaveBeenCalled();
|
21
|
+
});
|
22
|
+
return it("should clear the input after creating a todo", function() {
|
23
|
+
spyOn(this.view, "getValue").andReturn("text");
|
24
|
+
spyOn(this.view, "clearInput");
|
25
|
+
this.view.add();
|
26
|
+
return expect(this.view.clearInput).toHaveBeenCalled();
|
27
|
+
});
|
28
|
+
});
|
29
|
+
});
|
@@ -0,0 +1,59 @@
|
|
1
|
+
define ["views/todoedit"], (TodoEditor) ->
|
2
|
+
describe "TodoEditor", ->
|
3
|
+
beforeEach ->
|
4
|
+
@view = new TodoEditor
|
5
|
+
@$element = $("<div><div id='todo-item'></div><div>")
|
6
|
+
setFixtures(@$element)
|
7
|
+
|
8
|
+
describe "attaching", ->
|
9
|
+
it "should hide the element", ->
|
10
|
+
spyOn(@$element, "hide")
|
11
|
+
@view.attach(@$element, @todo)
|
12
|
+
expect(@$element.hide).toHaveBeenCalled()
|
13
|
+
|
14
|
+
it "should set the value of the input to the models text", ->
|
15
|
+
@view.attach(@$element, @todo)
|
16
|
+
expect(@view.$input.val()).toMatch /new todo/
|
17
|
+
|
18
|
+
it "should focus the input", ->
|
19
|
+
@view.attach(@$element, @todo)
|
20
|
+
expect(@view.$input).toBeFocused()
|
21
|
+
|
22
|
+
describe "detaching", ->
|
23
|
+
beforeEach ->
|
24
|
+
@view.attach(@$element, @todo)
|
25
|
+
|
26
|
+
it "should show the hidden element again", ->
|
27
|
+
@view.detach()
|
28
|
+
expect(@$element).toBeVisible()
|
29
|
+
|
30
|
+
it "should detach the editor element", ->
|
31
|
+
@view.detach()
|
32
|
+
expect(@view.$el.parent().length).toBe(0)
|
33
|
+
|
34
|
+
describe "when attached", ->
|
35
|
+
beforeEach ->
|
36
|
+
@view.attach(@$element, @todo)
|
37
|
+
spyOn(@todo, "setText").andCallThrough()
|
38
|
+
|
39
|
+
it "should save and detach on blur", ->
|
40
|
+
@view.$input.blur()
|
41
|
+
expect(@todo.setText).toHaveBeenCalled()
|
42
|
+
expect(@view.attached).toBeFalsy()
|
43
|
+
|
44
|
+
it "should just detach on pressing ESC", ->
|
45
|
+
keyUp = jQuery.Event("keyup", {keyCode: 27})
|
46
|
+
@view.$input.trigger(keyUp)
|
47
|
+
expect(@todo.setText).not.toHaveBeenCalled()
|
48
|
+
expect(@view.attached).toBeFalsy()
|
49
|
+
|
50
|
+
it "should save and detach on pressing ENTER", ->
|
51
|
+
keyUp = jQuery.Event("keyup", {keyCode: 13})
|
52
|
+
@view.$input.trigger(keyUp)
|
53
|
+
expect(@todo.setText).toHaveBeenCalled()
|
54
|
+
expect(@view.attached).toBeFalsy()
|
55
|
+
|
56
|
+
it "should not detach when text is empty", ->
|
57
|
+
@view.$input.val("")
|
58
|
+
@view.save()
|
59
|
+
expect(@view.attached).toBeTruthy()
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
define(["views/todoedit"], function(TodoEditor) {
|
3
|
+
return describe("TodoEditor", function() {
|
4
|
+
beforeEach(function() {
|
5
|
+
this.view = new TodoEditor;
|
6
|
+
this.$element = $("<div><div id='todo-item'></div><div>");
|
7
|
+
return setFixtures(this.$element);
|
8
|
+
});
|
9
|
+
describe("attaching", function() {
|
10
|
+
it("should hide the element", function() {
|
11
|
+
spyOn(this.$element, "hide");
|
12
|
+
this.view.attach(this.$element, this.todo);
|
13
|
+
return expect(this.$element.hide).toHaveBeenCalled();
|
14
|
+
});
|
15
|
+
it("should set the value of the input to the models text", function() {
|
16
|
+
this.view.attach(this.$element, this.todo);
|
17
|
+
return expect(this.view.$input.val()).toMatch(/new todo/);
|
18
|
+
});
|
19
|
+
return it("should focus the input", function() {
|
20
|
+
this.view.attach(this.$element, this.todo);
|
21
|
+
return expect(this.view.$input).toBeFocused();
|
22
|
+
});
|
23
|
+
});
|
24
|
+
describe("detaching", function() {
|
25
|
+
beforeEach(function() {
|
26
|
+
return this.view.attach(this.$element, this.todo);
|
27
|
+
});
|
28
|
+
it("should show the hidden element again", function() {
|
29
|
+
this.view.detach();
|
30
|
+
return expect(this.$element).toBeVisible();
|
31
|
+
});
|
32
|
+
return it("should detach the editor element", function() {
|
33
|
+
this.view.detach();
|
34
|
+
return expect(this.view.$el.parent().length).toBe(0);
|
35
|
+
});
|
36
|
+
});
|
37
|
+
return describe("when attached", function() {
|
38
|
+
beforeEach(function() {
|
39
|
+
this.view.attach(this.$element, this.todo);
|
40
|
+
return spyOn(this.todo, "setText").andCallThrough();
|
41
|
+
});
|
42
|
+
it("should save and detach on blur", function() {
|
43
|
+
this.view.$input.blur();
|
44
|
+
expect(this.todo.setText).toHaveBeenCalled();
|
45
|
+
return expect(this.view.attached).toBeFalsy();
|
46
|
+
});
|
47
|
+
it("should just detach on pressing ESC", function() {
|
48
|
+
var keyUp;
|
49
|
+
keyUp = jQuery.Event("keyup", {
|
50
|
+
keyCode: 27
|
51
|
+
});
|
52
|
+
this.view.$input.trigger(keyUp);
|
53
|
+
expect(this.todo.setText).not.toHaveBeenCalled();
|
54
|
+
return expect(this.view.attached).toBeFalsy();
|
55
|
+
});
|
56
|
+
it("should save and detach on pressing ENTER", function() {
|
57
|
+
var keyUp;
|
58
|
+
keyUp = jQuery.Event("keyup", {
|
59
|
+
keyCode: 13
|
60
|
+
});
|
61
|
+
this.view.$input.trigger(keyUp);
|
62
|
+
expect(this.todo.setText).toHaveBeenCalled();
|
63
|
+
return expect(this.view.attached).toBeFalsy();
|
64
|
+
});
|
65
|
+
return it("should not detach when text is empty", function() {
|
66
|
+
this.view.$input.val("");
|
67
|
+
this.view.save();
|
68
|
+
return expect(this.view.attached).toBeTruthy();
|
69
|
+
});
|
70
|
+
});
|
71
|
+
});
|
72
|
+
});
|
@@ -0,0 +1,28 @@
|
|
1
|
+
define ["views/todolist", "models/todo"], (TodoListView, Todo) ->
|
2
|
+
describe "TodoListView", ->
|
3
|
+
beforeEach ->
|
4
|
+
@view = new TodoListView(@viewOptions)
|
5
|
+
$element = sandbox(id: "todo-list")
|
6
|
+
$element.append(@view.render().el)
|
7
|
+
|
8
|
+
it "should append a new item on the 'add' event", ->
|
9
|
+
@view.collection.trigger("add", new Todo)
|
10
|
+
expect(@view.$el.children().length).toEqual 1
|
11
|
+
|
12
|
+
# test if new item has fade-in state
|
13
|
+
expect(@view.$el.children()[0]).toHaveClass("new transition-bg")
|
14
|
+
|
15
|
+
it "should append all undone items on the 'reset' event", ->
|
16
|
+
@view.collection.add([new Todo, new Todo, new Todo(done:true)], silent: true)
|
17
|
+
@view.collection.trigger("reset", @view.collection)
|
18
|
+
expect(@view.$el.children().length).toEqual 2
|
19
|
+
|
20
|
+
it "should show a message instead of the list when no more items are remaining", ->
|
21
|
+
@view.collection.reset()
|
22
|
+
expect(@view.$el.parent().length).toEqual 0
|
23
|
+
expect(@view.$emptyList.parent().length).toEqual 1
|
24
|
+
|
25
|
+
it "should hide the empty message before a new item is added", ->
|
26
|
+
@view.collection.reset()
|
27
|
+
@view.collection.add(@todo)
|
28
|
+
expect(@view.$emptyList.parent().length).toEqual 0
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
define(["views/todolist", "models/todo"], function(TodoListView, Todo) {
|
3
|
+
return describe("TodoListView", function() {
|
4
|
+
beforeEach(function() {
|
5
|
+
var $element;
|
6
|
+
this.view = new TodoListView(this.viewOptions);
|
7
|
+
$element = sandbox({
|
8
|
+
id: "todo-list"
|
9
|
+
});
|
10
|
+
return $element.append(this.view.render().el);
|
11
|
+
});
|
12
|
+
it("should append a new item on the 'add' event", function() {
|
13
|
+
this.view.collection.trigger("add", new Todo);
|
14
|
+
expect(this.view.$el.children().length).toEqual(1);
|
15
|
+
return expect(this.view.$el.children()[0]).toHaveClass("new transition-bg");
|
16
|
+
});
|
17
|
+
it("should append all undone items on the 'reset' event", function() {
|
18
|
+
this.view.collection.add([
|
19
|
+
new Todo, new Todo, new Todo({
|
20
|
+
done: true
|
21
|
+
})
|
22
|
+
], {
|
23
|
+
silent: true
|
24
|
+
});
|
25
|
+
this.view.collection.trigger("reset", this.view.collection);
|
26
|
+
return expect(this.view.$el.children().length).toEqual(2);
|
27
|
+
});
|
28
|
+
it("should show a message instead of the list when no more items are remaining", function() {
|
29
|
+
this.view.collection.reset();
|
30
|
+
expect(this.view.$el.parent().length).toEqual(0);
|
31
|
+
return expect(this.view.$emptyList.parent().length).toEqual(1);
|
32
|
+
});
|
33
|
+
return it("should hide the empty message before a new item is added", function() {
|
34
|
+
this.view.collection.reset();
|
35
|
+
this.view.collection.add(this.todo);
|
36
|
+
return expect(this.view.$emptyList.parent().length).toEqual(0);
|
37
|
+
});
|
38
|
+
});
|
39
|
+
});
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<!doctype html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<title>Todos</title>
|
6
|
+
<link href="assets/css/bootstrap.css" rel="stylesheet">
|
7
|
+
<link href="assets/css/style.css" rel="stylesheet">
|
8
|
+
<script data-main="app/config" src="assets/js/libs/require.js"></script>
|
9
|
+
<script>
|
10
|
+
// define the bootstrap module inside index.erb so we can easily inject the default collection
|
11
|
+
define("bootstrap", [], function() {
|
12
|
+
return function(todoList) {
|
13
|
+
todoList.reset(<%= @todos.to_json %>);
|
14
|
+
};
|
15
|
+
});
|
16
|
+
|
17
|
+
// require main to kickstart the app
|
18
|
+
require(["main"]);
|
19
|
+
</script>
|
20
|
+
</head>
|
21
|
+
<body>
|
22
|
+
<div class="shell container-fluid">
|
23
|
+
<div class="page-header">
|
24
|
+
<h1>Todos</h1>
|
25
|
+
</div>
|
26
|
+
<div id="todo-container" class="hidden transition-opacity row-fluid">
|
27
|
+
<div class="span2">
|
28
|
+
<div id="todo-stats"></div>
|
29
|
+
</div>
|
30
|
+
|
31
|
+
<div class="span10">
|
32
|
+
<div class="row">
|
33
|
+
<div class="span8">
|
34
|
+
<div id="todo-add"></div>
|
35
|
+
<div id="todo-list"></div>
|
36
|
+
</div>
|
37
|
+
</div>
|
38
|
+
</div>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
<a href='/details'>Show details</a>
|
42
|
+
</body>
|
43
|
+
</html>
|
data/lib/rack/noncache.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'rack'
|
2
|
+
require 'rack/noncache/version'
|
3
|
+
require 'rack/noncache/engine'
|
4
4
|
|
5
5
|
module Rack
|
6
6
|
module NonCache
|
7
|
-
|
8
|
-
|
9
|
-
Engine.new(backend, options, &b)
|
7
|
+
def self.new(backend, opts = {}, &b)
|
8
|
+
Engine.new(backend, opts, &b)
|
10
9
|
end
|
11
|
-
|
12
10
|
end
|
13
11
|
end
|
data/lib/rack/noncache/engine.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
require_relative 'filters'
|
2
|
+
|
1
3
|
module Rack
|
2
4
|
module NonCache
|
3
|
-
|
4
5
|
class Engine
|
5
6
|
attr_accessor :whitelist, :blacklist
|
6
7
|
|
@@ -15,33 +16,18 @@ module Rack
|
|
15
16
|
# execute the request using our backend
|
16
17
|
status, headers, response = @backend.call(env)
|
17
18
|
|
18
|
-
|
19
|
-
|
20
|
-
headers['HTTP_CACHE_CONTROL'] =
|
21
|
-
'no-cache, max-age=0, must-revalidate, no-store, private, '
|
22
|
-
|
23
|
-
# Set standard HTTP/1.0 no-cache header.
|
24
|
-
headers['HTTP_CACHE_CONTROL'] +=
|
25
|
-
'max-stale=0, post-check=0, pre-check=0, ' +
|
26
|
-
'no-cache=\"Set-Cookie, Set-Cookie2\"'
|
27
|
-
|
28
|
-
# Set standard HTTP/1.1 no-cache header.
|
29
|
-
headers['HTTP_PRAGMA'] = 'no-cache'
|
30
|
-
|
31
|
-
# Set to expire far in the past. Prevents caching at the proxy server
|
32
|
-
headers['HTTP_EXPIRES'] = Time.now.httpdate
|
33
|
-
|
34
|
-
# Deprecated header
|
35
|
-
headers['HTTP_KEEP_ALIVE'] = 'timeout=3, max=993'
|
36
|
-
|
37
|
-
headers['X-Content-Type-Options'] = 'nosniff'
|
38
|
-
end
|
39
|
-
|
19
|
+
uri = env['REQUEST_URI']
|
20
|
+
filters.each { |filter| filter.apply(headers) } if target_path? uri
|
40
21
|
[status, headers, response]
|
41
22
|
end
|
42
23
|
|
43
24
|
private
|
44
25
|
|
26
|
+
def filters
|
27
|
+
[Http10Filter, Http11Filter, ProxyFilter, SecurityFilter,
|
28
|
+
DeprecatedFilter]
|
29
|
+
end
|
30
|
+
|
45
31
|
def target_path?(uri)
|
46
32
|
if @whitelist
|
47
33
|
return match(@whitelist, uri)
|
@@ -55,11 +41,9 @@ module Rack
|
|
55
41
|
def match(list, uri)
|
56
42
|
list.index do |path|
|
57
43
|
(path.class.eql?(String) && path.eql?(uri)) ||
|
58
|
-
|
44
|
+
(path.class.eql?(Regexp) && path.match(uri))
|
59
45
|
end
|
60
46
|
end
|
61
|
-
|
62
47
|
end
|
63
|
-
|
64
48
|
end
|
65
49
|
end
|