rity 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/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ gem "rake"
6
+ gem "awesome_print"
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Lars Gierth
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,15 @@
1
+ Evented Fiber-aware Ruby webserver
2
+ ==================================
3
+
4
+ Rity is a lightweight Ruby webserver that runs inside an EventMachine loop and puts each request into a fiber.
5
+
6
+ TODO
7
+ ----
8
+
9
+ - Tests (!)
10
+ - Command Line Interface
11
+ - Logging
12
+ - Proxying via EM.enable_proxy
13
+ - Rack Handler
14
+ - Support for keep-alive connections
15
+ - Investigate MVM support in JRuby/Rubinius/MRI
@@ -0,0 +1,11 @@
1
+ require "bundler"
2
+ Bundler.setup :default
3
+
4
+ task :default => :test
5
+
6
+ require "rake/testtask"
7
+ Rake::TestTask.new :test do |t|
8
+ t.test_files = FileList["test/*_test.rb"]
9
+ end
10
+
11
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rity/cli"
4
+ Rity::CLI.start
@@ -0,0 +1,4 @@
1
+ require "rity/connection"
2
+ require "rity/request"
3
+ require "rity/server"
4
+ require "rity/version"
@@ -0,0 +1,19 @@
1
+ require "rity"
2
+ require "thor"
3
+
4
+ module Rity
5
+ class CLI < Thor
6
+ map "--version" => :version, "-v" => :version
7
+
8
+ desc :version, "Print version information"
9
+ def version
10
+ say Rity::VERSION
11
+ end
12
+
13
+ desc :start, "Start an instance of Rity"
14
+ def start
15
+ server = Rity::Server.new
16
+ server.start
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,64 @@
1
+ require "eventmachine"
2
+ require "hatetepe"
3
+
4
+ require "rity/request"
5
+
6
+ module Rity
7
+ class Connection < EM::Connection
8
+ def initialize(app)
9
+ @app = app
10
+ @requests = []
11
+ end
12
+
13
+ def post_init
14
+ request = nil
15
+ @parser = Hatetepe::Parser.new do |p|
16
+ p.on_request do |verb, url|
17
+ request = Request.new(@app, verb, url)
18
+ @requests.push(request)
19
+ request.callback &@responder.method(:resume)
20
+ end
21
+
22
+ p.on_header do |name, value|
23
+ request.add_header(name, value)
24
+ end
25
+
26
+ p.on_headers_complete do
27
+ request.precall
28
+ end
29
+
30
+ p.on_body_chunk do |chunk|
31
+ request.add_body_chunk(chunk)
32
+ end
33
+
34
+ p.on_complete do
35
+ request.call
36
+ end
37
+ end
38
+
39
+ @builder = Hatetepe::Builder.new do |b|
40
+ b.on_write &method(:send_data)
41
+
42
+ b.on_complete do
43
+ close_connection_after_writing if @requests.empty?
44
+ end
45
+ end
46
+
47
+ @responder = Fiber.new do
48
+ loop do
49
+ while @requests[0] && @requests[0].response
50
+ request = @requests.shift
51
+ @builder.response(request.response)
52
+ end
53
+ Fiber.yield
54
+ end
55
+ end
56
+ end
57
+
58
+ def receive_data(data)
59
+ @parser << data
60
+ rescue Exception
61
+ close_connection
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ require "em/deferrable"
2
+ require "fiber"
3
+ require "stringio"
4
+
5
+ require "rack"
6
+ require "async-rack"
7
+
8
+ module Rity
9
+ class Request
10
+ include EM::Deferrable
11
+
12
+ attr_reader :app, :env, :response
13
+
14
+ def initialize(app, verb, url)
15
+ @app = app
16
+ @env = {
17
+ "REQUEST_METHOD" => verb,
18
+ "REQUEST_URI" => url,
19
+ "rack.input" => StringIO.new,
20
+ "async.callback" => method(:postcall)
21
+ }
22
+ end
23
+
24
+ def add_body_chunk(chunk)
25
+ env["rack.input"] << chunk
26
+ end
27
+
28
+ def add_header(name, value)
29
+ key = "HTTP_" + name.upcase.gsub("-", "_")
30
+ @env[key] = value
31
+ end
32
+
33
+ def precall
34
+ Fiber.new do
35
+ rescue_errors { app.precall(env) }
36
+ end.resume if app.respond_to?(:precall)
37
+ end
38
+
39
+ def call
40
+ env["rack.input"].close
41
+ env["rack.input"].rewind
42
+
43
+ Fiber.new do
44
+ rescue_errors { postcall(app.call(env)) }
45
+ end.resume
46
+ end
47
+
48
+ def postcall(response)
49
+ return if @response || response[0] < 0
50
+ @response = response
51
+ succeed
52
+ end
53
+
54
+ def rescue_errors
55
+ begin
56
+ yield
57
+ rescue Exception
58
+ postcall([500, {"Content-Type" => "text/html"},
59
+ ["<h1>#{Hatetepe::STATUS_CODES[500]}</h1>"]])
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ require "eventmachine"
2
+ require "em-synchrony"
3
+
4
+ require "rity/connection"
5
+
6
+ module Rity
7
+ class Server
8
+ def self.start(address, port, app)
9
+ EM.synchrony do
10
+ trap("INT") { EM.stop }
11
+ trap("TERM") { EM.stop }
12
+
13
+ EM.epoll
14
+
15
+ puts "Binding to #{address}:#{port}"
16
+ EM.start_server address, port, Connection, app
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ module Rity
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,20 @@
1
+ require "bundler"
2
+ Bundler.setup :default
3
+
4
+ require "rity"
5
+ require "awesome_print"
6
+
7
+ class MyApp
8
+ def call(env)
9
+ raise "Error, Error!"
10
+
11
+ response = [200, {"Content-Type" => "text/html"}, ["Hello!"]]
12
+ return response
13
+
14
+ EM.add_timer(2) { env["async.callback"].call(response) }
15
+
16
+ [-1, {}, []]
17
+ end
18
+ end
19
+
20
+ Rity::Server.start "127.0.0.1", 3000, MyApp.new
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "rity/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "rity"
7
+ s.version = Rity::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Lars Gierth"]
10
+ s.email = ["lars.gierth@gmail.com"]
11
+ s.homepage = "https://github.com/lgierth/rity"
12
+ s.summary = %q{Evented Fiber-aware Ruby webserver}
13
+ s.description = %q{Rity is a lightweight Ruby webserver that runs inside an EventMachine loop and puts each request into a fiber.}
14
+
15
+ s.add_dependency "eventmachine"
16
+ s.add_dependency "em-synchrony"
17
+ s.add_dependency "hatetepe"
18
+ s.add_dependency "rack"
19
+ s.add_dependency "async-rack"
20
+ s.add_dependency "thor"
21
+
22
+ s.files = `git ls-files`.split("\n") - [".gitignore"]
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata ADDED
@@ -0,0 +1,138 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rity
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Lars Gierth
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-07 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ requirement: &id001 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: "0"
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: em-synchrony
28
+ requirement: &id002 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *id002
37
+ - !ruby/object:Gem::Dependency
38
+ name: hatetepe
39
+ requirement: &id003 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *id003
48
+ - !ruby/object:Gem::Dependency
49
+ name: rack
50
+ requirement: &id004 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *id004
59
+ - !ruby/object:Gem::Dependency
60
+ name: async-rack
61
+ requirement: &id005 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: *id005
70
+ - !ruby/object:Gem::Dependency
71
+ name: thor
72
+ requirement: &id006 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: *id006
81
+ description: Rity is a lightweight Ruby webserver that runs inside an EventMachine loop and puts each request into a fiber.
82
+ email:
83
+ - lars.gierth@gmail.com
84
+ executables:
85
+ - rity
86
+ extensions: []
87
+
88
+ extra_rdoc_files: []
89
+
90
+ files:
91
+ - Gemfile
92
+ - LICENSE
93
+ - README.md
94
+ - Rakefile
95
+ - bin/rity
96
+ - lib/rity.rb
97
+ - lib/rity/cli.rb
98
+ - lib/rity/connection.rb
99
+ - lib/rity/request.rb
100
+ - lib/rity/server.rb
101
+ - lib/rity/version.rb
102
+ - myapp.rb
103
+ - rity.gemspec
104
+ homepage: https://github.com/lgierth/rity
105
+ licenses: []
106
+
107
+ post_install_message:
108
+ rdoc_options: []
109
+
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ hash: -1038596497
118
+ segments:
119
+ - 0
120
+ version: "0"
121
+ required_rubygems_version: !ruby/object:Gem::Requirement
122
+ none: false
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ hash: -1038596497
127
+ segments:
128
+ - 0
129
+ version: "0"
130
+ requirements: []
131
+
132
+ rubyforge_project:
133
+ rubygems_version: 1.8.2
134
+ signing_key:
135
+ specification_version: 3
136
+ summary: Evented Fiber-aware Ruby webserver
137
+ test_files: []
138
+