amber-kit 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ class Amber::RoutePath
2
+ attr_reader :child, :method, :callback
3
+
4
+ def initialize(method = "GET", callback = nil)
5
+ @child = {}
6
+ @method = method
7
+ @callback = callback
8
+ end
9
+
10
+ def has_child?
11
+ !@child.empty?
12
+ end
13
+
14
+ def can_call?
15
+ @callback != nil
16
+ end
17
+
18
+ def add_child(path, child)
19
+ if child.is_a? Amber::RoutePath
20
+ @child[path] = child
21
+ return
22
+ end
23
+
24
+ raise ArgumentError, "Child should be a route item"
25
+ end
26
+
27
+ def method=(method)
28
+ @method = method
29
+ end
30
+
31
+ def callback=(callback)
32
+ if callback.is_a? Proc
33
+ @callback = callback
34
+ return
35
+ end
36
+
37
+ raise ArgumentError, "Callback should be a proc"
38
+ end
39
+ end
@@ -0,0 +1,103 @@
1
+ class Amber::Server
2
+ attr_accessor :port, :host, :base
3
+
4
+ def initialize(port = 3001, host = '127.0.0.1')
5
+ @port = port
6
+ @host = host
7
+ @server_socket
8
+ @server_address
9
+ @fd_set = []
10
+ end
11
+
12
+ def prepare
13
+ @server_socket = Socket.new(Socket::AF_INET, Socket::SOCK_STREAM, 0)
14
+ @server_address = Socket.sockaddr_in(@port, @host)
15
+
16
+ @server_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
17
+ @server_socket.bind(@server_address)
18
+ @server_socket.listen(5)
19
+
20
+ @fd_set << @server_socket
21
+ end
22
+
23
+ def start
24
+ loop {
25
+ fd_items = IO.select(@fd_set, [], [], 5)
26
+
27
+ if fd_items.is_a?(Array)
28
+ readable_items = fd_items.first
29
+ readable_items.each do |socket|
30
+ self.communicate(socket)
31
+ end
32
+ end
33
+ }
34
+ end
35
+
36
+ def communicate(socket)
37
+ if socket == @server_socket
38
+ begin
39
+ client_socket, client_address = @server_socket.accept_nonblock
40
+ @fd_set << client_socket
41
+ rescue IO::WaitReadable, Errno::EINTR
42
+ retry
43
+ end
44
+
45
+ else
46
+ @fd_set.delete(socket)
47
+ task = Fiber.new {
48
+ self.transaction(socket)
49
+ }
50
+ task.resume
51
+ end
52
+ end
53
+
54
+ def transaction(socket)
55
+ http_request = Amber::Http::Request.new(socket)
56
+ http_response = Amber::Http::Response.new(socket)
57
+
58
+ if http_request.receive
59
+ time = Time.new
60
+ time_string = time.strftime("%Y-%m-%d %H:%M:%S")
61
+ STDOUT.puts "#{time_string} #{http_request.method} #{http_request.url}"
62
+ begin
63
+ if (path = @base.route.find(http_request.url)) && path.can_call?
64
+ if path.method == http_request.method
65
+ result = path.callback.call http_request
66
+ case result
67
+ when Amber::View
68
+ http_response.status = result.code.to_s
69
+ http_response.header = result.header
70
+ http_response.content_type = result.content.type
71
+ http_response.body = result.content.body
72
+ when String
73
+ http_response.status = "200"
74
+ http_response.body = result
75
+ else
76
+ http_response.status = "500"
77
+ http_response.body = "<html><h1>Server Internal Error</h1></html>"
78
+ end
79
+ else
80
+ http_response.status = "301"
81
+ http_response.body = "<html><h1>Moved Permanently</h1></html>"
82
+ end
83
+ else
84
+ http_response.status = "404"
85
+ http_response.body = "<html><h1>Not Found</h1></html>"
86
+ end
87
+ rescue Exception => e
88
+ STDOUT.puts e
89
+ end
90
+ else
91
+ http_response.status = "400"
92
+ http_response.body = "<html><h1>Bad Request</h1></html>"
93
+ end
94
+
95
+ http_response.send
96
+
97
+ socket.close
98
+ end
99
+ end
100
+
101
+ require "socket"
102
+ require "fiber"
103
+
@@ -0,0 +1,116 @@
1
+ class Amber::Storage::Json < Amber::Storage
2
+ def initialize(file_path)
3
+ @file_path = file_path
4
+ end
5
+
6
+ def fetch
7
+ data = []
8
+ if raw_data = self.read_file
9
+ data = self.deserialize(raw_data)
10
+ end
11
+ data.first
12
+ end
13
+
14
+ def fetch_all
15
+ data = []
16
+ if raw_data = self.read_file
17
+ data = self.deserialize(raw_data)
18
+ end
19
+ data
20
+ end
21
+
22
+ def save(data)
23
+ if File.exist? @file_path
24
+ file = File.open(@file_path, "w")
25
+ file.puts self.serialize(data)
26
+ file.close
27
+ end
28
+ end
29
+
30
+ def update(data)
31
+ if raw_data = self.read_file
32
+ origin_data = self.deserialize(raw_data)
33
+ new_data = []
34
+
35
+ if data.is_a? Array
36
+ origin_data.each do |item|
37
+ new_item = item
38
+ data.each do |data_item|
39
+ if data_item["id"] == item["id"]
40
+ new_item = data_item
41
+ end
42
+ end
43
+ new_data.push(new_item)
44
+ end
45
+ else
46
+ origin_data.each do |item|
47
+ new_item = item
48
+ if data["id"] == item["id"]
49
+ new_item = data
50
+ end
51
+ new_data.push(new_item)
52
+ end
53
+ end
54
+
55
+ self.save(new_data)
56
+ end
57
+ end
58
+
59
+ def delete(data)
60
+ if raw_data = self.read_file
61
+ origin_data = self.deserialize(raw_data)
62
+ new_data = []
63
+
64
+ if data.is_a? Array
65
+ origin_data.each do |item|
66
+ retain = true
67
+ data.each do |data_item|
68
+ if data_item["id"] == item["id"]
69
+ retain = false
70
+ end
71
+ end
72
+ new_data.push(item) if retain
73
+ end
74
+ else
75
+ origin_data.each do |item|
76
+ retain = true
77
+ if data["id"] == item["id"]
78
+ retain = false
79
+ end
80
+ new_data.push(item) if retain
81
+ end
82
+ end
83
+
84
+ self.save(new_data)
85
+ end
86
+ end
87
+
88
+ def serialize(data)
89
+ begin
90
+ data = [data] unless data.is_a? Array
91
+ JSON.generate(data)
92
+ rescue Exception => e
93
+ p e
94
+ end
95
+ end
96
+
97
+ def deserialize(data)
98
+ begin
99
+ JSON.parse(data)
100
+ rescue Exception => e
101
+ p e
102
+ end
103
+ end
104
+
105
+ def read_file
106
+ if File.exist? @file_path
107
+ file = File.open(@file_path)
108
+ raw_data = file.read
109
+ raw_data = "[]" if raw_data.empty?
110
+ file.close
111
+ return raw_data
112
+ end
113
+ end
114
+ end
115
+
116
+ require "json"
@@ -0,0 +1,103 @@
1
+ class Amber::Storage::RemoteJson < Amber::Storage
2
+ def initialize(url)
3
+ @uri = URI.parse(url)
4
+ @status = false
5
+ @data = {}
6
+ end
7
+
8
+ def query(data)
9
+ self.request({"token" => "", "data" => data})
10
+ end
11
+
12
+ def request(body = nil)
13
+ request = Net::HTTP::Post.new(@uri)
14
+ # request.body = body if body
15
+ response = nil
16
+ @status = false
17
+ @data = {}
18
+ result = Net::HTTP.start(@uri.hostname, @uri.port) do |http|
19
+ response = http.request(request)
20
+ end
21
+
22
+ case result
23
+ when Net::HTTPSuccess
24
+ info = self.deserialize(result.body)
25
+ if info.is_a? Hash
26
+ if info.has_key?("status") && info["status"] == 1
27
+ @status = true
28
+ info_data = {}
29
+ info_data = info["data"] if info.has_key?("data")
30
+ if info_data.is_a?(Array) || info_data.is_a?(Hash)
31
+ @data = info_data
32
+ end
33
+ else
34
+ @status = false
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ def serialize(data)
41
+ data_string = ""
42
+ begin
43
+ data = [data] unless data.is_a? Array
44
+ data_string = JSON.generate(data)
45
+ rescue Exception => e
46
+ p e
47
+ end
48
+ data_string
49
+ end
50
+
51
+ def deserialize(data)
52
+ data_struct = nil
53
+ begin
54
+ data_struct = JSON.parse(data)
55
+ rescue Exception => e
56
+ p e
57
+ end
58
+ data_struct
59
+ end
60
+
61
+ def pack(map)
62
+ data = nil
63
+ if map.is_a? Hash
64
+ if @data.is_a? Hash
65
+ data = {}
66
+ map.each do |key, value|
67
+ if @data.has_key? key
68
+ data[value] = @data[key]
69
+ else
70
+ data[value] = nil
71
+ end
72
+ end
73
+ elsif @data.is_a? Array
74
+ data = []
75
+ @data.each do |result_data_item|
76
+ if result_data_item.is_a? Hash
77
+ data_item = {}
78
+ map.each do |key, value|
79
+ if @result_data_item.has_key? key
80
+ data_item[value] = @result_data_item[key]
81
+ else
82
+ data_item[value] = nil
83
+ end
84
+ end
85
+ data.push data_item
86
+ end
87
+ end
88
+ end
89
+ end
90
+ data
91
+ end
92
+
93
+ def unpack(data, map)
94
+ # map.each do |key, value|
95
+ # if data.is_a? Hash
96
+
97
+ # end
98
+ # end
99
+ end
100
+ end
101
+
102
+ require "json"
103
+ require "net/http"
@@ -0,0 +1,8 @@
1
+ class Amber::Storage
2
+ attr_reader :status, :data
3
+
4
+ def initialize
5
+ @status = false
6
+ @data = nil
7
+ end
8
+ end
@@ -0,0 +1,43 @@
1
+ class Amber::Switch::Content::FormData < Amber::Switch::Content
2
+ include Amber::Switch::ContentDelegate
3
+
4
+ def initialize(data = {})
5
+ super Amber::Switch::Content::FORM_DATA_CONTENT, data
6
+ end
7
+
8
+ def data=(data)
9
+ if data.is_a? Hash
10
+ super
11
+ end
12
+ end
13
+
14
+ def serialize(data)
15
+ form_data_string = ""
16
+ if data.is_a? Hash
17
+ form_data_items = []
18
+ data.each do |key, value|
19
+ form_data_item = URI.encode(key) + "=" + URI.encode(value)
20
+ form_data_items.push form_data_item
21
+ end
22
+ form_data_string = form_data_items.join "&"
23
+ end
24
+ form_data_string
25
+ end
26
+
27
+ def deserialize(data)
28
+ form_data = {}
29
+ form_data_string = data.to_s
30
+ form_data_items = form_data_string.split '&'
31
+ form_data_items.each do |form_data_item|
32
+ info = form_data_item.split '='
33
+ if info.length == 2
34
+ key = URI.encode info[0]
35
+ value = URI.decode info[1]
36
+ form_data[key] = value
37
+ end
38
+ end
39
+ form_data
40
+ end
41
+ end
42
+
43
+ require "uri"
@@ -0,0 +1,35 @@
1
+ class Amber::Switch::Content::Json < Amber::Switch::Content
2
+ include Amber::Switch::ContentDelegate
3
+
4
+ def initialize(data = {})
5
+ super Amber::Switch::Content::JSON_CONTENT, data
6
+ end
7
+
8
+ def data=(data)
9
+ if data.is_a? Hash
10
+ super
11
+ end
12
+ end
13
+
14
+ def serialize(data)
15
+ begin
16
+ return JSON.generate data
17
+ rescue Exception => e
18
+ p e
19
+ end
20
+ ""
21
+ end
22
+
23
+ def deserialize(data)
24
+ if data.is_a? String
25
+ begin
26
+ return JSON.parse data
27
+ rescue Exception => e
28
+ p e
29
+ end
30
+ end
31
+ {}
32
+ end
33
+ end
34
+
35
+ require "amber/switch/content_delegate"
@@ -0,0 +1,22 @@
1
+ class Amber::Switch::Content::Text < Amber::Switch::Content
2
+ include Amber::Switch::ContentDelegate
3
+
4
+ def initialize(data = "")
5
+ super Amber::Switch::Content::TEXT_CONTENT, data
6
+ end
7
+
8
+ def data=(data)
9
+ if data.is_a? String
10
+ super
11
+ end
12
+ end
13
+ def serialize(data)
14
+ data.to_s
15
+ end
16
+
17
+ def deserialize(data)
18
+ data.to_s
19
+ end
20
+ end
21
+
22
+ require "amber/switch/content_delegate"
@@ -0,0 +1,38 @@
1
+ class Amber::Switch::Content
2
+ attr_accessor :type
3
+
4
+ TEXT_CONTENT = 'text/plain'
5
+ FORM_DATA_CONTENT = 'application/x-www-form-urlencoded'
6
+ JSON_CONTENT = 'application/json'
7
+
8
+ def initialize(type, data = nil)
9
+ @type = type
10
+
11
+ if data
12
+ self.data = data
13
+ end
14
+ end
15
+
16
+ def data
17
+ @data
18
+ end
19
+
20
+ def data=(data)
21
+ @data = data
22
+ end
23
+
24
+ def body
25
+ if self.class.include? Amber::Switch::ContentDelegate
26
+ return self.serialize @data
27
+ end
28
+ end
29
+
30
+ def body=(body)
31
+ if self.class.include? Amber::Switch::ContentDelegate
32
+ @data = self.deserialize body
33
+ return
34
+ end
35
+ end
36
+ end
37
+
38
+ require "amber/switch/content_delegate"
@@ -0,0 +1,9 @@
1
+ module Amber::Switch::ContentDelegate
2
+ def serialize(data)
3
+
4
+ end
5
+
6
+ def deserialize(data)
7
+
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class Amber::Switch::Request::Get < Amber::Switch::Request
2
+ def initialize(url = "")
3
+ super Amber::Switch::Request::GET_METHOD, url
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class Amber::Switch::Request::Post < Amber::Switch::Request
2
+ attr_accessor :content
3
+
4
+ def initialize(url = "")
5
+ super Amber::Switch::Request::POST_METHOD, url
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ class Amber::Switch::Request
2
+ attr_accessor :method, :url, :header
3
+
4
+ GET_METHOD = 'GET'
5
+ POST_METHOD = 'POST'
6
+ PUT_METHOD = 'PUT'
7
+ DELETE_METHOD = 'DELETE'
8
+
9
+ def initialize(method, url)
10
+ @method = method
11
+ @url = url
12
+ @header = {}
13
+ end
14
+ end
15
+
16
+ require "json"
@@ -0,0 +1,10 @@
1
+ class Amber::Switch::Response
2
+ attr_accessor :status, :header, :content
3
+
4
+ def initialize
5
+ @status = false
6
+ @header = {}
7
+ end
8
+ end
9
+
10
+ require "json"
@@ -0,0 +1,71 @@
1
+ class Amber::Switch
2
+ def query(request)
3
+ if request.is_a? Amber::Switch::Request
4
+ result = nil
5
+ case request
6
+ when Amber::Switch::Request::Get
7
+ result = self.request(request.url, request.method, request.header)
8
+ when Amber::Switch::Request::Post
9
+ body = request.content.is_a?(Amber::Switch::Content) ? request.content.body : nil
10
+ result = self.request(request.url, request.method, request.header, body)
11
+ end
12
+ if result
13
+ response = Amber::Switch::Response.new
14
+ response.status = result["status"]
15
+ response.header = result["header"]
16
+ response_content_type = result["content_type"].is_a?(Array) ? result["content_type"].first : result["content_type"].to_s
17
+ case response_content_type
18
+ when Amber::Switch::Content::JSON_CONTENT
19
+ response.content = Amber::Switch::Content::Json.new
20
+ response.content.body = result["body"]
21
+ else
22
+ response.content = Amber::Switch::Content::Text.new
23
+ response.content.body = result["body"]
24
+ end
25
+ return response
26
+ end
27
+ end
28
+
29
+ p "#{request} should be an instance of Amber::Switch::Request"
30
+ return
31
+ end
32
+
33
+ def request(url, method, header = {}, body = nil)
34
+ request = nil
35
+ uri = URI(url)
36
+ response = {
37
+ "status" => false,
38
+ "code" => 400,
39
+ "content_type" => nil,
40
+ "header" => {},
41
+ "body" => nil
42
+ }
43
+ case method
44
+ when Amber::Switch::Request::GET_METHOD
45
+ request = Net::HTTP::Get.new uri
46
+ when Amber::Switch::Request::POST_METHOD
47
+ request = Net::HTTP::Post.new uri
48
+ end
49
+ if request
50
+ header.each do |key, value|
51
+ request[key] = value
52
+ end
53
+ request.body = body if body
54
+ result = Net::HTTP.start(uri.hostname, uri.port) do |http|
55
+ http.request(request)
56
+ end
57
+
58
+ case result
59
+ when Net::HTTPSuccess
60
+ response["status"] = true
61
+ response["code"] = result.code.to_i
62
+ response["content_type"] = result.content_type
63
+ response["header"] = result.to_hash
64
+ response["body"] = result.body
65
+ end
66
+ end
67
+ response
68
+ end
69
+ end
70
+
71
+ require "net/http"
@@ -0,0 +1,9 @@
1
+ class Amber::View::Json < Amber::View
2
+ def initialize(code = 404, header = {}, data = nil)
3
+ super code, header, Amber::Switch::Content::Json.new
4
+
5
+ if data
6
+ self.content.data = data
7
+ end
8
+ end
9
+ end
data/lib/amber/view.rb ADDED
@@ -0,0 +1,9 @@
1
+ class Amber::View
2
+ attr_accessor :code, :header, :content
3
+
4
+ def initialize(code = 404, header = {}, content = nil)
5
+ @code = code
6
+ @header = header
7
+ @content = content
8
+ end
9
+ end