trusted 0.2.1 → 0.3.2

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,58 @@
1
+ use std::sync::mpsc::Sender;
2
+
3
+ use ruru::{AnyObject, Class, NilClass, Object};
4
+
5
+ use ruby::Response;
6
+ use response::Response as RustResponse;
7
+
8
+ lazy_static! {
9
+ static ref OBSERVER_CLASS: Class = {
10
+ Class::from_existing("Trusted")
11
+ .get_nested_class("Request")
12
+ .get_nested_class("Observer")
13
+ };
14
+ }
15
+
16
+ pub struct ObserverData {
17
+ sender: Sender<RustResponse>,
18
+ }
19
+
20
+ wrappable_struct!(ObserverData, ObserverWrapper, OBSERVER_DATA_TYPE);
21
+
22
+ class!(Observer);
23
+
24
+ unsafe_methods!(
25
+ Observer,
26
+ itself,
27
+
28
+ // This method is called when the `Future` finishes its execution
29
+ // (when request is processed by Rack stack)
30
+ //
31
+ // Extract `Sender` which points to the corresponding Hyper handler and
32
+ // send response to it
33
+ fn update(_time: AnyObject, response: Response, _reason: AnyObject) -> NilClass {
34
+ let data = itself.get_data(&*OBSERVER_DATA_TYPE);
35
+
36
+ data.sender.send(response.into()).unwrap();
37
+
38
+ NilClass::new()
39
+ }
40
+ );
41
+
42
+ impl Observer {
43
+ pub fn define_ruby_class() {
44
+ let data_class = Class::from_existing("Data");
45
+
46
+ Class::from_existing("Trusted")
47
+ .get_nested_class("Request")
48
+ .define_nested_class("Observer", Some(&data_class))
49
+ .define(|itself| {
50
+ itself.def("update", update);
51
+ });
52
+ }
53
+
54
+ pub fn new(sender: Sender<RustResponse>) -> Self {
55
+ let observer_data = ObserverData { sender: sender };
56
+ (*OBSERVER_CLASS).wrap_data(observer_data, &*OBSERVER_DATA_TYPE)
57
+ }
58
+ }
@@ -0,0 +1,17 @@
1
+ use ruru::Object;
2
+
3
+ use ruby::request::Observer;
4
+ use ruby::Response;
5
+ use ruby::Request;
6
+
7
+ class!(ProcessingPool);
8
+
9
+ impl ProcessingPool {
10
+ pub fn process(&self, request: Request, response: Response, observer: Observer) {
11
+ let args = vec![request.to_any_object(),
12
+ response.to_any_object(),
13
+ observer.to_any_object()];
14
+
15
+ self.send("execute_future", args);
16
+ }
17
+ }
@@ -0,0 +1,84 @@
1
+ use std::convert::From;
2
+
3
+ use ruru::{Class, Hash, Object, RString};
4
+
5
+ use request::{REQUEST_DATA_TYPE, Request as RustRequest};
6
+
7
+ lazy_static! {
8
+ static ref REQUEST_CLASS: Class = {
9
+ Class::from_existing("Trusted").get_nested_class("Request").get_nested_class("Request")
10
+ };
11
+ }
12
+
13
+ class!(Request);
14
+
15
+ methods!(
16
+ Request,
17
+ itself,
18
+
19
+ fn method() -> RString {
20
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).method())
21
+ }
22
+
23
+ fn uri() -> RString {
24
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).url())
25
+ }
26
+
27
+ fn path_info() -> RString {
28
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).path_info())
29
+ }
30
+
31
+ fn query_string() -> RString {
32
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).query_string())
33
+ }
34
+
35
+ fn remote_addr() -> RString {
36
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).remote_addr())
37
+ }
38
+
39
+ fn server_port() -> RString {
40
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).server_port())
41
+ }
42
+
43
+ fn headers() -> Hash {
44
+ let mut headers = Hash::new();
45
+
46
+ for header in itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).headers().iter() {
47
+ let field = header.name().to_string().replace("-", "_").to_uppercase();
48
+ let value = header.value_string();
49
+
50
+ let field = format!("HTTP_{}", field);
51
+
52
+ headers.store(RString::new(&field), RString::new(&value));
53
+ }
54
+
55
+ headers
56
+ }
57
+
58
+ fn body() -> RString {
59
+ RString::new(itself.get_data::<RustRequest>(&*REQUEST_DATA_TYPE).body())
60
+ }
61
+ );
62
+
63
+ impl Request {
64
+ pub fn define_ruby_class() {
65
+ Class::from_existing("Trusted")
66
+ .get_nested_class("Request")
67
+ .define_nested_class("Request", None).define(|itself| {
68
+ itself.def("method", method);
69
+ itself.def("uri", uri);
70
+ itself.def("path_info", path_info);
71
+ itself.def("query_string", query_string);
72
+ itself.def("remote_addr", remote_addr);
73
+ itself.def("server_port", server_port);
74
+ itself.def("headers", headers);
75
+ itself.def("body", body);
76
+ });
77
+ }
78
+ }
79
+
80
+ impl From<RustRequest> for Request {
81
+ fn from(request: RustRequest) -> Self {
82
+ (*REQUEST_CLASS).wrap_data(request, &*REQUEST_DATA_TYPE)
83
+ }
84
+ }
@@ -10,6 +10,14 @@ lazy_static! {
10
10
  class!(Response);
11
11
 
12
12
  impl Response {
13
+ pub fn define_ruby_class() {
14
+ Class::from_existing("Trusted").define_nested_class("Response", None).define(|itself| {
15
+ itself.attr_accessor("status");
16
+ itself.attr_accessor("headers");
17
+ itself.attr_accessor("body");
18
+ });
19
+ }
20
+
13
21
  pub fn new() -> Self {
14
22
  let response = (*RESPONSE_CLASS).new_instance(vec![]);
15
23
 
@@ -1,8 +1,10 @@
1
1
  use std::error::Error;
2
2
 
3
- use ruru::{Class, NilClass, RString, Object, VM};
3
+ use ruru::{Class, NilClass, Object, VM};
4
4
 
5
- use server::Server as RustServer;
5
+ use core::Server as RustServer;
6
+ use config::Config as RustConfig;
7
+ use ruby::Config;
6
8
 
7
9
  class!(Server);
8
10
 
@@ -10,12 +12,12 @@ methods!(
10
12
  Server,
11
13
  itself,
12
14
 
13
- fn initialize(addr: RString) -> Server {
14
- if let Err(ref error) = addr {
15
+ fn initialize(config: Config) -> Server {
16
+ if let Err(ref error) = config {
15
17
  VM::raise(error.to_exception(), error.description());
16
18
  }
17
19
 
18
- itself.instance_variable_set("@addr", addr.unwrap());
20
+ itself.instance_variable_set("@config", config.unwrap());
19
21
 
20
22
  itself
21
23
  }
@@ -23,10 +25,10 @@ methods!(
23
25
  fn listen() -> NilClass {
24
26
  let handler = VM::block_proc();
25
27
 
26
- // We can use unsafe here, because the type of addr is checked in the constructor
27
- let addr = unsafe { itself.instance_variable_get("@addr").to::<RString>().to_string() };
28
+ // We can use unsafe here, because the type of @config is checked in the constructor
29
+ let config = unsafe { itself.instance_variable_get("@config").to::<Config>() };
28
30
 
29
- RustServer::new(addr).listen(handler);
31
+ RustServer::new(RustConfig::from(config)).listen(handler);
30
32
 
31
33
  NilClass::new()
32
34
  }
@@ -6,12 +6,11 @@ module Rack
6
6
  module Handler
7
7
  class Trusted
8
8
  def self.run(app, options = {})
9
- ::Trusted::Server.new("0.0.0.0:3000").listen do |request, response|
9
+ config = options[:trusted_config] || ::Trusted::Config::Builder.new.build
10
+
11
+ ::Trusted::Server.new(config).listen do |request, response|
10
12
  puts "REQUEST: [#{request.method}] #{request.uri}"
11
13
  puts "PATH_INFO: #{request.path_info}"
12
- puts "QUERY_STRING: #{request.query_string}"
13
- puts "REMOTE_ADDR: #{request.remote_addr.inspect}"
14
- puts "SERVER_PORT: #{request.server_port.inspect}"
15
14
  puts "REQUEST HEADERS: #{request.headers.inspect}"
16
15
 
17
16
  rack_input = StringIO::new(request.body)
@@ -28,7 +27,7 @@ module Rack
28
27
  'rack.version' => Rack::VERSION,
29
28
  'rack.input' => rack_input,
30
29
  'rack.errors' => $stderr,
31
- 'rack.multithread' => false,
30
+ 'rack.multithread' => true,
32
31
  'rack.multiprocess' => false,
33
32
  'rack.run_once' => false,
34
33
  'rack.url_scheme' => 'http',
@@ -47,6 +46,8 @@ module Rack
47
46
  body.each { |b| response.body.concat(b) }
48
47
 
49
48
  body.close if body.respond_to?(:close)
49
+
50
+ response
50
51
  end
51
52
  end
52
53
  end
@@ -0,0 +1,39 @@
1
+ module Trusted
2
+ module Config
3
+ class Builder
4
+ attr_reader :config
5
+
6
+ DEFAULT_CONFIG = {
7
+ binding_type: :tcp,
8
+ listen_on: 'localhost:3000',
9
+ thread_pool_size: 1,
10
+ }.freeze
11
+
12
+ def self.dsl(&block)
13
+ Docile.dsl_eval(new, &block).build
14
+ end
15
+
16
+ def initialize
17
+ @config = {}
18
+ end
19
+
20
+ def binding_type(type)
21
+ config[:binding_type] = type
22
+ end
23
+
24
+ def listen_on(address)
25
+ config[:listen_on] = address
26
+ end
27
+
28
+ def thread_pool_size(size)
29
+ config[:thread_pool_size] = size
30
+ end
31
+
32
+ def build
33
+ configuration = DEFAULT_CONFIG.merge(config)
34
+
35
+ Config.new(configuration)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,13 @@
1
+ module Trusted
2
+ module Config
3
+ class Config
4
+ attr_reader :binding_type, :listen_on, :thread_pool_size
5
+
6
+ def initialize(configuration)
7
+ @binding_type = configuration[:binding_type]
8
+ @listen_on = configuration[:listen_on]
9
+ @thread_pool_size = configuration[:thread_pool_size]
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,23 @@
1
+ module Trusted
2
+ module Request
3
+ class ProcessingPool
4
+ attr_reader :handler, :thread_pool
5
+
6
+ def initialize(handler, thread_pool_size)
7
+ @handler = handler
8
+ @thread_pool = Concurrent::FixedThreadPool.new(thread_pool_size)
9
+
10
+ puts "[ruby] Spawning #{thread_pool_size} green thread(s)"
11
+ end
12
+
13
+ private
14
+
15
+ def execute_future(request, response, observer)
16
+ future = Concurrent::Future.new(executor: thread_pool, args: [request, response], &handler)
17
+
18
+ future.add_observer(observer)
19
+ future.execute
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,3 +1,3 @@
1
1
  module Trusted
2
- VERSION = '0.2.1'
2
+ VERSION = '0.3.2'
3
3
  end
data/lib/trusted.rb CHANGED
@@ -1,18 +1,20 @@
1
- require 'fiddle'
1
+ require 'concurrent'
2
+ require 'docile'
3
+ require 'thermite/fiddle'
4
+
5
+ require 'trusted/config/builder'
6
+ require 'trusted/config/config'
7
+
8
+ require 'trusted/request/processing_pool'
2
9
 
3
- require 'trusted/request'
4
- require 'trusted/response'
5
10
  require 'trusted/version'
6
11
 
7
12
  require 'rack/handler/trusted'
8
13
 
9
- library_path = File.expand_path(
10
- File.join(File.dirname(__FILE__), 'libtrusted.dylib')
11
- )
14
+ toplevel_dir = File.dirname(File.dirname(__FILE__))
12
15
 
13
- library = Fiddle::dlopen(library_path)
14
- function = Fiddle::Function.new(library['initialize_my_app'], [], Fiddle::TYPE_VOIDP)
15
- function.call
16
-
17
- module Trusted
18
- end
16
+ Thermite::Fiddle.load_module(
17
+ 'initialize_my_app',
18
+ ruby_project_path: toplevel_dir,
19
+ cargo_project_path: File.join(toplevel_dir, 'ext', 'trusted')
20
+ )
data/trusted.gemspec CHANGED
@@ -17,13 +17,17 @@ Gem::Specification.new do |spec|
17
17
  spec.extensions << 'Rakefile'
18
18
 
19
19
  spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20
- spec.bindir = 'exe'
21
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ['lib']
20
+ spec.bindir = 'bin'
21
+ spec.executables = %w(trusted)
22
+ spec.require_paths = %w(lib)
23
23
 
24
- spec.add_dependency 'thermite', '~> 0.6.0'
24
+ spec.add_dependency 'concurrent-ruby', '~> 1.0'
25
+ spec.add_dependency 'docile', '~> 1.1'
26
+ spec.add_dependency 'rack', '>= 1.0', '< 3.0'
27
+ spec.add_dependency 'thermite', '~> 0.7.0'
25
28
 
26
29
  spec.add_development_dependency 'bundler', '~> 1.10'
27
30
  spec.add_development_dependency 'rake', '~> 10.0'
28
- spec.add_development_dependency 'rspec'
31
+ spec.add_development_dependency 'rspec', '~> 3.5'
32
+ spec.add_development_dependency 'rspec-its', '~> 1.2'
29
33
  end
metadata CHANGED
@@ -1,29 +1,77 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trusted
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Gritsay
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-04 00:00:00.000000000 Z
11
+ date: 2016-12-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: concurrent-ruby
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: docile
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ - - "<"
49
+ - !ruby/object:Gem::Version
50
+ version: '3.0'
51
+ type: :runtime
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: '1.0'
58
+ - - "<"
59
+ - !ruby/object:Gem::Version
60
+ version: '3.0'
13
61
  - !ruby/object:Gem::Dependency
14
62
  name: thermite
15
63
  requirement: !ruby/object:Gem::Requirement
16
64
  requirements:
17
65
  - - "~>"
18
66
  - !ruby/object:Gem::Version
19
- version: 0.6.0
67
+ version: 0.7.0
20
68
  type: :runtime
21
69
  prerelease: false
22
70
  version_requirements: !ruby/object:Gem::Requirement
23
71
  requirements:
24
72
  - - "~>"
25
73
  - !ruby/object:Gem::Version
26
- version: 0.6.0
74
+ version: 0.7.0
27
75
  - !ruby/object:Gem::Dependency
28
76
  name: bundler
29
77
  requirement: !ruby/object:Gem::Requirement
@@ -56,20 +104,35 @@ dependencies:
56
104
  name: rspec
57
105
  requirement: !ruby/object:Gem::Requirement
58
106
  requirements:
59
- - - ">="
107
+ - - "~>"
60
108
  - !ruby/object:Gem::Version
61
- version: '0'
109
+ version: '3.5'
62
110
  type: :development
63
111
  prerelease: false
64
112
  version_requirements: !ruby/object:Gem::Requirement
65
113
  requirements:
66
- - - ">="
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '3.5'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rspec-its
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.2'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
67
129
  - !ruby/object:Gem::Version
68
- version: '0'
130
+ version: '1.2'
69
131
  description: Write a longer description or delete this line.
70
132
  email:
71
133
  - unseductable@gmail.com
72
- executables: []
134
+ executables:
135
+ - trusted
73
136
  extensions:
74
137
  - Rakefile
75
138
  extra_rdoc_files: []
@@ -84,21 +147,33 @@ files:
84
147
  - Rakefile
85
148
  - bin/console
86
149
  - bin/setup
150
+ - bin/trusted
87
151
  - ext/trusted/Cargo.toml
88
- - ext/trusted/src/handler.rs
152
+ - ext/trusted/src/config/binding_type.rs
153
+ - ext/trusted/src/config/config.rs
154
+ - ext/trusted/src/config/mod.rs
155
+ - ext/trusted/src/core/channel.rs
156
+ - ext/trusted/src/core/core.rs
157
+ - ext/trusted/src/core/handler.rs
158
+ - ext/trusted/src/core/mod.rs
159
+ - ext/trusted/src/core/server.rs
89
160
  - ext/trusted/src/lib.rs
90
161
  - ext/trusted/src/request.rs
91
162
  - ext/trusted/src/request_processor.rs
92
163
  - ext/trusted/src/response.rs
164
+ - ext/trusted/src/ruby/config.rs
93
165
  - ext/trusted/src/ruby/mod.rs
94
- - ext/trusted/src/ruby/request.rs
166
+ - ext/trusted/src/ruby/request/mod.rs
167
+ - ext/trusted/src/ruby/request/observer.rs
168
+ - ext/trusted/src/ruby/request/processing_pool.rs
169
+ - ext/trusted/src/ruby/request/request.rs
95
170
  - ext/trusted/src/ruby/response.rs
96
171
  - ext/trusted/src/ruby/server.rs
97
- - ext/trusted/src/server.rs
98
172
  - lib/rack/handler/trusted.rb
99
173
  - lib/trusted.rb
100
- - lib/trusted/request.rb
101
- - lib/trusted/response.rb
174
+ - lib/trusted/config/builder.rb
175
+ - lib/trusted/config/config.rb
176
+ - lib/trusted/request/processing_pool.rb
102
177
  - lib/trusted/version.rb
103
178
  - trusted.gemspec
104
179
  homepage: http://this-week-in-ruru.org/
@@ -1,55 +0,0 @@
1
- use std::io::Write;
2
- use std::sync::Mutex;
3
- use std::sync::mpsc::{Sender, Receiver};
4
-
5
- use hyper::server::{Handler as HyperHandler, Request as HyperRequest, Response as HyperResponse};
6
- use hyper::status::StatusCode;
7
-
8
- use request::Request;
9
- use response::Response;
10
-
11
- pub struct Handler {
12
- sender: Mutex<Sender<Request>>,
13
- receiver: Mutex<Receiver<Response>>,
14
- }
15
-
16
- impl Handler {
17
- pub fn new(sender: Sender<Request>, receiver: Receiver<Response>) -> Self {
18
- Handler {
19
- sender: Mutex::new(sender),
20
- receiver: Mutex::new(receiver),
21
- }
22
- }
23
- }
24
-
25
- impl HyperHandler for Handler {
26
- fn handle(&self, hyper_request: HyperRequest, mut hyper_response: HyperResponse) {
27
- println!("[hyper] New request received");
28
-
29
- self.sender.lock().unwrap().send(hyper_request.into()).unwrap();
30
-
31
- println!("[hyper] Sent to main thread");
32
-
33
- let response = self.receiver.lock().unwrap().recv().unwrap();
34
-
35
- println!("[hyper] Received response from main thread");
36
-
37
- {
38
- let headers = hyper_response.headers_mut();
39
- *headers = response.headers;
40
- }
41
-
42
- {
43
- let status = hyper_response.status_mut();
44
- *status = StatusCode::from_u16(response.status);
45
- }
46
-
47
- println!("[hyper] Starting to send response to client");
48
-
49
- let mut res = hyper_response.start().unwrap();
50
- res.write_all(response.body.as_bytes()).unwrap();
51
-
52
- println!("[hyper] Response successfully sent to client");
53
- println!("[hyper] ------------------------------------")
54
- }
55
- }
@@ -1,44 +0,0 @@
1
- use std::convert::From;
2
-
3
- use ruru::{Class, Hash, Object, RString};
4
-
5
- use request::Request as RustRequest;
6
-
7
- lazy_static! {
8
- static ref REQUEST_CLASS: Class = {
9
- Class::from_existing("Trusted").get_nested_class("Request")
10
- };
11
- }
12
-
13
- class!(Request);
14
-
15
- impl From<RustRequest> for Request {
16
- fn from(request: RustRequest) -> Self {
17
- let mut headers = Hash::new();
18
-
19
- for header in request.headers.iter() {
20
- let field = header.name().to_string().replace("-", "_").to_uppercase();
21
- let value = header.value_string();
22
-
23
- let field = format!("HTTP_{}", field);
24
-
25
- headers.store(RString::new(&field), RString::new(&value));
26
- }
27
-
28
- let request = (*REQUEST_CLASS).new_instance(
29
- vec![
30
- RString::new(&request.method).to_any_object(),
31
- RString::new(&request.url).to_any_object(),
32
- RString::new(&request.path_info).to_any_object(),
33
- RString::new(&request.query_string).to_any_object(),
34
- RString::new(&request.remote_addr).to_any_object(),
35
- RString::new(&request.server_port).to_any_object(),
36
- headers.to_any_object(),
37
- RString::new(&request.body).to_any_object(),
38
- ]
39
- );
40
-
41
- // We can use unsafe here, because request is created by our own code
42
- unsafe { request.to::<Self>() }
43
- }
44
- }