Skip to content

Commit acc64fc

Browse files
committed
Allow curl headers to be filtered out
This allows extraneous headers to be filtered out of the sample cURL request. Headers such as "Host" and "Cookie" are not needed with a cURL request and can be filtered. Closes zipmark#42
1 parent 6d3a390 commit acc64fc

File tree

9 files changed

+159
-20
lines changed

9 files changed

+159
-20
lines changed

features/curl.feature

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
Feature: cURL output
2+
Background:
3+
Given a file named "app_spec.rb" with:
4+
"""
5+
require "rspec_api_documentation"
6+
require "rspec_api_documentation/dsl"
7+
8+
class App
9+
def self.call(env)
10+
if env["HTTP_ACCEPT"] == "foo"
11+
[200, {}, ["foo"]]
12+
else
13+
[406, {}, ["unknown content type"]]
14+
end
15+
end
16+
end
17+
18+
RspecApiDocumentation.configure do |config|
19+
config.app = App
20+
config.curl_host = "example.org"
21+
end
22+
23+
resource "FooBars" do
24+
get "/foobar" do
25+
header "Accept", "foo"
26+
27+
example "Getting Foo" do
28+
do_request
29+
response_body.should == "foo"
30+
end
31+
end
32+
end
33+
"""
34+
35+
Scenario: Not filtering headers in cURL
36+
Given a file named "config.rb" with:
37+
"""
38+
"""
39+
When I run `rspec app_spec.rb --require ./config.rb --format RspecApiDocumentation::ApiFormatter`
40+
41+
Then the outputted docs should not filter out headers
42+
43+
Scenario: Filtering out headers in cURL
44+
Given a file named "config.rb" with:
45+
"""
46+
require "rspec_api_documentation"
47+
48+
RspecApiDocumentation.configure do |config|
49+
config.curl_headers_to_filter = ["Host", "Cookie"]
50+
end
51+
"""
52+
When I run `rspec app_spec.rb --require ./config.rb --format RspecApiDocumentation::ApiFormatter`
53+
54+
Then the outputted docs should filter out headers
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Then /the outputted docs should( not)? filter out headers$/ do |condition|
2+
visit "/foobars/getting_foo.html"
3+
4+
within("pre.curl") do
5+
if condition
6+
page.should have_content("Host")
7+
page.should have_content("Cookie")
8+
else
9+
page.should_not have_content("Host")
10+
page.should_not have_content("Cookie")
11+
end
12+
end
13+
end

lib/rspec_api_documentation/configuration.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ def self.add_setting(name, opts = {})
5454
end
5555
}
5656

57+
add_setting :curl_headers_to_filter, :default => nil
5758
add_setting :curl_host, :default => nil
5859
add_setting :keep_source_order, :default => false
5960
add_setting :api_name, :default => "API Documentation"

lib/rspec_api_documentation/curl.rb

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ module RspecApiDocumentation
44
class Curl < Struct.new(:method, :path, :data, :headers)
55
attr_accessor :host
66

7-
def output(config_host)
7+
def output(config_host, config_headers_to_filer = nil)
88
self.host = config_host
9+
@config_headers_to_filer = Array(config_headers_to_filer)
910
send(method.downcase)
1011
end
1112

@@ -17,6 +18,10 @@ def get
1718
"curl \"#{url}#{get_data}\" -X GET #{headers}"
1819
end
1920

21+
def head
22+
"curl \"#{url}#{get_data}\" -X HEAD #{headers}"
23+
end
24+
2025
def put
2126
"curl \"#{url}\" #{post_data} -X PUT #{headers}"
2227
end
@@ -25,10 +30,6 @@ def delete
2530
"curl \"#{url}\" #{post_data} -X DELETE #{headers}"
2631
end
2732

28-
def head
29-
"curl \"#{url}#{get_data}\" -X HEAD #{headers}"
30-
end
31-
3233
def patch
3334
"curl \"#{url}\" #{post_data} -X PATCH #{headers}"
3435
end
@@ -38,8 +39,8 @@ def url
3839
end
3940

4041
def headers
41-
super.map do |k, v|
42-
"\\\n\t-H \"#{format_header(k, v)}\""
42+
filter_headers(super).map do |k, v|
43+
"\\\n\t-H \"#{format_full_header(k, v)}\""
4344
end.join(" ")
4445
end
4546

@@ -53,10 +54,24 @@ def post_data
5354
end
5455

