Skip to content

Commit 71c5d71

Browse files
author
Tim Vandecasteele
committed
Merge branch 'custom-header-support'
2 parents 8183d19 + c30b3cd commit 71c5d71

File tree

4 files changed

+148
-15
lines changed

4 files changed

+148
-15
lines changed

README.markdown

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,26 @@ You can pass a hash with some configuration possibilities to ```add_swagger_docu
4242
* ```:base_path``` Basepath of the API that's being exposed
4343
* ```:markdown``` Allow markdown in `notes`, default `false`
4444

45+
## Swagger Header Parameters
46+
47+
Swagger also supports the documentation of parameters passed in the header. Since grape's ```params[]``` doesn't return header parameters we can
48+
to specify header parameters seperately in a block after the description.
49+
50+
``` ruby
51+
desc "Return super-secret information", {
52+
headers: {
53+
"XAuthToken" => {
54+
description: "Valdates your identity",
55+
required: true
56+
},
57+
XOptionalHeader" => {
58+
description: "Not reallly needed",
59+
required: false
60+
}
61+
}
62+
}
63+
```
64+
4565
## Swagger additions
4666
grape-swagger allows you to add an explanation in markdown in the notes field. Which would result in proper formatted markdown in Swagger UI. The default Swagger UI doesn't allow HTML in the notes field, so you need to use an adapted version of Swagger UI (you can find one at https://github.com/tim-vandecasteele/swagger-ui/tree/vasco).
4767

lib/grape-swagger.rb

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ def self.setup(options)
8787
:summary => route.route_description || '',
8888
:nickname => route.route_method + route.route_path.gsub(/[\/:\(\)\.]/,'-'),
8989
:httpMethod => route.route_method,
90-
:parameters => parse_params(route.route_params, route.route_path, route.route_method)
90+
:parameters => parse_header_params(route.route_headers) +
91+
parse_params(route.route_params, route.route_path, route.route_method)
9192
}]
9293
}
9394
end
@@ -105,19 +106,46 @@ def self.setup(options)
105106

106107
helpers do
107108
def parse_params(params, path, method)
108-
params.map do |param, value|
109-
value[:type] = 'file' if value.is_a?(Hash) && value[:type] == 'Rack::Multipart::UploadedFile'
110-
dataType = value.is_a?(Hash) ? value[:type]||'String' : 'String'
111-
description = value.is_a?(Hash) ? value[:desc] : ''
112-
required = value.is_a?(Hash) ? !!value[:required] : false
113-
paramType = path.match(":#{param}") ? 'path' : (method == 'POST') ? 'body' : 'query'
114-
{
115-
paramType: paramType,
116-
name: value[:full_name] || param,
117-
description: description,
118-
dataType: dataType,
119-
required: required
120-
}
109+
if params
110+
params.map do |param, value|
111+
value[:type] = 'file' if value.is_a?(Hash) && value[:type] == 'Rack::Multipart::UploadedFile'
112+
113+
dataType = value.is_a?(Hash) ? value[:type]||'String' : 'String'
114+
description = value.is_a?(Hash) ? value[:desc] : ''
115+
required = value.is_a?(Hash) ? !!value[:required] : false
116+
paramType = path.match(":#{param}") ? 'path' : (method == 'POST') ? 'body' : 'query'
117+
name = (value.is_a?(Hash) && value[:full_name]) || param
118+
{
119+
paramType: paramType,
120+
name: name,
121+
description: description,
122+
dataType: dataType,
123+
required: required
124+
}
125+
end
126+
else
127+
[]
128+
end
129+
end
130+
131+
132+
def parse_header_params(params)
133+
if params
134+
params.map do |param, value|
135+
dataType = 'String'
136+
description = value.is_a?(Hash) ? value[:description] : ''
137+
required = value.is_a?(Hash) ? !!value[:required] : false
138+
paramType = "header"
139+
{
140+
paramType: paramType,
141+
name: param,
142+
description: description,
143+
dataType: dataType,
144+
required: required
145+
}
146+
end
147+
else
148+
[]
121149
end
122150
end
123151

spec/grape-swagger-helper_spec.rb

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
require 'spec_helper'
2+
3+
describe "helpers" do
4+
5+
before(:all) do
6+
class HelperTestAPI < Grape::API
7+
add_swagger_documentation
8+
end
9+
10+
@api = Object.new
11+
# after injecting grape-swagger into the Test API we get the helper methods
12+
# back from the first endpoint's class (the API mounted by grape-swagger
13+
# to serve the swagger_doc
14+
@api.extend HelperTestAPI.endpoints.first.options[:app].helpers
15+
16+
end
17+
18+
context "parsing parameters" do
19+
it "should parse params as query strings for a GET" do
20+
params = {
21+
name: {type: 'String', :desc => "A name", required: true },
22+
level: 'max'
23+
}
24+
path = "/coolness"
25+
method = "GET"
26+
@api.parse_params(params, path, method).should ==
27+
[
28+
{paramType: "query", name: :name, description:"A name", dataType: "String", required: true},
29+
{paramType: "query", name: :level, description:"", dataType: "String", required: false}
30+
]
31+
end
32+
33+
it "should parse params as body for a POST" do
34+
params = {
35+
name: {type: 'String', :desc =>"A name", required: true },
36+
level: 'max'
37+
}
38+
path = "/coolness"
39+
method = "POST"
40+
@api.parse_params(params, path, method).should ==
41+
[
42+
{paramType: "body", name: :name, description:"A name", dataType: "String", required: true},
43+
{paramType: "body", name: :level, description:"", dataType: "String", required: false}
44+
]
45+
end
46+
end
47+
48+
context "parsing the path" do
49+
it "should parse the path" do
50+
path = ":abc/def(.:format)"
51+
@api.parse_path(path, nil).should == "{abc}/def.{format}"
52+
end
53+
54+
it "should parse the path with a specified version" do
55+
path = ":abc/{version}/def(.:format)"
56+
@api.parse_path(path, 'v1').should == "{abc}/v1/def.{format}"
57+
end
58+
end
59+
60+
context "parsing header parameters" do
61+
it "should parse params for the header" do
62+
params = {"XAuthToken" => { description: "A required header.", required: true}}
63+
@api.parse_header_params(params).should ==
64+
[
65+
{paramType: "header", name: "XAuthToken", description:"A required header.", dataType: "String", required: true}
66+
]
67+
end
68+
end
69+
70+
end

spec/simple_mounted_api_spec.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,16 @@ class SimpleMountedApi < Grape::API
99
get '/simple' do
1010
{:bla => 'something'}
1111
end
12+
13+
desc 'this gets something else', {
14+
:headers => {
15+
"XAuthToken" => {description: "A required header.", required: true},
16+
"XOtherHeader" => {description: "An optional header.", required: false}
17+
}
18+
}
19+
get '/simple_with_headers' do
20+
{:bla => 'something_else'}
21+
end
1222
end
1323

1424
class SimpleApi < Grape::API
@@ -21,11 +31,16 @@ def app; SimpleApi end
2131

2232
it "retrieves swagger-documentation on /swagger_doc" do
2333
get '/swagger_doc'
24-
last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/simple.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
34+
last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :operations=>[], :apis=>[{:path=>\"/swagger_doc/simple.{format}\"}, {:path=>\"/swagger_doc/simple_with_headers.{format}\"}, {:path=>\"/swagger_doc/swagger_doc.{format}\"}]}"
2535
end
2636

2737
it "retrieves the documentation for mounted-api" do
2838
get '/swagger_doc/simple'
2939
last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :resourcePath=>\"\", :apis=>[{:path=>\"/simple.{format}\", :operations=>[{:notes=>\"_test_\", :summary=>\"this gets something\", :nickname=>\"GET-simple---format-\", :httpMethod=>\"GET\", :parameters=>[]}]}]}"
3040
end
41+
42+
it "retrieves the documentation for mounted-api that includes headers" do
43+
get '/swagger_doc/simple_with_headers'
44+
last_response.body.should == "{:apiVersion=>\"0.1\", :swaggerVersion=>\"1.1\", :basePath=>\"http://example.org\", :resourcePath=>\"\", :apis=>[{:path=>\"/simple_with_headers.{format}\", :operations=>[{:notes=>nil, :summary=>\"this gets something else\", :nickname=>\"GET-simple_with_headers---format-\", :httpMethod=>\"GET\", :parameters=>[{:paramType=>\"header\", :name=>\"XAuthToken\", :description=>\"A required header.\", :dataType=>\"String\", :required=>true}, {:paramType=>\"header\", :name=>\"XOtherHeader\", :description=>\"An optional header.\", :dataType=>\"String\", :required=>false}]}]}]}"
45+
end
3146
end

0 commit comments

Comments
 (0)