Skip to content

Commit

Permalink
Replace HTTP::Server#tls with HTTP::Server#bind_ssl
Browse files Browse the repository at this point in the history
  • Loading branch information
straight-shoota committed Apr 17, 2018
1 parent 5bc5c87 commit 3f367f9
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 15 deletions.
29 changes: 29 additions & 0 deletions spec/std/http/server/server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
require "spec"
require "http/server"
{% unless flag?(:without_openssl) %}
require "../../../support/ssl"
{% end %}

private class RaiseErrno < IO
def initialize(@value : Int32)
Expand Down Expand Up @@ -284,6 +287,32 @@ module HTTP
end
end

{% unless flag?(:without_openssl) %}
describe "#bind_ssl" do
it "binds SSL server context" do
server = Server.new do |context|
context.response.puts "Test Server (#{context.request.headers["Host"]?})"
context.response.close
end

server_context, client_context = ssl_context_pair

socket = SSLServer.new(TCPServer.new("127.0.0.1", 0), server_context)
server.bind socket
ip_address1 = server.bind_ssl "127.0.0.1", 0, server_context
ip_address2 = socket.local_address

spawn server.listen
Fiber.yield

HTTP::Client.get("https://#{ip_address1}", tls: client_context).body.should eq "Test Server (#{ip_address1})\n"
HTTP::Client.get("https://#{ip_address2}", tls: client_context).body.should eq "Test Server (#{ip_address2})\n"

server.close
end
end
{% end %}

describe "#listen" do
it "fails after listen" do
server = Server.new { }
Expand Down
10 changes: 5 additions & 5 deletions spec/std/http/web_socket_spec.cr
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require "spec"
require "http/web_socket"
require "random/secure"
require "../../../support/ssl"

private def assert_text_packet(packet, size, final = false)
assert_packet packet, HTTP::WebSocket::Protocol::Opcode::TEXT, size, final: final
Expand Down Expand Up @@ -336,6 +337,8 @@ describe HTTP::WebSocket do
it "negotiates over HTTPS correctly" do
address_chan = Channel(Socket::IPAddress).new

server_context, client_context = ssl_context_pair

spawn do
http_ref = nil
ws_handler = HTTP::WebSocketHandler.new do |ws, ctx|
Expand All @@ -351,17 +354,14 @@ describe HTTP::WebSocket do
end

http_server = http_ref = HTTP::Server.new([ws_handler])
tls = http_server.tls = OpenSSL::SSL::Context::Server.new
tls.certificate_chain = File.join(__DIR__, "../openssl/ssl/openssl.crt")
tls.private_key = File.join(__DIR__, "../openssl/ssl/openssl.key")
address = http_server.bind_unused_port

address = http_server.bind_ssl("127.0.0.1", context: server_context)
address_chan.send(address)
http_server.listen
end

listen_address = address_chan.receive

client_context = OpenSSL::SSL::Context::Client.insecure
ws2 = HTTP::WebSocket.new(listen_address.address, port: listen_address.port, path: "/", tls: client_context)

random = Random::Secure.hex
Expand Down
2 changes: 2 additions & 0 deletions spec/support/ssl.cr
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
require "openssl"

def ssl_context_pair
server_context = OpenSSL::SSL::Context::Server.new
server_context.certificate_chain = File.join("spec", "std", "openssl", "ssl", "openssl.crt")
Expand Down
45 changes: 35 additions & 10 deletions src/http/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,6 @@ require "./common"
# server.listen
# ```
class HTTP::Server
{% if !flag?(:without_openssl) %}
property tls : OpenSSL::SSL::Context::Server?
{% end %}

@sockets = [] of Socket::Server

# Returns `true` if this server is closed.
Expand Down Expand Up @@ -162,6 +158,41 @@ class HTTP::Server
bind_tcp host, 0, reuse_port
end

# Creates a `SSLServer` and adds it as a socket.
#
# The SSL server wraps a `TCPServer` listenting on `host:port`.
#
# ```
# server = HTTP::Server.new { }
# context = OpenSSL::SSL::Context::Server.new
# context.certificate_chain = "openssl.crt"
# context.private_key = "openssl.key"
# server.bind_ssl "127.0.0.1", 8080, context
# ```
def bind_ssl(host : String, port : Int32, context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new, reuse_port : Bool = false) : Socket::IPAddress
tcp_server = TCPServer.new(host, port, reuse_port)
server = SSLServer.new(tcp_server, context)

bind(server)

tcp_server.local_address
end

# Creates a `SSLServer` and adds it as a socket.
#
# The SSL server wraps a `TCPServer` listenting on an unused port on *host*.
#
# ```
# server = HTTP::Server.new { }
# context = OpenSSL::SSL::Context::Server.new
# context.certificate_chain = "openssl.crt"
# context.private_key = "openssl.key"
# address = server.bind_ssl "127.0.0.1", context
# ```
def bind_ssl(host : String, context : OpenSSL::SSL::Context::Server = OpenSSL::SSL::Context::Server.new) : Socket::IPAddress
bind_ssl(host, 0, context)
end

# Adds a `Socket::Server` *socket* to this server.
def bind(socket : Socket::Server) : Nil
raise "Can't add socket to running server" if listening?
Expand Down Expand Up @@ -250,12 +281,6 @@ class HTTP::Server
io.sync = false
end

{% if !flag?(:without_openssl) %}
if tls = @tls
io = OpenSSL::SSL::Socket::Server.new(io, tls, sync_close: true)
end
{% end %}

@processor.process(io, io)
end

Expand Down

0 comments on commit 3f367f9

Please sign in to comment.