Skip to content
This repository has been archived by the owner on Dec 7, 2018. It is now read-only.

Commit

Permalink
Merge 21bbc1c into 1a3061c
Browse files Browse the repository at this point in the history
  • Loading branch information
digitalextremist committed Mar 24, 2015
2 parents 1a3061c + 21bbc1c commit 300004f
Show file tree
Hide file tree
Showing 10 changed files with 120 additions and 46 deletions.
30 changes: 25 additions & 5 deletions CHANGES.md
@@ -1,5 +1,25 @@
0.6.0 (2015-03-24)
-----
* Fix stack level too deep when writing to ChunkStream
* Use HTTP::Resonse::Status::REASONS table ( HTTP::Response::* deprecated in the HTTP gem )
* Use Timers 3.0.0 API
* Case-insensitivity for header field names ( i.e. in case a proxy downcases them )
* Catch when openssl sometimes fires ECONNRESET, EPIPE, ETIMEDOUT, EHOSTUNREACH and as an error
* Unused `optimize` socket modifications taken off all server implementations
* Fixed 404 error in roundtrip example
* Fixed "Reel::StateError: already processing a request" when client is killed
* Numerous updates to rspec.
* Switched to websocket/driver and improved websocket handling
* Implement DriverEnvironment to fix websocket example
* Refactored Server::HTTPS to be more idomatic
* Fixed jRuby related test failures
* Fixed "ArgumentError: Data object has already been freed" caused by underlying parser.
* FINALLY! Support for UNIX Socket servers across all RVM's, as of jRuby 1.7.19
* Unified Server#run removes need for duplication of #run across all Server implementations.
* Standardized method of rescuing exceptions unique to each type of Server in unified #run method.

0.5.0 (2014-04-15)
------------------
-----
* Reel::Server(::SSL) renamed to Reel::Server::HTTP and Reel::Server::HTTPS
* New Reel::Spy API for observing requests and responses from the server
* Fixes to chunked encoding handling
Expand All @@ -8,7 +28,7 @@
* Ensure response bodies are always closed
* Support for passing a fixnum status to Connection#respond

0.4.0
0.4.0 (2013-09-14)
-----
* Rack adapter moved to the reel-rack project
* Pipelining support
Expand All @@ -23,7 +43,7 @@
* Remove Reel::App (unmaintained, sorry)
* Reel::CODENAME added (0.4.0 is "Garbo")

0.3.0
0.3.0 (2013-02-01)
-----
* Reel::App: Sinatra-like DSL for defining Reel apps using Octarine
* Chunked upload support
Expand All @@ -33,12 +53,12 @@
* Bugfix: Send CRLF after chunks
* Bugfix: Increase TCP connection backlog to 1024

0.2.0
0.2.0 (2012-09-03)
-----
* Initial WebSockets support via Reel::WebSocket
* Experimental Rack adapter by Alberto Fernández-Capel
* Octarine (Sinatra-like DSL) support by Grant Rodgers

0.1.0
0.1.0 (2012-07-12)
-----
* Initial release
1 change: 1 addition & 0 deletions lib/reel.rb
Expand Up @@ -14,6 +14,7 @@
require 'reel/server'
require 'reel/server/http'
require 'reel/server/https'
require 'reel/server/unix' unless defined? JRUBY_VERSION

require 'reel/websocket'
require 'reel/stream'
Expand Down
2 changes: 1 addition & 1 deletion lib/reel/connection.rb
Expand Up @@ -56,7 +56,7 @@ def request

req = @parser.current_request
@request_fsm.transition :headers
@keepalive = false if req[CONNECTION] == CLOSE || req.version == HTTP_VERSION_1_0
@keepalive = false if req.nil? || req[CONNECTION] == CLOSE || req.version == HTTP_VERSION_1_0
@current_request = req

req
Expand Down
6 changes: 5 additions & 1 deletion lib/reel/request/parser.rb
Expand Up @@ -43,7 +43,11 @@ def current_request

