webfx 0.0.7 → 0.0.8
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/webfx.rb +104 -127
- metadata +5 -5
data/lib/webfx.rb
CHANGED
@@ -1,89 +1,7 @@
|
|
1
|
+
require 'zlib'
|
2
|
+
require 'stringio'
|
1
3
|
require 'json'
|
2
4
|
|
3
|
-
class Request
|
4
|
-
attr_reader :user, :params, :body, :path, :method
|
5
|
-
|
6
|
-
def initialize(env)
|
7
|
-
request = Rack::Request.new(env)
|
8
|
-
params = request.params
|
9
|
-
|
10
|
-
if params['_method']
|
11
|
-
method = params['_method']
|
12
|
-
else
|
13
|
-
method = request.request_method
|
14
|
-
end
|
15
|
-
|
16
|
-
@user = @@authenticate ? @@authenticate.call(params) : nil
|
17
|
-
@params = params
|
18
|
-
@body = params['file'] ? '' : (request.post? or request.put?) ? request.body.read : ''
|
19
|
-
@path = request.path
|
20
|
-
@method = method.downcase
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
|
25
|
-
class Response
|
26
|
-
attr_writer :status, :header
|
27
|
-
|
28
|
-
class DeferrableBody
|
29
|
-
include EM::Deferrable
|
30
|
-
|
31
|
-
def call(body)
|
32
|
-
body.each do |chunk|
|
33
|
-
@body_callback.call(chunk)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def each &blk
|
38
|
-
@body_callback = blk
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def initialize(env)
|
43
|
-
@env = env
|
44
|
-
@body = DeferrableBody.new
|
45
|
-
@status = nil
|
46
|
-
@header = nil
|
47
|
-
end
|
48
|
-
|
49
|
-
def fail(message)
|
50
|
-
@status = 500 if @status.nil?
|
51
|
-
@header = {'Content-Type' => 'text/plain'} if @header.nil?
|
52
|
-
@env['async.callback'].call [@status, @header, @body]
|
53
|
-
@body.call [message]
|
54
|
-
@body.fail
|
55
|
-
end
|
56
|
-
|
57
|
-
def succeed(body)
|
58
|
-
@status = 200 if @status.nil?
|
59
|
-
@header = {'Content-Type' => 'application/json'} if @header.nil?
|
60
|
-
@env['async.callback'].call [@status, @header, @body]
|
61
|
-
|
62
|
-
if @header['Content-Type'] == 'application/json' and
|
63
|
-
not ((body.kind_of? String) and (['{', '['].include? body.slice(0, 1)))
|
64
|
-
body = body.to_json
|
65
|
-
end
|
66
|
-
|
67
|
-
@body.call [body]
|
68
|
-
@body.succeed
|
69
|
-
end
|
70
|
-
|
71
|
-
def deleted
|
72
|
-
@status = 200 if @status.nil?
|
73
|
-
@header = {'Content-Type' => 'text/plain'} if @header.nil?
|
74
|
-
@env['async.callback'].call [@status, @header, @body]
|
75
|
-
@body.succeed
|
76
|
-
end
|
77
|
-
|
78
|
-
def updated
|
79
|
-
@status = 200 if @status.nil?
|
80
|
-
@header = {'Content-Type' => 'text/plain'} if @header.nil?
|
81
|
-
@env['async.callback'].call [@status, @header, @body]
|
82
|
-
@body.succeed
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
5
|
@@routes = {'get' => [], 'post' => [], 'put' => [], 'delete' => []}
|
88
6
|
@@authenticate = false
|
89
7
|
|
@@ -111,56 +29,115 @@ def authenticate(&fn)
|
|
111
29
|
@@authenticate = fn
|
112
30
|
end
|
113
31
|
|
32
|
+
class MyResult
|
33
|
+
attr_reader :env
|
34
|
+
|
35
|
+
def initialize(env)
|
36
|
+
@env = env
|
37
|
+
end
|
38
|
+
end
|
114
39
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
40
|
+
def gzip(data)
|
41
|
+
s = StringIO.new
|
42
|
+
gz = Zlib::GzipWriter.new(s, 0, nil)
|
43
|
+
gz.write data
|
44
|
+
gz.close
|
45
|
+
s.string
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
def index_html
|
50
|
+
@@index_html ||= gzip(File.read('public/index.html').gsub(/<!--(.|\s)*?-->/, ''))
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def run_app(env)
|
55
|
+
begin
|
56
|
+
request = Rack::Request.new(env)
|
124
57
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
58
|
+
def static(type, file)
|
59
|
+
[200, { 'Content-Type' => type, 'Cache-Control' => 'public, max-age=86400' }, File.read(file)]
|
60
|
+
end
|
61
|
+
|
62
|
+
if request.path == '/'
|
63
|
+
return [200, { 'Content-Type' => 'text/html', 'Content-Encoding' => 'gzip' }, index_html]
|
64
|
+
end
|
65
|
+
|
66
|
+
if request.path.match(/(.*).js$/)
|
67
|
+
return static('text/javascript', "public/#{$1}.js")
|
68
|
+
end
|
69
|
+
|
70
|
+
if request.path.match(/(.*).css$/)
|
71
|
+
return static('text/css', "public/#{$1}.css")
|
72
|
+
end
|
73
|
+
|
74
|
+
if request.path.match(/(images\/.*).png$/)
|
75
|
+
return static('image/png', "public/#{$1}.png")
|
76
|
+
end
|
77
|
+
|
78
|
+
if request.path.match(/(images\/.*).jpg$/)
|
79
|
+
return static('image/jpg', "public/#{$1}.jpg")
|
80
|
+
end
|
81
|
+
|
82
|
+
params = request.params
|
83
|
+
|
84
|
+
if request.post?
|
85
|
+
if not params['file']
|
86
|
+
body = request.body.read
|
87
|
+
params.merge!(JSON.parse(body)) if body != ''
|
137
88
|
end
|
89
|
+
end
|
90
|
+
|
91
|
+
force_method = params['_method']
|
92
|
+
if force_method
|
93
|
+
method = force_method
|
94
|
+
params.delete('_method')
|
95
|
+
else
|
96
|
+
method = request.request_method
|
97
|
+
end
|
98
|
+
method.downcase!
|
138
99
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
100
|
+
@@routes[method].each do |item|
|
101
|
+
if request.path[1..-1].match(item[:regexp])
|
102
|
+
me = @@authenticate ? @@authenticate.call(params) : nil
|
103
|
+
|
104
|
+
case $~.length
|
105
|
+
when 1 then result = item[:fn].call(params, me)
|
106
|
+
when 2 then result = item[:fn].call($1, params, me)
|
107
|
+
when 3 then result = item[:fn].call($1, $2, params, me)
|
108
|
+
when 4 then result = item[:fn].call($1, $2, $3, params, me)
|
109
|
+
when 5 then result = item[:fn].call($1, $2, $3, $4, params, me)
|
110
|
+
else result = item[:fn].call($~, params, me)
|
147
111
|
end
|
148
|
-
|
149
|
-
if
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
112
|
+
|
113
|
+
return result.env if result.kind_of? MyResult
|
114
|
+
|
115
|
+
case method
|
116
|
+
when 'get', 'post'
|
117
|
+
if result.kind_of? String and ['{', '['].include? result.slice(0, 1)
|
118
|
+
json = result
|
119
|
+
else
|
120
|
+
json = result.to_json
|
121
|
+
end
|
122
|
+
return [200, {'Content-Type' => 'application/json', 'Content-Encoding' => 'gzip'}, gzip(json)]
|
123
|
+
else
|
124
|
+
return [200, {'Content-Type' => 'application/json', 'Content-Encoding' => 'gzip'}, gzip({:result => :success}.to_json)]
|
160
125
|
end
|
161
126
|
end
|
162
127
|
end
|
128
|
+
[404, {'Content-Type' => 'text/plain'}, 'Not found.']
|
129
|
+
|
130
|
+
rescue => e
|
131
|
+
result = {:message => e.message, :callstack => e.backtrace.join("\n")}
|
132
|
+
[500, {'Content-Type' => 'text/plain' }, e.message]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
163
136
|
|
164
|
-
|
165
|
-
|
137
|
+
module WebFx
|
138
|
+
class Application
|
139
|
+
def self.call(env)
|
140
|
+
run_app(env)
|
141
|
+
end
|
142
|
+
end
|
166
143
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: webfx
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 8
|
10
|
+
version: 0.0.8
|
11
11
|
platform: ruby
|
12
12
|
authors: []
|
13
13
|
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-02 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -62,6 +62,6 @@ rubyforge_project:
|
|
62
62
|
rubygems_version: 1.3.7
|
63
63
|
signing_key:
|
64
64
|
specification_version: 3
|
65
|
-
summary:
|
65
|
+
summary: Minimal, RESTful, json, sinatra-inspired framework.
|
66
66
|
test_files: []
|
67
67
|
|