Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

in_http: Implement support for CORS preflight requests #2144

Merged
merged 1 commit into from
Oct 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
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
38 changes: 38 additions & 0 deletions lib/fluent/plugin/in_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ def on_headers_complete(headers)
# For multiple X-Forwarded-For headers. Use first header value.
v = v.first if v.is_a?(Array)
@remote_addr = v.split(",").first
when /Access-Control-Request-Method/i
@access_control_request_method = v
when /Access-Control-Request-Headers/i
@access_control_request_headers = v
end
}
if expect
Expand All @@ -367,9 +371,43 @@ def on_body(chunk)
@body << chunk
end

# Web browsers can send an OPTIONS request before performing POST
# to check if cross-origin requests are supported.
def handle_options_request
# Is CORS enabled in the first place?
if @cors_allow_origins.nil?
return send_response_and_close("403 Forbidden", {}, "")
end

# in_http does not support HTTP methods except POST
if @access_control_request_method != 'POST'
return send_response_and_close("403 Forbidden", {}, "")
end

header = {
"Access-Control-Allow-Methods" => "POST",
"Access-Control-Allow-Headers" => @access_control_request_headers || "",
}

# Check the origin and send back a CORS response
if @cors_allow_origins.include?('*')
header["Access-Control-Allow-Origin"] = "*"
send_response_and_close("200 OK", header, "")
elsif @cors_allow_origins.include?(@origin)
header["Access-Control-Allow-Origin"] = @origin
send_response_and_close("200 OK", header, "")
else
send_response_and_close("403 Forbidden", {}, "")
end
end

def on_message_complete
return if closing?

if @parser.http_method == 'OPTIONS'
return handle_options_request()
end

# CORS check
# ==========
# For every incoming request, we check if we have some CORS
Expand Down
23 changes: 23 additions & 0 deletions test/plugin/test_in_http.rb
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,23 @@ def test_cors_allowed_wildcard
end
end

def test_cors_preflight
d = create_driver(CONFIG + 'cors_allow_origins ["*"]')

d.run do
header = {
"Origin" => "http://foo.com",
"Access-Control-Request-Method" => "POST",
"Access-Control-Request-Headers" => "Content-Type",
}
res = options("/cors.test", {}, header)

assert_equal "200", res.code
assert_equal "*", res["Access-Control-Allow-Origin"]
assert_equal "POST", res["Access-Control-Allow-Methods"]
end
end

def test_content_encoding_gzip
d = create_driver

Expand Down Expand Up @@ -744,6 +761,12 @@ def test_if_content_type_is_initialized_properly
assert_equal $test_in_http_connection_object_ids[0], $test_in_http_connection_object_ids[1]
end

def options(path, params, header = {})
http = Net::HTTP.new("127.0.0.1", PORT)
req = Net::HTTP::Options.new(path, header)
http.request(req)
end

def post(path, params, header = {}, &block)
http = Net::HTTP.new("127.0.0.1", PORT)
req = Net::HTTP::Post.new(path, header)
Expand Down