def readpartial(size = @buffer_size)
bytes = @socket.readpartial(size)
@parser << bytes
begin
@parser << bytes
rescue ArgumentError
raise Errno::EPIPE
end
end

#
Expand Down
25 changes: 21 additions & 4 deletions lib/reel/server.rb
Expand Up @@ -2,14 +2,14 @@ module Reel
# Base class for Reel servers.
#
# This class is a Celluloid::IO actor which provides a barebones server
# which does not open a socket itself, it just begin handling connections once
# initialized with a specific kind of protocol-based server.
# which does not open a socket itself, it just begin handling connections
# once initialized with a specific kind of protocol-based server.

# For specific protocol support, use:

# Reel::Server::HTTP
# Reel::Server::HTTPS
# Coming soon: Reel::Server::UNIX
# Reel::Server::UNIX ( not on jRuby yet )

class Server
include Celluloid::IO
Expand All @@ -25,6 +25,15 @@ def initialize(server, options={}, &callback)
@callback = callback
@server = server

@options[:rescue] ||= []
@options[:rescue] += [
Errno::ECONNRESET,
Errno::EPIPE,
Errno::EINPROGRESS,
Errno::ETIMEDOUT,
Errno::EHOSTUNREACH
]

@server.listen(options.fetch(:backlog, DEFAULT_BACKLOG))

async.run
Expand All @@ -35,7 +44,15 @@ def shutdown
end

def run
loop { async.handle_connection @server.accept }
loop {
begin
socket = @server.accept
rescue *@options[:rescue] => ex
Logger.warn "Error accepting socket: #{ex.class}: #{ex.to_s}"
next
end
async.handle_connection socket
}
end

def handle_connection(socket)
Expand Down
23 changes: 5 additions & 18 deletions lib/reel/server/https.rb
Expand Up @@ -27,12 +27,11 @@ def initialize(host, port, options={}, &callback)

# if verify_mode isn't explicitly set, verify peers if we've
# been provided CA information that would enable us to do so
ssl_context.verify_mode = case
when options.include?(:verify_mode)
ssl_context.verify_mode = if options.include?(:verify_mode)
options[:verify_mode]
when options.include?(:ca_file)
elsif options.include?(:ca_file)
OpenSSL::SSL::VERIFY_PEER
when options.include?(:ca_path)
elsif options.include?(:ca_path)
OpenSSL::SSL::VERIFY_PEER
else
OpenSSL::SSL::VERIFY_NONE
Expand All @@ -43,22 +42,10 @@ def initialize(host, port, options={}, &callback)
server = Celluloid::IO::SSLServer.new(@tcpserver, ssl_context)
options.merge!(host: host, port: port)

options[:rescue] = [ OpenSSL::SSL::SSLError ]

super(server, options, &callback)
end

def run
loop do
begin
socket = @server.accept
rescue OpenSSL::SSL::SSLError, Errno::ECONNRESET, Errno::EPIPE,
Errno::ETIMEDOUT, Errno::EHOSTUNREACH => ex
Logger.warn "Error accepting SSLSocket: #{ex.class}: #{ex.to_s}"
retry
end

async.handle_connection socket
end
end
end
end
end
18 changes: 18 additions & 0 deletions lib/reel/server/unix.rb
@@ -0,0 +1,18 @@
module Reel
class Server
class UNIX < Server

# Create a new Reel HTTPS server
#
# @option options [String] socket path to bind to
# @option options [Fixnum] backlog of requests to accept
#
# @return [Reel::Server::UNIX] Reel UNIX server actor
def initialize(socket_path, options={}, &callback)
server = Celluloid::IO::UNIXServer.new(socket_path)
options[:socket_path] = socket_path
super(server, options, &callback)
end
end
end
end
3 changes: 0 additions & 3 deletions spec/reel/http_server_spec.rb
Expand Up @@ -14,9 +14,7 @@
expect(request.method).to eq 'GET'
expect(request.version).to eq "1.1"
expect(request.url).to eq example_path

