wouter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/wouter.rb +156 -0
- metadata +165 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a103da6e9f11d0e96881ccaf75062ef5a6a5322e78e3010300465645d5a9bd62
|
4
|
+
data.tar.gz: e10e000a61b9a304156429f1c22244ab6af4b456bb17d1960a901eb9c1579a4d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ae45cbb20ba4659e9ef46d44fdb9deafef6fb252ab17acdad3eef68a4a3f446113c2641e672e165d3b9e97cf32d8399932141f4db223a0bbcbfb8f0bcd9c6db
|
7
|
+
data.tar.gz: 95239729b7a893187eb60d126bbd75aab7901718c21e28b47053c491bea3b0eb613539618f2245b69b55cdb4a18a0f3155781179216d173c19f6cd47d2c680f4
|
data/lib/wouter.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler.setup(:default)
|
3
|
+
require "rack"
|
4
|
+
|
5
|
+
class Wouter
|
6
|
+
|
7
|
+
# Incoming HTTP Request Wrapper
|
8
|
+
class Request
|
9
|
+
attr_reader :params
|
10
|
+
|
11
|
+
def initialize(params:)
|
12
|
+
@params = params
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Outgoing HTTP Response Wrapper
|
17
|
+
class Response
|
18
|
+
attr_accessor :headers
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@headers = {'Content-Type' => 'text/html'}
|
22
|
+
@body = ""
|
23
|
+
@status = 200
|
24
|
+
end
|
25
|
+
|
26
|
+
def body(b)
|
27
|
+
@body = b
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def status(s)
|
32
|
+
@status = s
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def build_response
|
37
|
+
[@status, @headers, [@body]]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# HTTP Endpoint Helper class
|
42
|
+
class Endpoint
|
43
|
+
attr_accessor :request, :response
|
44
|
+
attr_reader :params
|
45
|
+
|
46
|
+
def initialize
|
47
|
+
@request = request
|
48
|
+
@response = response
|
49
|
+
end
|
50
|
+
|
51
|
+
def call(req, res)
|
52
|
+
@request = req
|
53
|
+
@params = req.params
|
54
|
+
@response = res
|
55
|
+
r = respond
|
56
|
+
@response.body r
|
57
|
+
end
|
58
|
+
|
59
|
+
def json(body)
|
60
|
+
@response.headers['Content-Type'] = 'application/json'
|
61
|
+
body
|
62
|
+
end
|
63
|
+
|
64
|
+
def status(code)
|
65
|
+
@response.status code
|
66
|
+
""
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
## Route Definitions
|
71
|
+
|
72
|
+
@@routes = []
|
73
|
+
|
74
|
+
## DSL
|
75
|
+
|
76
|
+
class <<self
|
77
|
+
%i[get post put delete].each do |m|
|
78
|
+
define_method(m) do |path, route_class|
|
79
|
+
@@routes.push({
|
80
|
+
method: m.to_s.upcase.to_sym,
|
81
|
+
path: path,
|
82
|
+
route_class: route_class
|
83
|
+
})
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
## Rack API
|
89
|
+
|
90
|
+
def self.call(env)
|
91
|
+
path = env["PATH_INFO"]
|
92
|
+
method = env["REQUEST_METHOD"].to_sym
|
93
|
+
|
94
|
+
route_params = {}
|
95
|
+
|
96
|
+
route = @@routes.find do |route|
|
97
|
+
if route[:method] == method
|
98
|
+
if route[:path].include?(":")
|
99
|
+
split_path = route[:path].split("/")
|
100
|
+
# Find all the named parameters in the route, drop the ":" so we have the names: ":id" => "id"
|
101
|
+
route_param_names = split_path.find_all { |s| s.size > 1 ? s[0] == ":" : false }.map { |s| s[1..-1] }
|
102
|
+
# Turn the route into a regex: "/hello/:name" => "\/hello\/(\w*)"
|
103
|
+
path_regex_string = split_path.map { |s| s[0] == ":" ? "(\\w*)" : s }.join("\/")
|
104
|
+
r = Regexp.new(path_regex_string)
|
105
|
+
if r.match?(path)
|
106
|
+
match_data = r.match(path)
|
107
|
+
# Match the match data with the named params, ex { "id" => 123 }
|
108
|
+
route_param_names.each_with_index do |n, i|
|
109
|
+
route_params[n] = match_data[i+1]
|
110
|
+
end
|
111
|
+
true
|
112
|
+
else
|
113
|
+
false
|
114
|
+
end
|
115
|
+
else
|
116
|
+
route[:path] == path
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
if route
|
122
|
+
params = generate_params(env["rack.input"].gets).merge(route_params)
|
123
|
+
|
124
|
+
request = Request.new(params: params)
|
125
|
+
response = Response.new
|
126
|
+
|
127
|
+
route_response = route[:route_class].new.call(request, response)
|
128
|
+
response route_response
|
129
|
+
else
|
130
|
+
response not_found
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
### Helpers
|
135
|
+
|
136
|
+
def self.not_found
|
137
|
+
resp = Response.new
|
138
|
+
resp.status 404
|
139
|
+
resp.body "Not Found"
|
140
|
+
end
|
141
|
+
|
142
|
+
# Query string comes in as "key=value&key=value" and we turn it into { "key" => "value", "key" => "value" }
|
143
|
+
def self.generate_params(params)
|
144
|
+
return {} if params.nil? || params.empty?
|
145
|
+
params_hash = {}
|
146
|
+
params.split("&").each do |param_pair|
|
147
|
+
key, value = param_pair.split("=")
|
148
|
+
params_hash[key] = value
|
149
|
+
end
|
150
|
+
params_hash
|
151
|
+
end
|
152
|
+
|
153
|
+
def self.response(route_response)
|
154
|
+
route_response.build_response
|
155
|
+
end
|
156
|
+
end
|
metadata
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wouter
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Peterson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-11-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rack
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.6
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 2.0.6
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rake
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '12.3'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 12.3.1
|
43
|
+
type: :development
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '12.3'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 12.3.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: rack-test
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.1'
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.1.0
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '1.1'
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.1.0
|
73
|
+
- !ruby/object:Gem::Dependency
|
74
|
+
name: minitest
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
76
|
+
requirements:
|
77
|
+
- - "~>"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '5.11'
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 5.11.3
|
83
|
+
type: :development
|
84
|
+
prerelease: false
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.11'
|
90
|
+
- - ">="
|
91
|
+
- !ruby/object:Gem::Version
|
92
|
+
version: 5.11.3
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: minitest-rg
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - "~>"
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: '5.2'
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: 5.2.0
|
103
|
+
type: :development
|
104
|
+
prerelease: false
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '5.2'
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: 5.2.0
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: m
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - "~>"
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '1.5'
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.5.1
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '1.5'
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: 1.5.1
|
133
|
+
description: Wouter is a modular web router built on Rack. I like explicitness. I
|
134
|
+
like modularity. Wouter aims to make both of those aspects simple.
|
135
|
+
email: robertpeterson@gmail.com
|
136
|
+
executables: []
|
137
|
+
extensions: []
|
138
|
+
extra_rdoc_files: []
|
139
|
+
files:
|
140
|
+
- lib/wouter.rb
|
141
|
+
homepage: https://github.com/rawburt/wouter
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
metadata: {}
|
145
|
+
post_install_message:
|
146
|
+
rdoc_options: []
|
147
|
+
require_paths:
|
148
|
+
- lib
|
149
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
requirements: []
|
160
|
+
rubyforge_project:
|
161
|
+
rubygems_version: 2.7.3
|
162
|
+
signing_key:
|
163
|
+
specification_version: 4
|
164
|
+
summary: Rack web router.
|
165
|
+
test_files: []
|