Skip to content

Commit

Permalink
Remove HTTP::Server#port and add HTTP::Server#bind_unused_port
Browse files Browse the repository at this point in the history
The return type is now an IPAddress instead of only the port number.
  • Loading branch information
straight-shoota committed Mar 14, 2018
1 parent c3635e1 commit c6306a4
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 44 deletions.
38 changes: 18 additions & 20 deletions spec/std/http/server/server_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -194,22 +194,19 @@ module HTTP
end

describe HTTP::Server do
it "re-sets special port zero after bind" do
it "binds to unused port" do
server = Server.new { |ctx| }
server.bind 0
server.port.should_not eq(0)
end
address = server.bind_unused_port
address.port.should_not eq(0)

it "re-sets port to nil after close" do
server = Server.new { |ctx| }
server.bind 0
server.close
server.port.should be_nil
port = server.bind(0).local_address.port
port.should_not eq(0)
end

it "doesn't raise on accept after close #2692" do
server = Server.new { }
server.bind "0.0.0.0", 0
server.bind_unused_port

spawn do
server.close
Expand All @@ -221,34 +218,35 @@ module HTTP

it "reuses the TCP port (SO_REUSEPORT)" do
s1 = Server.new { |ctx| }
s1.bind(0, reuse_port: true)
address = s1.bind_unused_port(reuse_port: true)

s2 = Server.new { |ctx| }
s2.bind(s1.port.not_nil!, reuse_port: true)
s2.bind(address.port, reuse_port: true)

s1.close
s2.close
end

it "binds to different interfaces" do
it "binds to different ports" do
server = Server.new do |context|
context.response.print "Test Server (#{context.request.headers["Host"]?})"
end

interface1 = server.bind(0)
interface2 = server.bind(0)
tcp_server = TCPServer.new("127.0.0.1", 0)
server.bind tcp_server
address1 = tcp_server.local_address

address2 = server.bind_unused_port

port1 = interface1.local_address.port
port2 = interface2.local_address.port
port1.should_not eq port2
address1.should_not eq address2

spawn { server.listen }

Fiber.yield

HTTP::Client.get("http://127.0.0.1:#{port2}/").body.should eq "Test Server (127.0.0.1:#{port2})"
HTTP::Client.get("http://127.0.0.1:#{port1}/").body.should eq "Test Server (127.0.0.1:#{port1})"
HTTP::Client.get("http://127.0.0.1:#{port1}/").body.should eq "Test Server (127.0.0.1:#{port1})"
HTTP::Client.get("http://#{address2}/").body.should eq "Test Server (#{address2})"
HTTP::Client.get("http://#{address1}/").body.should eq "Test Server (#{address1})"
HTTP::Client.get("http://#{address1}/").body.should eq "Test Server (#{address1})"
end
end

Expand Down
8 changes: 4 additions & 4 deletions spec/std/http/web_socket_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,8 @@ describe HTTP::WebSocket do
end

http_server = http_ref = HTTP::Server.new([ws_handler])
http_server.bind 0
port_chan.send(http_server.port.not_nil!)
port = http_server.bind_unused_port
port_chan.send(port)
http_server.listen
end

Expand Down Expand Up @@ -354,8 +354,8 @@ describe HTTP::WebSocket do
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")
http_server.bind 0
port_chan.send(http_server.port.not_nil!)
port = http_server.bind_unused_port
port_chan.send(port)
http_server.listen
end

Expand Down
24 changes: 4 additions & 20 deletions src/http/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -123,22 +123,6 @@ class HTTP::Server
@processor = RequestProcessor.new(handler)
end

# Returns the TCP port of the first socket the server is bound to.
#
# For example you may let the system choose a port, then report it:
# ```
# server = HTTP::Server.new { }
# server.bind 0
# server.port # => 12345
# ```
def port : Int32?
@sockets.each do |socket|
if socket.is_a?(TCPServer)
return socket.local_address.port.to_i
end
end
end

# Creates a `TCPServer` and adds it as a socket.
#
# If *port* is `0`, a random, free port will be chosen.
Expand All @@ -161,15 +145,15 @@ class HTTP::Server

# Creates a `TCPServer` listening on an unused port and adds it as a socket.
#
# Returns the determined port number.
# Returns the `Socket::IPAddress` with the determined port number.
#
# ```
# server = HTTP::Server.new { }
# server.bind_unused_port # => 12345
# server.bind_unused_port # => Socket::IPAddress.new("127.0.0.1", 12345)
# ```
def bind_unused_port(host : String = "127.0.0.1", reuse_port : Bool = false) : Int32
def bind_unused_port(host : String = "127.0.0.1", reuse_port : Bool = false) : Socket::IPAddress
tcp_server = bind(host, 0, reuse_port)
tcp_server.local_address.port
tcp_server.local_address
end

# Adds a `Socket::Server` *socket* to this server.
Expand Down

0 comments on commit c6306a4

Please sign in to comment.