5556
private
56-
def format_header(header, value)
57-
formatted_header = header.gsub(/^HTTP_/, '').titleize.split.join("-")
57+
58+
def format_header(header)
59+
header.gsub(/^HTTP_/, '').titleize.split.join("-")
60+
end
61+
62+
def format_full_header(header, value)
5863
formatted_value = value.gsub(/"/, "\\\"")
59-
"#{formatted_header}: #{formatted_value}"
64+
"#{format_header(header)}: #{formatted_value}"
65+
end
66+
67+
def filter_headers(headers)
68+
if !@config_headers_to_filer.empty?
69+
headers.reject do |header|
70+
@config_headers_to_filer.include?(format_header(header))
71+
end
72+
else
73+
headers
74+
end
6075
end
6176
end
6277
end

lib/rspec_api_documentation/views/markup_example.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ class MarkupExample < Mustache
66
def initialize(example, configuration)
77
@example = example
88
@host = configuration.curl_host
9+
@filter_headers = configuration.curl_headers_to_filter
910
self.template_path = configuration.template_path
1011
end
1112

@@ -33,7 +34,9 @@ def requests
3334
hash[:request_query_parameters_text] = format_hash(hash[:request_query_parameters])
3435
hash[:response_headers_text] = format_hash(hash[:response_headers])
3536
if @host
36-
hash[:curl] = hash[:curl].output(@host) if hash[:curl].is_a? RspecApiDocumentation::Curl
37+
if hash[:curl].is_a? RspecApiDocumentation::Curl
38+
hash[:curl] = hash[:curl].output(@host, @filter_headers)
39+
end
3740
else
3841
hash[:curl] = nil
3942
end

lib/rspec_api_documentation/writers/json_writer.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ class JsonExample
6262
def initialize(example, configuration)
6363
@example = example
6464
@host = configuration.curl_host
65+
@filter_headers = configuration.curl_headers_to_filter
6566
end
6667

6768
def method_missing(method, *args, &block)
@@ -96,7 +97,9 @@ def as_json(opts = nil)
9697
def requests
9798
super.map do |hash|
9899
if @host
99-
hash[:curl] = hash[:curl].output(@host) if hash[:curl].is_a? RspecApiDocumentation::Curl
100+
if hash[:curl].is_a? RspecApiDocumentation::Curl
101+
hash[:curl] = hash[:curl].output(@host, @filter_headers)
102+
end
100103
else
101104
hash[:curl] = nil
102105
end

spec/configuration_spec.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
its(:filter) { should == :all }
4949
its(:exclusion_filter) { should be_nil }
5050
its(:app) { should be_nil }
51+
its(:curl_headers_to_filter) { should be_nil }
5152
its(:curl_host) { should be_nil }
5253
its(:keep_source_order) { should be_false }
5354
its(:api_name) { should == "API Documentation" }

spec/curl_spec.rb

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
let(:host) { "http://example.com" }
44
let(:curl) { RspecApiDocumentation::Curl.new(method, path, data, headers) }
55

6-
subject { curl.output(host) }
6+
subject { curl.output(host, ["Host", "Cookies"]) }
77

88
describe "POST" do
99
let(:method) { "POST" }
@@ -13,7 +13,9 @@
1313
{
1414
"HTTP_ACCEPT" => "application/json",
1515
"HTTP_X_HEADER" => "header",
16-
"HTTP_AUTHORIZATION" => %{Token token="mytoken"}
16+
"HTTP_AUTHORIZATION" => %{Token token="mytoken"},
17+
"HTTP_HOST" => "example.org",
18+
"HTTP_COOKIES" => ""
1719
}
1820
end
1921

@@ -24,6 +26,8 @@
2426
it { should =~ /-H "Accept: application\/json"/ }
2527
it { should =~ /-H "X-Header: header"/ }
2628
it { should =~ /-H "Authorization: Token token=\\"mytoken\\""/ }
29+
it { should_not =~ /-H "Host: example\.org"/ }
30+
it { should_not =~ /-H "Cookies: "/ }
2731

2832
it "should call post" do
2933
curl.should_receive(:post)
@@ -35,13 +39,22 @@
3539
let(:method) { "GET" }
3640
let(:path) { "/orders" }
3741
let(:data) { "size=large" }
38-
let(:headers) { {"HTTP_ACCEPT" => "application/json", "HTTP_X_HEADER" => "header"} }
42+
let(:headers) do
43+
{
44+
"HTTP_ACCEPT" => "application/json",
45+
"HTTP_X_HEADER" => "header",
46+
"HTTP_HOST" => "example.org",
47+
"HTTP_COOKIES" => ""
48+
}
49+
end
3950

4051
it { should =~ /^curl/ }
4152
it { should =~ /http:\/\/example\.com\/orders\?size=large/ }
4253
it { should =~ /-X GET/ }
4354
it { should =~ /-H "Accept: application\/json"/ }
4455
it { should =~ /-H "X-Header: header"/ }
56+
it { should_not =~ /-H "Host: example\.org"/ }
57+
it { should_not =~ /-H "Cookies: "/ }
4558

