hara 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.
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/hara.gemspec +26 -0
- data/lib/hara/app.rb +128 -0
- data/lib/hara/base.rb +13 -0
- data/lib/hara/main.rb +15 -0
- data/lib/hara/server.rb +41 -0
- data/lib/hara/version.rb +3 -0
- data/lib/hara.rb +2 -0
- metadata +107 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 jjy
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Hara
|
2
|
+
|
3
|
+
Hara is a simple framework, help you build websocket server.
|
4
|
+
|
5
|
+
## Notice
|
6
|
+
|
7
|
+
Current API is unstable, you should lock the version.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Add this line to your application's Gemfile:
|
12
|
+
|
13
|
+
gem 'hara'
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install hara
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
*server*
|
26
|
+
```ruby
|
27
|
+
#test.rb
|
28
|
+
require 'hara'
|
29
|
+
|
30
|
+
class Echo < Hara::App
|
31
|
+
define_action :echo do |str|
|
32
|
+
socket << str
|
33
|
+
end
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
*client*
|
38
|
+
```javascript
|
39
|
+
var msg = JSON.stringify({action: 'echo',args:['hello world']})
|
40
|
+
var ws = new WebSocket('ws://localhost:3210')
|
41
|
+
ws.onmessage = function(msg){console.log(msg.data)}
|
42
|
+
ws.send(msg)
|
43
|
+
//hello world
|
44
|
+
```
|
45
|
+
|
46
|
+
*start server*
|
47
|
+
`ruby test.rb`
|
48
|
+
|
49
|
+
`ruby test.rb -h` to view details
|
50
|
+
|
51
|
+
## Contributing
|
52
|
+
|
53
|
+
1. Fork it
|
54
|
+
2. Feel free to send pull requests
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/hara.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'hara/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "hara"
|
8
|
+
spec.version = Hara::VERSION
|
9
|
+
spec.authors = ["jjy"]
|
10
|
+
spec.email = ["jjyruby@gmail.com"]
|
11
|
+
spec.description = %q{Hara is a simple framework, help you build [web ]socket server. Power by reel and celluloid.}
|
12
|
+
spec.summary = %q{Hara can help your build [web ]socket server easier.}
|
13
|
+
spec.homepage = "http://github.com/jjyr/hara"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
|
22
|
+
spec.add_dependency "reel", "~> 0.3"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
25
|
+
spec.add_development_dependency "rake"
|
26
|
+
end
|
data/lib/hara/app.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'celluloid/io'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module Hara
|
5
|
+
class App
|
6
|
+
include Celluloid::IO
|
7
|
+
include Celluloid::Logger
|
8
|
+
|
9
|
+
attr_reader :socket
|
10
|
+
|
11
|
+
alias halt terminate
|
12
|
+
|
13
|
+
Actions = {}
|
14
|
+
|
15
|
+
def self.inherited klass
|
16
|
+
::Hara.const_set :Application, klass
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize socket
|
20
|
+
@socket = socket
|
21
|
+
async.setup
|
22
|
+
end
|
23
|
+
|
24
|
+
def after_connect
|
25
|
+
end
|
26
|
+
|
27
|
+
#return true or false
|
28
|
+
def authentication
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def authentication_failed
|
33
|
+
halt
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_authentication
|
37
|
+
end
|
38
|
+
|
39
|
+
class << self
|
40
|
+
def define_action action, &block
|
41
|
+
action = action.to_s
|
42
|
+
warn "Action #{action} duplication defined" if Actions.has_key? action
|
43
|
+
Hara::Application.send :define_method, action, &block
|
44
|
+
method = Hara::Application.send :instance_method, action
|
45
|
+
Hara::Application.send :remove_method, action
|
46
|
+
Actions[action] = method
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def process message
|
51
|
+
@command = JSON.parse(message)
|
52
|
+
action = @command["action"]
|
53
|
+
args = @command["args"]
|
54
|
+
info "#{Time.now} : #{@socket.remote_ip} request action: #{action}"
|
55
|
+
before_process action, args
|
56
|
+
call_action action, *args
|
57
|
+
rescue JSON::ParserError
|
58
|
+
warn "#{Time.now} : #{@socket.remote_ip} message can't parse"
|
59
|
+
terminate
|
60
|
+
rescue StandardError => e
|
61
|
+
warn "#{Time.now} : #{@socket.remote_ip} want action: #{action} args: #{args} but process error:\n#{e.inspect}"
|
62
|
+
terminate
|
63
|
+
ensure
|
64
|
+
after_process action, args
|
65
|
+
end
|
66
|
+
|
67
|
+
def before_process action, args
|
68
|
+
end
|
69
|
+
|
70
|
+
def after_process action, args
|
71
|
+
end
|
72
|
+
|
73
|
+
def action_missing action, args
|
74
|
+
warn "#{Time.now} : #{socket.remote_ip} request action: #{action} args: #{args}, action not defined"
|
75
|
+
end
|
76
|
+
|
77
|
+
def command
|
78
|
+
@command || {}
|
79
|
+
end
|
80
|
+
|
81
|
+
def on_close
|
82
|
+
end
|
83
|
+
|
84
|
+
def run
|
85
|
+
while msg = @socket.read
|
86
|
+
process msg
|
87
|
+
if @closed
|
88
|
+
terminate
|
89
|
+
return
|
90
|
+
end
|
91
|
+
end
|
92
|
+
rescue Reel::SocketError, EOFError #client disconnect
|
93
|
+
info "#{Time.now} : #{@socket.remote_ip} disconnect, user: #{@user ? @user.id : "none"}"
|
94
|
+
begin
|
95
|
+
@closed = true unless @closed
|
96
|
+
on_close
|
97
|
+
ensure
|
98
|
+
terminate
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def finalizer
|
103
|
+
on_close unless @closed
|
104
|
+
ensure
|
105
|
+
@socket.close if @socket
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def setup
|
110
|
+
info "#{Time.now} : #{socket.remote_ip} coming"
|
111
|
+
after_connect
|
112
|
+
unless authentication
|
113
|
+
authentication_failed
|
114
|
+
else
|
115
|
+
after_authentication
|
116
|
+
async.run
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def call_action action, *args
|
121
|
+
if Actions.has_key? action
|
122
|
+
Actions[action].bind(self).call *args
|
123
|
+
else
|
124
|
+
action_missing action, args
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/hara/base.rb
ADDED
data/lib/hara/main.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'hara/base'
|
2
|
+
|
3
|
+
start_options = {host: 'localhost', port: 3210}
|
4
|
+
|
5
|
+
#like sinatra..
|
6
|
+
if ARGV.any?
|
7
|
+
require 'optparse'
|
8
|
+
OptionParser.new { |op|
|
9
|
+
op.on('-p port', "set the port (default is #{start_options[:port]})") { |val| start_options[:port] = val.to_i }
|
10
|
+
op.on('-o addr', "set the host (default is #{start_options[:host]})") { |val| srart_options[:host] = val }
|
11
|
+
op.on('-e env', 'set the environment (default is development)') { |val| Hara.env = val.to_sym }
|
12
|
+
}.parse!(ARGV.dup)
|
13
|
+
end
|
14
|
+
|
15
|
+
at_exit { Hara::Server.start(start_options[:host], start_options[:port]) if $!.nil? }
|
data/lib/hara/server.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'reel'
|
2
|
+
|
3
|
+
module Hara
|
4
|
+
class Server < Reel::Server
|
5
|
+
include Celluloid::Logger
|
6
|
+
|
7
|
+
def initialize host, port
|
8
|
+
info "Server starting on #{host}:#{port}"
|
9
|
+
super(host, port, &method(:on_connection))
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_connection(connection)
|
13
|
+
while request = connection.request
|
14
|
+
case request
|
15
|
+
when Reel::WebSocket
|
16
|
+
info "Received a WebSocket connection"
|
17
|
+
handle_websocket request
|
18
|
+
when Reel::Request
|
19
|
+
warn "Not support normal connection"
|
20
|
+
handle_request connection, request
|
21
|
+
else
|
22
|
+
warn "Not support normal connection"
|
23
|
+
request.close
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_request connection, request
|
29
|
+
request.close
|
30
|
+
end
|
31
|
+
|
32
|
+
def handle_websocket socket
|
33
|
+
Hara::Application.new socket
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.start host, port
|
37
|
+
self.supervise_as :hara, host, port
|
38
|
+
sleep
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/hara/version.rb
ADDED
data/lib/hara.rb
ADDED
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hara
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- jjy
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-06-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: reel
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.3'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0.3'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: bundler
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '1.3'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '1.3'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
description: Hara is a simple framework, help you build [web ]socket server. Power
|
63
|
+
by reel and celluloid.
|
64
|
+
email:
|
65
|
+
- jjyruby@gmail.com
|
66
|
+
executables: []
|
67
|
+
extensions: []
|
68
|
+
extra_rdoc_files: []
|
69
|
+
files:
|
70
|
+
- .gitignore
|
71
|
+
- Gemfile
|
72
|
+
- LICENSE.txt
|
73
|
+
- README.md
|
74
|
+
- Rakefile
|
75
|
+
- hara.gemspec
|
76
|
+
- lib/hara.rb
|
77
|
+
- lib/hara/app.rb
|
78
|
+
- lib/hara/base.rb
|
79
|
+
- lib/hara/main.rb
|
80
|
+
- lib/hara/server.rb
|
81
|
+
- lib/hara/version.rb
|
82
|
+
homepage: http://github.com/jjyr/hara
|
83
|
+
licenses:
|
84
|
+
- MIT
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.8.23
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Hara can help your build [web ]socket server easier.
|
107
|
+
test_files: []
|