amber-kit 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b2b0cde2d48a5f894ed730b36260d428de273da
4
+ data.tar.gz: df73ca4d62fb83e44fde411594a1d451a3448dbe
5
+ SHA512:
6
+ metadata.gz: d0e02a5aa95e3fbfd6d2cf492fc333b9673a20c565e16452a99b711c3943343ac03f30279ef4bc65b30f2aa21131264bb602136d92afc858380f36f48d627d5c
7
+ data.tar.gz: b2c3db8bcb7203822e8f9604a7f288a35c7a082fb825372128ad651b8718d92e0eb8be1180d3ca1d79c56d2c4734ba779c59fd739c696fe04e699b432c20fb8f
data/Rakefile ADDED
File without changes
data/amber.gemspec ADDED
@@ -0,0 +1,49 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "amber-kit"
3
+ s.version = "0.0.1"
4
+ s.authors = ["Jakit"]
5
+ s.date = "2017-06-03"
6
+ s.summary = "A glitter network toolkit"
7
+ s.description = "Useful network toolkit for create your application"
8
+ s.email = "jakit_liang@outlook.com"
9
+ s.files = [
10
+ "Rakefile",
11
+ "amber.gemspec",
12
+ "bin/amber",
13
+ "lib/amber.rb",
14
+ "lib/amber/controller.rb",
15
+ "lib/amber/data.rb",
16
+ "lib/amber/data/array_data.rb",
17
+ "lib/amber/data/date_data.rb",
18
+ "lib/amber/data/float_data.rb",
19
+ "lib/amber/data/integer_data.rb",
20
+ "lib/amber/data/string_data.rb",
21
+ "lib/amber/data_delegate.rb",
22
+ "lib/amber/http.rb",
23
+ "lib/amber/http/request.rb",
24
+ "lib/amber/http/response.rb",
25
+ "lib/amber/model.rb",
26
+ "lib/amber/route.rb",
27
+ "lib/amber/route_path.rb",
28
+ "lib/amber/server.rb",
29
+ "lib/amber/storage.rb",
30
+ "lib/amber/storage/json.rb",
31
+ "lib/amber/storage/remote_json.rb",
32
+ "lib/amber/switch.rb",
33
+ "lib/amber/switch/content.rb",
34
+ "lib/amber/switch/content/form_data.rb",
35
+ "lib/amber/switch/content/json.rb",
36
+ "lib/amber/switch/content/text.rb",
37
+ "lib/amber/switch/content_delegate.rb",
38
+ "lib/amber/switch/request.rb",
39
+ "lib/amber/switch/request/get.rb",
40
+ "lib/amber/switch/request/post.rb",
41
+ "lib/amber/switch/response.rb",
42
+ "lib/amber/view.rb",
43
+ "lib/amber/view/json.rb"
44
+ ]
45
+ s.executables << 'amber'
46
+ s.require_paths = ["lib"]
47
+ s.homepage = "http://pingz.org.cn/amber"
48
+ s.license = "MIT"
49
+ end
data/bin/amber ADDED
@@ -0,0 +1,55 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "amber"
4
+
5
+ run_operation = ARGV[0] ? ARGV[0] : "run"
6
+ run_parameter = ARGV[1] ? ARGV[0] : nil
7
+
8
+ current_path = Dir.pwd
9
+
10
+ # Add controller path if exist
11
+ controller_path = current_path + '/controller'
12
+
13
+ if File.exist? controller_path
14
+ $LOAD_PATH << controller_path
15
+ end
16
+
17
+ # Add model path if exist
18
+ model_path = current_path + '/model'
19
+
20
+ if File.exist? model_path
21
+ $LOAD_PATH << model_path
22
+ end
23
+
24
+ # Add library path if exist
25
+ library_path = current_path + '/library'
26
+
27
+ if File.exist? library_path
28
+ $LOAD_PATH << library_path
29
+ end
30
+
31
+ # Add view path if exist
32
+ view_path = current_path + '/view'
33
+
34
+ if File.exist? view_path
35
+ $LOAD_PATH << view_path
36
+ end
37
+
38
+ if run_operation
39
+ case run_operation
40
+ when /\w+.rb/
41
+ if File.exist? run_operation
42
+ if run_operation.slice(0, 1) == '/'
43
+ require run_operation
44
+ else
45
+ require_relative current_path + '/' + run_operation
46
+ end
47
+ end
48
+ when "run"
49
+ amber_instance = Amber.new
50
+ amber_instance.run
51
+ else
52
+ amber_instance = Amber.new
53
+ amber_instance.run
54
+ end
55
+ end
@@ -0,0 +1,5 @@
1
+ class Amber::Controller
2
+ def main
3
+ "Hello World"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ class Amber::Data::ArrayData < Amber::Data
2
+ include Amber::DataDelegate
3
+
4
+ def initialize(value = [])
5
+ @delegate = self
6
+
7
+ self.assign(value)
8
+ end
9
+
10
+ def assign(value)
11
+ if value.is_a? Array
12
+ @value = value
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class Amber::Data::DateData < Amber::Data
2
+ include Amber::DataDelegate
3
+
4
+ def initialize(value = Time.new)
5
+ @delegate = self
6
+
7
+ self.assign(value)
8
+ end
9
+
10
+ def assign(value)
11
+ if (value.is_a?(Integer)) || (value.is_a?(Float))
12
+ @value = Time.at(value)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ class Amber::Data::FloatData < Amber::Data
2
+ include Amber::DataDelegate
3
+
4
+ def initialize(value = 0.0)
5
+ @delegate = self
6
+
7
+ self.assign(value)
8
+ end
9
+
10
+ def assign(value)
11
+ @value = value.to_f
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class Amber::Data::IntegerData < Amber::Data
2
+ include Amber::DataDelegate
3
+
4
+ def initialize(value = 0)
5
+ @delegate = self
6
+
7
+ self.assign(value)
8
+ end
9
+
10
+ def assign(value)
11
+ @value = value.to_i
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ class Amber::Data::StringData < Amber::Data
2
+ include Amber::DataDelegate
3
+
4
+ def initialize(value = '')
5
+ @delegate = self
6
+
7
+ self.assign(value)
8
+ end
9
+
10
+ def assign(value)
11
+ @value = value.to_s
12
+ end
13
+ end
data/lib/amber/data.rb ADDED
@@ -0,0 +1,14 @@
1
+ class Amber::Data
2
+ def initialize
3
+ @value = nil
4
+ @delegate = nil
5
+ end
6
+
7
+ def value
8
+ @delegate.fetch if @delegate.class.include?(Amber::DataDelegate)
9
+ end
10
+
11
+ def value=(value)
12
+ @delegate.assign(value) if @delegate.class.include?(Amber::DataDelegate)
13
+ end
14
+ end
@@ -0,0 +1,9 @@
1
+ module Amber::DataDelegate
2
+ def assign(value)
3
+ @value = value
4
+ end
5
+
6
+ def fetch
7
+ @value
8
+ end
9
+ end
@@ -0,0 +1,229 @@
1
+ class Amber::Http::Request < Amber::Http
2
+ attr_reader :method, :url, :query, :protocol, :body
3
+
4
+ GET = "GET"
5
+ POST = "POST"
6
+ PUT = "PUT"
7
+ DELETE = "DELETE"
8
+
9
+ def initialize(socket)
10
+ super
11
+
12
+ @url = ""
13
+ @query = {}
14
+ @body = {}
15
+ end
16
+
17
+ def receive
18
+ unless self.receive_request
19
+ STDERR.puts "Bad request"
20
+ return false
21
+ end
22
+
23
+ self.receive_header
24
+
25
+ # p @header
26
+
27
+ if @header.has_key?("Content-Length")
28
+ content_length = @header["Content-Length"].to_i
29
+
30
+ if content_length > 0
31
+ self.receive_body(content_length)
32
+ end
33
+ end
34
+
35
+ # p @body_raw_data
36
+
37
+ # p @body
38
+
39
+ return true
40
+ end
41
+
42
+ def receive_request
43
+ last_token = ""
44
+ data = ""
45
+
46
+ Timeout::timeout(30) {
47
+ while buffer = @socket.recv_nonblock(1)
48
+ if last_token == "\r" && buffer == "\n"
49
+ break
50
+ end
51
+
52
+ data << buffer
53
+ last_token = buffer
54
+ end
55
+ }
56
+
57
+ self.parse_request(data)
58
+ end
59
+
60
+ def parse_request(data)
61
+ request_info = data.split(' ')
62
+
63
+ if request_info.length == 3
64
+ case request_info[0]
65
+ when GET
66
+ @method = GET
67
+ when POST
68
+ @method = POST
69
+ when PUT
70
+ @method = PUT
71
+ when DELETE
72
+ @method = DELETE
73
+ else
74
+ return false
75
+ end
76
+
77
+ self.parse_url request_info[1]
78
+ @protocol = request_info[2]
79
+ end
80
+
81
+ return true
82
+ end
83
+
84
+ def parse_url(url)
85
+ if url.include? "?"
86
+ url_info = url.split "?"
87
+ @url = url_info[0]
88
+ if url_info.length > 1
89
+ self.parse_query url_info[1]
90
+ end
91
+ return
92
+ end
93
+ @url = url
94
+ end
95
+
96
+ def parse_query(query_string)
97
+ query_info = query_string.split "&"
98
+ query_info.each do |query_info_item|
99
+ query_item = query_info_item.split "="
100
+ if query_item.length == 2
101
+ query_item_key = query_item[0]
102
+ query_item_value = query_item[1]
103
+ @query[query_item_key] = query_item_value
104
+ end
105
+ end
106
+ end
107
+
108
+ def receive_header
109
+ loop { break unless receive_header_item }
110
+ end
111
+
112
+ def receive_header_item
113
+ last_token = ""
114
+ data = ""
115
+
116
+ while buffer = @socket.recv_nonblock(1)
117
+ if last_token == "\r" && buffer == "\n"
118
+ break
119
+ end
120
+
121
+ data << buffer
122
+ last_token = buffer
123
+ end
124
+
125
+ if data == "\r"
126
+ return false
127
+ end
128
+
129
+ self.parse_header_item(data.chomp)
130
+ end
131
+
132
+ def parse_header_item(data)
133
+ header_item = data.split(": ")
134
+
135
+ if header_item.length == 2
136
+ @header[header_item[0]] = header_item[1]
137
+ end
138
+
139
+ return true
140
+ end
141
+
142
+ def receive_body(size)
143
+ data = @socket.recv(size)
144
+ self.parse_body(data)
145
+ end
146
+
147
+ def parse_body(data)
148
+ @body_raw_data = data
149
+
150
+ if @header.has_key?("Content-Type")
151
+ content_type = @header["Content-Type"]
152
+
153
+ if content_type.include? "application/x-www-form-urlencoded"
154
+ self.parse_form_body(data)
155
+ elsif content_type.include? "multipart/form-data"
156
+ content_type_info = content_type.split("; ")
157
+ content_type_info.each do |info|
158
+ if info.include? "boundary"
159
+ boundary_info = info.split('=')
160
+
161
+ if boundary_info.length == 2
162
+ boundary = boundary_info[1]
163
+ self.parse_multipart_form_body(boundary, data)
164
+ end
165
+ end
166
+ end
167
+ end
168
+ end
169
+ end
170
+
171
+ def parse_form_body(data)
172
+ form_items = data.split('&')
173
+
174
+ form_items.each do |item|
175
+ item_info = item.split('=')
176
+ if item_info.length == 2
177
+ @body[item_info[0]] = item_info[1]
178
+ end
179
+ end
180
+ end
181
+
182
+ def parse_multipart_form_body(boundary, data)
183
+ offset = 0
184
+ boundary_string = "--#{boundary}"
185
+
186
+ while offset = data.index(boundary_string, offset)
187
+ next_offset = data.index(boundary_string, offset + 1)
188
+
189
+ unless next_offset
190
+ break
191
+ end
192
+
193
+ data_part = data.slice(offset + boundary_string.length + 2, next_offset - offset - boundary_string.length - 4)
194
+ self.parse_form_part(data_part)
195
+
196
+ offset = next_offset
197
+ end
198
+ end
199
+
200
+ def parse_form_part(data)
201
+ first_of_break = data.index("\r\n\r\n")
202
+ unless first_of_break === nil
203
+ content_info_data = data.slice(0, first_of_break)
204
+ content_info_data = content_info_data.gsub("\r\n", "; ")
205
+ content_info = content_info_data.split("; ")
206
+ content_disposition = ""
207
+ content_name = ""
208
+
209
+ content_info.each do |info|
210
+ if info.include? "Content-Disposition"
211
+ info_array = info.split(': ')
212
+ content_disposition = info_array[1] if info_array.length == 2
213
+
214
+ elsif info.include? "name="
215
+ info_array = info.split('=')
216
+ content_name = info_array[1] if info_array.length == 2
217
+ end
218
+ end
219
+
220
+ content_body = data.slice(first_of_break + 4, data.length - 4 - first_of_break - 2)
221
+
222
+ unless content_name.empty?
223
+ @body[content_name] = content_body
224
+ end
225
+ end
226
+ end
227
+ end
228
+
229
+ require "timeout"
@@ -0,0 +1,80 @@
1
+ class Amber::Http::Response < Amber::Http
2
+ attr_reader :status, :header, :content_type, :body
3
+
4
+ TEXT_CONTENT = "text/plain"
5
+ HTML_CONTENT = "text/html"
6
+ JSON_CONTENT = "application/json"
7
+
8
+ def initialize(socket)
9
+ super
10
+
11
+ @status_table = {
12
+ "100" => "Continue",
13
+ "200" => "OK",
14
+ "300" => "Multiple Choices",
15
+ "301" => "Moved Permanently",
16
+ "400" => "Bad Request",
17
+ "401" => "Unauthorized",
18
+ "403" => "Forbidden",
19
+ "404" => "Not Found",
20
+ "500" => "Internal Server Error",
21
+ "502" => "Bad Gateway",
22
+ "503" => "Service Unavailable"
23
+ }
24
+
25
+ @mime_table = [
26
+ TEXT_CONTENT,
27
+ HTML_CONTENT,
28
+ JSON_CONTENT
29
+ ]
30
+
31
+ @status = "200"
32
+ @header = {}
33
+ @content_type = HTML_CONTENT
34
+ @body = ""
35
+ end
36
+
37
+ def send
38
+ data = create_status_line
39
+ data << "Server: Amber/0.0.1\r\n"
40
+ @header.each do |key, value|
41
+ data << "#{key}: #{value}\r\n"
42
+ end
43
+ data << "Content-Type: #{@content_type}\r\n"
44
+ data << "Content-Length: #{@body.length}\r\n\r\n"
45
+ data << @body
46
+
47
+ @socket.sendmsg data, 0
48
+ end
49
+
50
+ def create_status_line
51
+ status_line = "HTTP/1.1 "
52
+ status_line << @status
53
+ status_line << ' '
54
+ status_line << @status_table[@status]
55
+ status_line << "\r\n"
56
+ status_line
57
+ end
58
+
59
+ def status=(status)
60
+ @status = status if @status_table.has_key?(status)
61
+ end
62
+
63
+ def header=(header)
64
+ if header.is_a? Hash
65
+ header.each do |key, value|
66
+ @header[key] = value
67
+ end
68
+ end
69
+ end
70
+
71
+ def content_type=(content_type)
72
+ @content_type = content_type if @mime_table.include?(content_type)
73
+ end
74
+
75
+ def body=(body)
76
+ if body.is_a? String
77
+ @body = body.bytes.to_a.pack("C*")
78
+ end
79
+ end
80
+ end
data/lib/amber/http.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Amber::Http
2
+ attr_reader :header
3
+
4
+ def initialize(socket)
5
+ @header = {}
6
+ @body_raw_data = ""
7
+ @socket = socket
8
+ end
9
+ end
@@ -0,0 +1,89 @@
1
+ class Amber::Model
2
+
3
+ def initialize
4
+ @data = {}
5
+ @data["id"] = Amber::Data::IntegerData.new
6
+ end
7
+
8
+ def [](key)
9
+ if @data.has_key? key
10
+ return @data[key]
11
+ end
12
+ end
13
+
14
+ def has_key?(key)
15
+ @data.has_key? key
16
+ end
17
+
18
+ def []=(key, value)
19
+ if value.is_a? Amber::Data
20
+ @data[key] = value
21
+ end
22
+ end
23
+
24
+ def keys
25
+ @data.keys
26
+ end
27
+
28
+ def pack(map = nil)
29
+ data = {}
30
+ if map.is_a? Hash
31
+ map.each do |key, value|
32
+ if @data.has_key? key
33
+ data_item = @data[key]
34
+ data[value] = data_item.value
35
+ end
36
+ end
37
+ else
38
+ @data.each do |key, value|
39
+ data[key] = value.value
40
+ end
41
+ end
42
+ data
43
+ end
44
+
45
+ def unpack(data, map = nil)
46
+ if data.is_a? Hash
47
+ if map.is_a? Hash
48
+ map.each do |key, value|
49
+ if @data.has_key?(key) && data.has_key?(value)
50
+ data_item = @data[key]
51
+ data_item.value = data[value]
52
+ end
53
+ end
54
+ else
55
+ data.each do |key, value|
56
+ if @data.has_key? key
57
+ data_item = @data[key]
58
+ data_item.value = data[key]
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ def struct(map = nil, name_only = false)
66
+ struct = {}
67
+ if map.is_a? Hash
68
+ map.each do |key, value|
69
+ if @data.has_key? key
70
+ data_item = @data[key]
71
+ if name_only
72
+ struct[value] = data_item.class.to_s.match('\w+$').to_s
73
+ next
74
+ end
75
+ struct[value] = data_item.class.to_s
76
+ end
77
+ end
78
+ else
79
+ @data.each do |key, value|
80
+ if name_only
81
+ struct[key] = value.class.to_s.match('\w+$').to_s
82
+ next
83
+ end
84
+ struct[key] = value.class.to_s
85
+ end
86
+ end
87
+ struct
88
+ end
89
+ end
@@ -0,0 +1,66 @@
1
+ class Amber::Route
2
+ attr_reader :root
3
+
4
+ def initialize
5
+ @root = Amber::RoutePath.new
6
+ end
7
+
8
+ def map(url, method = nil, &callback)
9
+ layers = self.parse_url(url)
10
+
11
+ if layers.length > 0
12
+ layers.delete ""
13
+ current_layer = @root
14
+
15
+ layers.each do |layer|
16
+ if layer == layers.last
17
+ if current_layer.child.has_key? layer
18
+ path = current_layer.child[layer]
19
+ path.callback = callback
20
+ path.method = method if method
21
+ next
22
+ end
23
+
24
+ new_path = Amber::RoutePath.new
25
+ new_path.callback = callback
26
+ new_path.method = method if method
27
+
28
+ current_layer.add_child(layer, new_path)
29
+ else
30
+ if current_layer.child.has_key? layer
31
+ current_layer = current_layer.child[layer]
32
+ next
33
+ end
34
+
35
+ new_path = Amber::RoutePath.new
36
+ current_layer.add_child(layer, new_path)
37
+ current_layer = new_path
38
+ end
39
+ end
40
+ else
41
+ @root.callback = callback
42
+ end
43
+ end
44
+
45
+ def find(url)
46
+ layers = self.parse_url(url)
47
+ current_layer = @root
48
+
49
+ if layers.length > 0
50
+ layers.delete ""
51
+ layers.each do |layer|
52
+ if current_layer.child.has_key? layer
53
+ current_layer = current_layer.child[layer]
54
+ else
55
+ return nil
56
+ end
57
+ end
58
+ end
59
+
60
+ current_layer
61
+ end
62
+
63
+ def parse_url(url)
64
+ url.split('/')
65
+ end
66
+ end