connection.respond :ok, response_body
rescue => ex
end
end

Expand All @@ -36,7 +34,6 @@
request = connection.request
expect(request.method).to eq 'POST'
connection.respond :ok, request.body.to_s
rescue => ex
end
end

Expand Down
17 changes: 3 additions & 14 deletions spec/reel/https_server_spec.rb
Expand Up @@ -2,6 +2,7 @@
require 'net/http'

RSpec.describe Reel::Server::HTTPS do

let(:example_https_port) { example_port + 1 }
let(:example_url) { "https://#{example_addr}:#{example_https_port}#{example_path}" }
let(:endpoint) { URI(example_url) }
Expand All @@ -24,27 +25,23 @@
expect(request.method).to eq 'GET'
expect(request.version).to eq "1.1"
expect(request.url).to eq example_path

connection.respond :ok, response_body
rescue => ex
end
end

with_reel_https_server(handler) do
http = Net::HTTP.new(endpoint.host, endpoint.port)
http.use_ssl = true
http.ca_file = self.ca_file

request = Net::HTTP::Get.new(endpoint.path)
response = http.request(request)

expect(response.body).to eq response_body
end

raise ex if ex
end

it 'verifies client SSL certs when provided with a CA' do
it "verifies client SSL certs when provided with a CA" do
ex = nil

handler = proc do |connection|
Expand All @@ -53,9 +50,7 @@
expect(request.method).to eq 'GET'
expect(request.version).to eq '1.1'
expect(request.url).to eq example_path

connection.respond :ok, response_body
rescue => ex
end
end

Expand All @@ -65,17 +60,15 @@
http.ca_file = self.ca_file
http.cert = OpenSSL::X509::Certificate.new self.client_cert
http.key = OpenSSL::PKey::RSA.new self.client_key

request = Net::HTTP::Get.new(endpoint.path)
response = http.request(request)

expect(response.body).to eq response_body
end

raise ex if ex
end

it %{fails to verify client certificates that aren't signed} do
it "fails to verify client certificates that aren't signed" do
ex = nil

handler = proc do |connection|
Expand All @@ -84,9 +77,7 @@
expect(request.method).to eq 'GET'
expect(request.version).to eq '1.1'
expect(request.url).to eq example_path

connection.respond :ok, response_body
rescue => ex
end
end

Expand All @@ -96,9 +87,7 @@
http.ca_file = self.ca_file
http.cert = OpenSSL::X509::Certificate.new self.client_cert_unsigned
http.key = OpenSSL::PKey::RSA.new self.client_key

request = Net::HTTP::Get.new(endpoint.path)

expect { http.request(request) }.to raise_error(OpenSSL::SSL::SSLError)
end

Expand Down
41 changes: 41 additions & 0 deletions spec/reel/unix_server_spec.rb
@@ -0,0 +1,41 @@
require 'spec_helper'
require 'net/http'

unless defined?(JRUBY_VERSION)

RSpec.describe Reel::Server::UNIX do
let(:endpoint) { URI(example_url) }
let(:response_body) { "ohai thar" }

it 'allows connections over UNIX sockets' do
ex = nil

handler = proc do |connection|
begin
request = connection.request
expect( request.method ).to eq 'GET'
connection.respond :ok, self.response_body
end
end

Dir::Tmpname.create('reel-sock') do |path|
begin
server = Reel::Server::UNIX.new(path, &handler)
sock = Net::BufferedIO.new Celluloid::IO::UNIXSocket.new(path)
request = Net::HTTP::Get.new('/')

request.exec(sock, '1.1', path)
response = Net::HTTPResponse.read_new(sock)
response.reading_body(sock, request.response_body_permitted?) { }

expect(response.body).to eq(self.response_body)
ensure
server.terminate if server && server.alive?
end
end

raise ex if ex
end
end

end

0 comments on commit 300004f

Please sign in to comment.