swee 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.
@@ -0,0 +1,118 @@
1
+ module Swee
2
+ class Config
3
+ class BaseConfig
4
+ def absolutely_app_path _file
5
+ _file.start_with?("/") ? _file : File.expand_path(_file,ENV["app_path"])
6
+ end
7
+
8
+ def [](key)
9
+ send(key)
10
+ end
11
+ end
12
+
13
+ class ServerConfig < BaseConfig
14
+ attr_accessor :listen
15
+ attr_accessor :handle_request_mode
16
+ attr_accessor :env
17
+ attr_accessor :logger_level
18
+ attr_accessor :code_reload
19
+ attr_accessor :restart_mode
20
+ attr_accessor :touch_file
21
+ attr_accessor :pid_file
22
+ attr_accessor :log_file
23
+ attr_accessor :max_connections
24
+ attr_accessor :performance_monitoring
25
+ attr_accessor :run_background
26
+ attr_accessor :cmd
27
+
28
+ def default_config! options
29
+ @listen = ( options[:listen] || 3000 )
30
+ @handle_request_mode ||= :event_loop
31
+ @env = ( options[:env] || :development )
32
+ @logger_level ||= :debug
33
+ @code_reload ||= true
34
+ @restart_mode ||= :pid
35
+ @touch_file ||= File.expand_path("./tmp/restart.txt",ENV["app_path"])
36
+ @pid_file ||= File.expand_path("./tmp/pid",ENV["app_path"])
37
+ @log_file ||= [ File.expand_path("./logs/#{env.to_s}.log",ENV["app_path"]), 10, 10240000 ]
38
+ @max_connections ||= 1024
39
+ @performance_monitoring ||= false
40
+ @run_background ||= false
41
+ @cmd = options[:cmd]
42
+ end
43
+
44
+ # def touch_file=(_file)
45
+ # @touch_file = absolutely_app_path(_file)
46
+ # end
47
+
48
+ # def pid_file=(_file)
49
+ # @touch_file = absolutely_app_path(_file)
50
+ # end
51
+
52
+ end
53
+
54
+ class AppConfig < BaseConfig
55
+ attr_accessor :time_zone
56
+ attr_accessor :default_locale
57
+ attr_accessor :page404
58
+ attr_accessor :page500
59
+ attr_accessor :include_path
60
+ attr_accessor :email
61
+
62
+ # def page404=(_file)
63
+ # @page404 = absolutely_app_path(_file)
64
+ # end
65
+
66
+ # def page500=(_file)
67
+ # @page500 = absolutely_app_path(_file)
68
+ # end
69
+
70
+ def default_config! options
71
+ @time_zone ||= "Beijing"
72
+ @default_locale ||= "zh-CN"
73
+ @page404 ||= File.expand_path("./public/404.html",ENV["app_path"])
74
+ @page500 ||= File.expand_path("./public/500.html",ENV["app_path"])
75
+ @include_path ||= []
76
+ @email ||= {}
77
+ end
78
+ end
79
+
80
+ { ServerConfig => [ :pid_file=, :touch_file=], AppConfig => [:page404=, :page500=] }.each do |_kls, _methods|
81
+ _methods.each do |_m|
82
+ _kls.send(:define_method,_m) do |_file|
83
+ eval "@#{_m.to_s} absolutely_app_path('#{_file}')"
84
+ end
85
+ end
86
+ end
87
+
88
+ class DbConfig < BaseConfig
89
+ attr_accessor :adapter
90
+ attr_accessor :database
91
+ attr_accessor :host
92
+ attr_accessor :username
93
+ attr_accessor :password
94
+ attr_accessor :encoding
95
+ attr_accessor :pool
96
+
97
+ def default_config! options
98
+
99
+ end
100
+ end
101
+
102
+ class AppPluginConfig
103
+
104
+ end
105
+
106
+ attr_accessor :app, :server, :db, :app_plugin
107
+ def initialize
108
+ @server = ServerConfig.new
109
+ @app = AppConfig.new
110
+ @db = DbConfig.new
111
+ # @plugin = AppPluginConfig.new
112
+ end
113
+
114
+ def default_config! options
115
+ [@server,@app,@db].each { |cfg| cfg.default_config! options }
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,48 @@
1
+ module Swee
2
+ class Connection < EventMachine::Connection
3
+
4
+ attr_accessor :server
5
+ attr_accessor :request
6
+ attr_accessor :response
7
+
8
+ # EM 初始化请求
9
+ def post_init
10
+ @request = ::Thin::Request.new
11
+ @response = ::Thin::Response.new
12
+ end
13
+
14
+ # EM 接收 data
15
+ def receive_data(data)
16
+ EM.defer do
17
+ # thin -> 解析 http
18
+ @request.parse(data)
19
+
20
+ # 获取 env
21
+ env = @request.env
22
+
23
+ # 默认 middlewave 先被执行
24
+ app = AppExecutor.method(:run)
25
+ # 代码重新加载
26
+ app = Reloader.new(app,Engine.server.logger) if @server.code_reload
27
+ # rack -> 代码异常
28
+ app = Rack::ShowExceptions.new(app)
29
+ # rack -> 请求日志
30
+ app = Rack::CommonLogger.new(app,Engine.server.logger)
31
+ # rack -> 自动分配 Content-Encoding
32
+ app = Rack::Deflater.new(app)
33
+ # 计算 content-length
34
+ app = ContentLength.new(app)
35
+
36
+ @response.status, @response.headers, @response.body = app.call(env)
37
+ @response.each do |chunk|
38
+ send_data chunk
39
+ end
40
+ end
41
+ end
42
+
43
+ def unbind
44
+ @server.connection_finished(self)
45
+ end
46
+ end
47
+ end
48
+
@@ -0,0 +1,158 @@
1
+ require "erb"
2
+
3
+ module Swee
4
+ # 过滤器
5
+ class FilterStruct
6
+ attr_accessor :type,:method,:actions
7
+ def initialize _t, _m, _a
8
+ @type,@method,@actions = _t,_m,_a
9
+ end
10
+ end
11
+
12
+ class Controller
13
+ include ControllerFilter
14
+ attr_reader :env, :request, :controller_name, :action_name, :request #, :response
15
+
16
+ # 包装request
17
+ # rack 的 request -> controller request
18
+ # .方法的 映射 -> [] 方法
19
+ # Struct 简单的包装
20
+ def warp_request env,route
21
+ @env = env
22
+ @rack_request = Rack::Request.new env # 暂时用 rack 方式接受 TODO: 解析 env
23
+ # @response = Rack::Response.new
24
+ @controller_name = route.controller_name
25
+ @name = route.controller
26
+ @action_name = route.action
27
+ request_struct = Struct.new(:hash) do
28
+ def method_missing method_name, *args, &blk
29
+ if hash.key? method_name
30
+ hash[method_name]
31
+ else
32
+ case method_name
33
+ when :remote_ip; hash[:ip]
34
+ when :post?; hash[:method] == "POST"
35
+ when :get?; hash[:method] == "GET"
36
+ when :xhr?; hash[:xhr]
37
+ else
38
+ super
39
+ end
40
+ end
41
+ end
42
+ end
43
+ @request = request_struct.new(rack_request_to_hash)
44
+ end
45
+
46
+ def _name
47
+ @name
48
+ end
49
+
50
+ def rack_request
51
+ @rack_request
52
+ end
53
+
54
+ def response
55
+ @response
56
+ end
57
+
58
+ # 获取 参数
59
+ def params
60
+ { "controller" => @controller_name, "action" => @action_name }.merge @rack_request.params
61
+ end
62
+
63
+ # 映射 rake request -> struct
64
+ def rack_request_to_hash
65
+ _request = rack_request
66
+ _body = {
67
+ ip: _request.ip,
68
+ cookies: _request.cookies,
69
+ session: _request.session,
70
+ session_options: _request.session_options,
71
+ referer: _request.referer,
72
+ user_agent: _request.user_agent,
73
+ method: _request.request_method,
74
+ path: _request.path,
75
+ path_info: _request.path_info,
76
+ params: _request.params,
77
+ port: _request.port,
78
+ url: _request.url,
79
+ base_url: _request.base_url,
80
+ fullpath: _request.fullpath,
81
+ host: _request.host,
82
+ host_with_port: _request.host_with_port,
83
+ logger: _request.logger,
84
+ media_type: _request.media_type,
85
+ media_type_params: _request.media_type_params,
86
+ POST: _request.POST,
87
+ query_string: _request.query_string,
88
+ scheme: _request.scheme,
89
+ script_name: _request.script_name,
90
+ ssl: _request.ssl?,
91
+ trace: _request.trace?,
92
+ xhr: _request.xhr?,
93
+ client: _request['client']
94
+ }
95
+ end
96
+
97
+ # 渲染
98
+ # text: render :text => "foobar"
99
+ # erb: render (可省略对应寻找view)
100
+ # json: render :json => { foo: "bar" }
101
+ def render options={}
102
+ if options.empty?
103
+ _render_file
104
+ else
105
+ if options[:text]
106
+ _render_text options
107
+ elsif options[:json]
108
+ _render_json options
109
+ end
110
+ end
111
+ end
112
+
113
+ def rake_format body,type
114
+
115
+ end
116
+
117
+ # TODO
118
+ def cookies
119
+
120
+ end
121
+
122
+ # TODO
123
+ def sessions
124
+
125
+ end
126
+
127
+ def __actions
128
+ ControllerFilter.fliter_methods[self.class.to_s]
129
+ end
130
+
131
+
132
+ private
133
+ def _render_file(ftype="html")
134
+ if ftype == "html"
135
+ _view = View.new(self)
136
+ _body = _view.create_view
137
+ else
138
+ _body = "no file was loaded!"
139
+ end
140
+ # _length = View.calc_length(_body).to_s
141
+ [200,{ "Content-Type" => "text/html; charset=utf8" },[_body]]
142
+ end
143
+
144
+ def _render_text options
145
+ _body = options[:text]
146
+ # _length = View.calc_length(_body).to_s
147
+ [200,{ "Content-Type" => "text/plain; charset=utf8" },[_body]]
148
+ end
149
+
150
+ def _render_json options
151
+ _body = options[:json].to_json
152
+ # _length = View.calc_length(_body).to_s
153
+ [200,{ "Content-Type" => "application/json; charset=utf8" },[_body]]
154
+ end
155
+
156
+ end
157
+ Controller.define_filter
158
+ end
@@ -0,0 +1,67 @@
1
+ module Swee
2
+ module ControllerFilter
3
+ @@fliter_methods = Hash.new {|h1,k1| h1[k1] = [] }
4
+
5
+ def self.fliter_methods
6
+ @@fliter_methods
7
+ end
8
+
9
+ def self.included(base)
10
+ base.extend self
11
+ end
12
+
13
+ def find_controller _controller
14
+ fliter_methods[_controller]
15
+ end
16
+
17
+ def delete_duplicated_filter _controller,_method
18
+ structs = find_controller _controller
19
+ dup_struct = structs.select { |struct| struct.method == _method }.first
20
+ structs.reject! { |struct| struct.equal?(dup_struct) }
21
+ end
22
+
23
+ def find_filter_methods _controller,_type,_action
24
+ structs = find_controller _controller
25
+ structs.select { |s|
26
+ _actions = s.actions
27
+ unless _actions.empty?
28
+ if s.actions[:only]
29
+ exist_action = s.actions[:only].map(&:to_sym).include?(_action.to_sym)
30
+ elsif s.actions[:except]
31
+ exist_action = !s.actions[:except].map(&:to_sym).include?(_action.to_sym)
32
+ end
33
+ end
34
+ (_actions.empty? && s.type == _type) ||
35
+ (_actions.empty? && s.type == :round) ||
36
+ ( s.type == _type && exist_action ) ||
37
+ ( s.type == :round && exist_action )
38
+ }.map(&:method)
39
+ end
40
+
41
+ def fliter_methods
42
+ @@fliter_methods
43
+ end
44
+
45
+ def filter! _type, _method, options={}
46
+ delete_duplicated_filter self.name, _method
47
+ fliter_methods[self.name] << FilterStruct.new(_type, _method.to_sym, options) # {_method => [:before,options] }
48
+ fliter_methods[self.name].uniq!
49
+ end
50
+
51
+ def define_filter
52
+ self.class.instance_eval do
53
+ [:before_filter,
54
+ # :skip_before_filter, TODO:
55
+ :after_filter,
56
+ # :skip_before_filter, TODO:
57
+ :round_filter,
58
+ # :skip_before_filter TODO:
59
+ ].each do |method_name|
60
+ define_method(method_name) do |_method,options={}|
61
+ filter! method_name.to_s.split("_").first.to_sym, _method, options
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,17 @@
1
+ module Daemonize
2
+ def safefork
3
+ tryagain = true
4
+
5
+ while tryagain
6
+ tryagain = false
7
+ begin
8
+ if pid = fork
9
+ return pid
10
+ end
11
+ rescue Errno::EWOULDBLOCK
12
+ sleep 5
13
+ tryagain = true
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,201 @@
1
+ require 'optparse'
2
+ require 'erb'
3
+ require 'rack'
4
+ require 'eventmachine'
5
+ require "thin_parser"
6
+
7
+ # ENV["app_path"] = File.expand_path('../../../../', __FILE__)
8
+ ENV["app_path"] = Dir.pwd
9
+
10
+ module Swee
11
+ # 获取 app 路径
12
+ def root
13
+ ENV["app_path"]
14
+ end
15
+
16
+ # 获取app配置
17
+ def app_config
18
+ yield self.config.app
19
+ end
20
+
21
+ # 获取 服务器配置
22
+ def server_config
23
+ yield self.config.server
24
+ end
25
+
26
+ # 获取 数据库配置
27
+ def database_config
28
+
29
+ end
30
+
31
+ # 配置实例
32
+ def config
33
+ @@config
34
+ end
35
+
36
+ # 初始化
37
+ def init_config
38
+ @@config = Config.new
39
+ end
40
+
41
+ # 静态化
42
+ module_function :root,:app_config,:server_config,:config, :database_config, :init_config
43
+
44
+ class Engine
45
+ @@__instance__ = nil # => 实例
46
+ @@__server__ = nil # => 服务器
47
+
48
+ def initialize options
49
+ # 初始化配置
50
+ @config = Swee.init_config
51
+
52
+ # 读取用户配置
53
+ require_user_appconfig
54
+
55
+ # 合并配置
56
+ merge_config! options
57
+ end
58
+
59
+ # 加载 app配置
60
+ def require_user_appconfig
61
+ # require_relative './application'
62
+ Lodder.app_require
63
+ end
64
+
65
+ # 合并配置
66
+ def merge_config! options
67
+ @config.default_config! options
68
+ end
69
+
70
+ class << self
71
+ # 当前实例
72
+ def instance
73
+ @@__instance__
74
+ end
75
+ # 配置实例
76
+ def config
77
+ instance.send :config
78
+ end
79
+ # 服务器实例
80
+ def server
81
+ @@__server__
82
+ end
83
+
84
+ # def load_middlewares
85
+ # @@instance.load_default_middlewares
86
+ # end
87
+
88
+ # def parse_path_info
89
+ # @@instance.run method(:path_to_routes)
90
+ # end
91
+
92
+ # 命令行解析
93
+ def parse_options
94
+ options = {}
95
+ OptionParser.new do |opts|
96
+ opts.banner = "swee框架使用参数如下"
97
+
98
+ opts.on("-p", "--port PORT", Integer,
99
+ "端口 (默认: 3000)") do |port|
100
+ options[:listen] = port
101
+ end
102
+
103
+ opts.on("-e", "--env ENV",
104
+ "环境 development 或 production (默认为development)") do |e|
105
+ options[:env] = e
106
+ end
107
+ end.parse!
108
+ options
109
+ end
110
+
111
+ # 启动服务
112
+ def boot! argv
113
+ cmd = argv.shift || "s"
114
+ options = parse_options.merge({:cmd => cmd})
115
+
116
+ case cmd
117
+ when "new"
118
+ proj_name = argv.shift
119
+ if proj_name.nil?
120
+ puts "格式错误,请输入: swee new 项目名称"
121
+ return
122
+ end
123
+ require_relative './installer'
124
+ Installer.run(proj_name)
125
+ return
126
+ when "g" # => Todo: generation 生成
127
+ return
128
+ else
129
+ require_files
130
+ cache_file_mtime
131
+ @@__instance__ = self.new options
132
+ parse_cmd cmd,options
133
+ end
134
+ end
135
+
136
+ # 解析命令
137
+ # c -> 命令行
138
+ # s -> 启动服务
139
+ def parse_cmd cmd,options
140
+ case cmd
141
+ when "c" # => 命令行模式
142
+ require 'irb'
143
+ IRB.start
144
+ when "s" # => 启动服务器
145
+ start_server!
146
+ else
147
+ raise "命令不合法"
148
+ end
149
+ end
150
+
151
+ # 加载全部文件
152
+ def require_files
153
+ # require 加载器 Lodder
154
+ require_relative './lodder'
155
+ Lodder.all
156
+
157
+ _app_path = ENV["app_path"]
158
+
159
+ # _app_env = Application.config["app_env"]
160
+
161
+ # if (begin
162
+ # require "active_record"
163
+ # rescue
164
+ # false
165
+ # end)
166
+ # ActiveRecord::Base.establish_connection YAML::load(File.open(ENV["app_path"]+'/database.yml'))[_app_env]
167
+ # end
168
+
169
+ # 加载路由
170
+ require File.expand_path('./routes', _app_path)
171
+
172
+ # 加载控制器
173
+ Dir.glob("#{_app_path}/controllers/*.rb") { |f| require f }
174
+
175
+ # 加载模型
176
+ Dir.glob("#{_app_path}/models/*.rb") { |f| require ENV["app_path"] + "/models/"+File.basename(f, '.*') }
177
+
178
+ end
179
+
180
+ def cache_file_mtime
181
+ Lodder.cache_file_mtime
182
+ end
183
+
184
+ # 重启服务器
185
+ def restart_server!
186
+ @@__server__ = nil
187
+ GC.start
188
+ require_files
189
+ cache_file_mtime
190
+ start_server!
191
+ end
192
+
193
+ # 启动服务器
194
+ def start_server!
195
+ @@__server__ = Server.new
196
+ @@__server__.run!
197
+ end
198
+ end
199
+ end
200
+ end
201
+