Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions spec/std/http/server/server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require "spec"
require "http/server"
require "tempfile"

private class RaiseErrno < IO
def initialize(@value : Int32)
Expand Down Expand Up @@ -40,6 +41,24 @@ private class ReverseResponseOutput < IO
end
end

# TODO: replace with `HTTP::Client` once it supports connecting to Unix socket.
private def unix_request(path)
UNIXSocket.open(path) do |io|
io << "GET / HTTP/1.1\r\n"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it shorter to use HTTP::Request directly here?

io << "X-Unix-Socket: #{path}\r\n"
io << "\r\n"
io.flush

loop do
line = io.gets || break

if line.empty?
return io.gets
end
end
end
end

module HTTP
class Server
describe Response do
Expand Down Expand Up @@ -310,6 +329,42 @@ module HTTP
end
end
end

{% if flag?(:unix) %}
describe "#bind_unix" do

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indent

it "binds to different unix sockets" do
path1 = Tempfile.tempname
path2 = Tempfile.tempname

begin
server = Server.new do |context|
# TODO: Replace custom header with local_address
context.response.puts "Test Server (#{context.request.headers["X-Unix-Socket"]?})"
context.response.close
end

socket1 = UNIXServer.new(path1)
server.bind socket1
socket2 = server.bind_unix path2

spawn server.listen

Fiber.yield

unix_request(path1).should eq "Test Server (#{path1})"
unix_request(path2).should eq "Test Server (#{path2})"

server.close

File.exists?(path1).should be_false
File.exists?(path2).should be_false
ensure
File.delete(path1) if File.exists?(path1)
File.delete(path2) if File.exists?(path2)
end
end
end
{% end %}
end

describe HTTP::Server::RequestProcessor do
Expand Down
14 changes: 14 additions & 0 deletions src/http/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,20 @@ class HTTP::Server
bind_tcp host, 0, reuse_port
end

# Creates a `UNIXServer` bound to *path* and adds it as a socket.
#
# ```
# server = HTTP::Server.new { }
# server.bind_unix "/tmp/my-socket.sock"
# ```
def bind_unix(path : String) : Socket::UNIXAddress
server = UNIXServer.new(path)

bind(server)

server.local_address
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