4659
it "should call get" do
4760
curl.should_receive(:get)
@@ -53,14 +66,23 @@
5366
let(:method) { "PUT" }
5467
let(:path) { "/orders/1" }
5568
let(:data) { "size=large" }
56-
let(:headers) { {"HTTP_ACCEPT" => "application/json", "HTTP_X_HEADER" => "header"} }
69+
let(:headers) do
70+
{
71+
"HTTP_ACCEPT" => "application/json",
72+
"HTTP_X_HEADER" => "header",
73+
"HTTP_HOST" => "example.org",
74+
"HTTP_COOKIES" => ""
75+
}
76+
end
5777

5878
it { should =~ /^curl/ }
5979
it { should =~ /http:\/\/example\.com\/orders\/1/ }
6080
it { should =~ /-d 'size=large'/ }
6181
it { should =~ /-X PUT/ }
6282
it { should =~ /-H "Accept: application\/json"/ }
6383
it { should =~ /-H "X-Header: header"/ }
84+
it { should_not =~ /-H "Host: example\.org"/ }
85+
it { should_not =~ /-H "Cookies: "/ }
6486

6587
it "should call put" do
6688
curl.should_receive(:put)
@@ -72,13 +94,22 @@
7294
let(:method) { "DELETE" }
7395
let(:path) { "/orders/1" }
7496
let(:data) { }
75-
let(:headers) { {"HTTP_ACCEPT" => "application/json", "HTTP_X_HEADER" => "header"} }
97+
let(:headers) do
98+
{
99+
"HTTP_ACCEPT" => "application/json",
100+
"HTTP_X_HEADER" => "header",
101+
"HTTP_HOST" => "example.org",
102+
"HTTP_COOKIES" => ""
103+
}
104+
end
76105

77106
it { should =~ /^curl/ }
78107
it { should =~ /http:\/\/example\.com\/orders\/1/ }
79108
it { should =~ /-X DELETE/ }
80109
it { should =~ /-H "Accept: application\/json"/ }
81110
it { should =~ /-H "X-Header: header"/ }
111+
it { should_not =~ /-H "Host: example\.org"/ }
112+
it { should_not =~ /-H "Cookies: "/ }
82113

83114
it "should call delete" do
84115
curl.should_receive(:delete)
@@ -90,13 +121,22 @@
90121
let(:method) { "HEAD" }
91122
let(:path) { "/orders" }
92123
let(:data) { "size=large" }
93-
let(:headers) { {"HTTP_ACCEPT" => "application/json", "HTTP_X_HEADER" => "header"} }
124+
let(:headers) do
125+
{
126+
"HTTP_ACCEPT" => "application/json",
127+
"HTTP_X_HEADER" => "header",
128+
"HTTP_HOST" => "example.org",
129+
"HTTP_COOKIES" => ""
130+
}
131+
end
94132

95133
it { should =~ /^curl/ }
96134
it { should =~ /http:\/\/example\.com\/orders\?size=large/ }
97135
it { should =~ /-X HEAD/ }
98136
it { should =~ /-H "Accept: application\/json"/ }
99137
it { should =~ /-H "X-Header: header"/ }
138+
it { should_not =~ /-H "Host: example\.org"/ }
139+
it { should_not =~ /-H "Cookies: "/ }
100140

101141
it "should call get" do
102142
curl.should_receive(:head)
@@ -108,14 +148,23 @@
108148
let(:method) { "PATCH" }
109149
let(:path) { "/orders/1" }
110150
let(:data) { "size=large" }
111-
let(:headers) { {"HTTP_ACCEPT" => "application/json", "HTTP_X_HEADER" => "header"} }
151+
let(:headers) do
152+
{
153+
"HTTP_ACCEPT" => "application/json",
154+
"HTTP_X_HEADER" => "header",
155+
"HTTP_HOST" => "example.org",
156+
"HTTP_COOKIES" => ""
157+
}
158+
end
112159

113160
it { should =~ /^curl/ }
114161
it { should =~ /http:\/\/example\.com\/orders\/1/ }
115162
it { should =~ /-d 'size=large'/ }
116163
it { should =~ /-X PATCH/ }
117164
it { should =~ /-H "Accept: application\/json"/ }
118165
it { should =~ /-H "X-Header: header"/ }
166+
it { should_not =~ /-H "Host: example\.org"/ }
167+
it { should_not =~ /-H "Cookies: "/ }
119168

120169
it "should call put" do
121170
curl.should_receive(:patch)

templates/rspec_api_documentation/html_example.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585

8686
{{# curl }}
8787
<h4>cURL</h4>
88-
<pre class="request">{{ curl }}</pre>
88+
<pre class="request curl">{{ curl }}</pre>
8989
{{/ curl }}
9090

9191
{{# response_status }}

0 commit comments

Comments
 (0)