README
1SYNOPSIS
2
3 package MyApp;
4
5 use Dancer;
6 use Dancer::Plugin::Swagger;
7
8 our $VERSION = "0.1";
9
10 get '/choreograph/:name' => sub { ... };
11
12 1;
13
14DESCRIPTION
15
16 This plugin provides tools to create and access a Swagger
17 <http://swagger.io/> specification file for a Dancer REST web service.
18
19 Overview of Dancer::Plugin::Swagger's features:
20
21 Can create a /swagger.json REST specification file.
22
23 Can auto-discover routes and add them to the swagger file.
24
25 Can provide a Swagger UI version of the swagger documentation.
26
27CONFIGURATION
28
29 plugins:
30 Swagger:
31 main_api_module: MyApp
32 show_ui: 1
33 ui_url: /doc
34 ui_dir: /path/to/files
35 auto_discover_skip:
36 - /swagger.json
37 - qr#^/doc/#
38
39 main_api_module
40
41 If not provided explicitly, the Swagger document's title and version
42 will be set to the abstract and version of this module.
43
44 Defaults to the first module to import Dancer::Plugin::Swagger.
45
46 show_ui
47
48 If true, a route will be created for the Swagger UI (see
49 http://swagger.io/swagger-ui/).
50
51 Defaults to true.
52
53 ui_url
54
55 Path of the swagger ui route. Will also be the prefix for all the
56 CSS/JS dependencies of the page.
57
58 Defaults to /doc.
59
60 ui_dir
61
62 Filesystem path to the directory holding the assets for the Swagger UI
63 page.
64
65 Defaults to a copy of the Swagger UI code bundled with the
66 Dancer::Plugin::Swagger distribution.
67
68 auto_discover_skip
69
70 List of urls that should not be added to the Swagger document by
71 swagger_auto_discover. If an url begins with qr, it will be compiled as
72 a regular expression.
73
74 Defauls to /swagger.json and, if show_ui is true, all the urls under
75 ui_url.
76
77 validate_response
78
79 If set to true, calls to swagger_response will verify if a schema is
80 defined for the response, and if so validate against it.
81 JSON::Schema::AsType is used for the validation (and this required if
82 this option is used).
83
84 Defaults to false.
85
86 strict_validation
87
88 If set to true, dies if a call to swagger_response doesn't find a
89 schema for its response.
90
91 Defaults to false.
92
93PLUGIN KEYWORDS
94
95 swagger_path $description, \%args, $route
96
97 swagger_path {
98 description => 'Returns info about a judge',
99 },
100 get '/judge/:judge_name' => sub {
101 ...;
102 };
103
104 Registers a route as a swagger path item in the swagger document.
105
106 %args is optional.
107
108 The $description is optional as well, and can also be defined as part
109 of the %args.
110
111 # equivalent to the main example
112 swagger_path 'Returns info about a judge',
113 get '/judge/:judge_name' => sub {
114 ...;
115 };
116
117 If the $description spans many lines, it will be left-trimmed.
118
119 swagger_path q{
120 Returns info about a judge.
121
122 Some more documentation can go here.
123
124 And this will be seen as a performatted block
125 by swagger.
126 },
127 get '/judge/:judge_name' => sub {
128 ...;
129 };
130
131 Supported arguments
132
133 method
134
135 The HTTP method (GET, POST, etc) for the path item.
136
137 Defaults to the route's method.
138
139 path
140
141 The url for the path item.
142
143 Defaults to the route's path.
144
145 description
146
147 The path item's description.
148
149 tags
150
151 Optional arrayref of tags assigned to the path.
152
153 parameters
154
155 List of parameters for the path item. Must be an arrayref or a
156 hashref.
157
158 Route parameters are automatically populated. E.g.,
159
160 swagger_path
161 get '/judge/:judge_name' => { ... };
162
163 is equivalent to
164
165 swagger_path {
166 parameters => [
167 { name => 'judge_name', in => 'path', required => 1, type => 'string' },
168 ]
169 },
170 get '/judge/:judge_name' => { ... };
171
172 If the parameters are passed as a hashref, the keys are the names of
173 the parameters, and they will appear in the swagger document
174 following their alphabetical order.
175
176 If the parameters are passed as an arrayref, they will appear in the
177 document in the order in which they are passed. Additionally, each
178 parameter can be given as a hashref, or can be a name => arguments
179 pair.
180
181 In both format, for the key/value pairs, a string value is considered
182 to be the description of the parameter.
183
184 Finally, if not specified explicitly, the in argument of a parameter
185 defaults to query, and its type to string.
186
187 parameters => [
188 { name => 'bar', in => 'path', required => 1, type => 'string' },
189 { name => 'foo', in => 'query', type => 'string', description => 'yadah' },
190 ],
191
192 # equivalent arrayref with mixed pairs/non-pairs
193
194 parameters => [
195 { name => 'bar', in => 'path', required => 1, type => 'string' },
196 foo => { in => 'query', type => 'string', description => 'yadah' },
197 ],
198
199 # equivalent hashref format
200
201 parameters => {
202 bar => { in => 'path', required => 1, type => 'string' },
203 foo => { in => 'query', type => 'string', description => 'yadah' },
204 },
205
206 # equivalent, using defaults
207 parameters => {
208 bar => { in => 'path', required => 1 },
209 foo => 'yadah',
210 },
211
212 responses
213
214 Possible responses from the path. Must be a hashref.
215
216 swagger_path {
217 responses => {
218 default => { description => 'The judge information' }
219 },
220 },
221 get '/judge/:judge_name' => { ... };
222
223 If the key example is given (instead of examples as defined by the
224 Swagger specs), and the serializer used by the application is
225 Dancer::Serializer::JSON or Dancer::Serializer::YAML, the example
226 will be expanded to have the right content-type key.
227
228 swagger_path {
229 responses => {
230 default => { example => { fullname => 'Mary Ann Murphy' } }
231 },
232 },
233 get '/judge/:judge_name' => { ... };
234
235 # equivalent to
236
237 swagger_path {
238 responses => {
239 default => { examples => { 'application/json' => { fullname => 'Mary Ann Murphy' } } }
240 },
241 },
242 get '/judge/:judge_name' => { ... };
243
244 The special key template will not appear in the Swagger doc, but will
245 be used by the swagger_template plugin keyword.
246
247 swagger_template $code, $args
248
249 swagger_path {
250 responses => {
251 404 => { template => sub { +{ error => "judge '$_[0]' not found" } }
252 },
253 },
254 get '/judge/:judge_name' => {
255 my $name = param('judge_name');
256 return swagger_template 404, $name unless in_db($name);
257 ...;
258 };
259
260 Calls the template for the $code response, passing it $args. If $code
261 is numerical, also set the response's status to that value.
262
263 swagger_auto_discover skip => \@list
264
265 Populates the Swagger document with information of all the routes of
266 the application.
267
268 Accepts an optional skip parameter that takes an arrayref of routes
269 that shouldn't be added to the Swagger document. The routes can be
270 specified as-is, or via regular expressions. If no skip list is given,
271 defaults to the c<auto_discover_skip> configuration value.
272
273 swagger_auto_discover skip => [ '/swagger.json', qr#^/doc/# ];
274
275 The information of a route won't be altered if it's already present in
276 the document.
277
278 If a route has path parameters, they will be automatically added as
279 such in the parameters section.
280
281 Routes defined as regexes are skipped, as there is no clean way to
282 automatically make them look nice.
283
284 # will be picked up
285 get '/user' => ...;
286
287 # ditto, as '/user/{user_id}'
288 get '/user/:user_id => ...;
289
290 # won't be picked up
291 get qr#/user/(\d+)# => ...;
292
293 Note that routes defined after swagger_auto_discover has been called
294 won't be added to the Swagger document. Typically, you'll want
295 swagger_auto_discover to be called at the very end of your module.
296 Alternatively, swagger_auto_discover can be called more than once
297 safely -- which can be useful if an application creates routes
298 dynamically.
299
300 swagger_definition $name => $definition, ...
301
302 Adds a schema (or more) to the definition section of the Swagger
303 document.
304
305 swagger_definition 'Judge' => {
306 type => 'object',
307 required => [ 'fullname' ],
308 properties => {
309 fullname => { type => 'string' },
310 seasons => { type => 'array', items => { type => 'integer' } },
311 }
312 };
313
314 The function returns the reference to the definition that can be then
315 used where schemas are used.
316
317 my $Judge = swagger_definition 'Judge' => { ... };
318 # $Judge is now the hashref '{ '$ref' => '#/definitions/Judge' }'
319
320 # later on...
321 swagger_path {
322 responses => {
323 default => { schema => $Judge },
324 },
325 },
326 get '/judge/:name' => sub { ... };
327
328
329EXAMPLES
330
331 See the examples/ directory of the distribution for a working example.
332
333SEE ALSO
334
335 http://swagger.io/|Swagger
336
337
README.mkdn
1# NAME
2
3Dancer::Plugin::Swagger - create Swagger documentation of the app REST interface
4
5# VERSION
6
7version 0.2.0
8
9# SYNOPSIS
10
11 package MyApp;
12
13 use Dancer;
14 use Dancer::Plugin::Swagger;
15
16 our $VERSION = "0.1";
17
18 get '/choreograph/:name' => sub { ... };
19
20 1;
21
22# DESCRIPTION
23
24This plugin provides tools to create and access a [Swagger](http://swagger.io/) specification file for a
25Dancer REST web service.
26
27Overview of `Dancer::Plugin::Swagger`'s features:
28
29- Can create a `/swagger.json` REST specification file.
30- Can auto-discover routes and add them to the swagger file.
31- Can provide a Swagger UI version of the swagger documentation.
32
33# CONFIGURATION
34
35 plugins:
36 Swagger:
37 main_api_module: MyApp
38 show_ui: 1
39 ui_url: /doc
40 ui_dir: /path/to/files
41 auto_discover_skip:
42 - /swagger.json
43 - qr#^/doc/#
44
45## main\_api\_module
46
47If not provided explicitly, the Swagger document's title and version will be set
48to the abstract and version of this module.
49
50Defaults to the first
51module to import [Dancer::Plugin::Swagger](https://metacpan.org/pod/Dancer::Plugin::Swagger).
52
53## show\_ui
54
55If `true`, a route will be created for the Swagger UI (see [http://swagger.io/swagger-ui/](http://swagger.io/swagger-ui/)).
56
57Defaults to `true`.
58
59## ui\_url
60
61Path of the swagger ui route. Will also be the prefix for all the CSS/JS dependencies of the page.
62
63Defaults to `/doc`.
64
65## ui\_dir
66
67Filesystem path to the directory holding the assets for the Swagger UI page.
68
69Defaults to a copy of the Swagger UI code bundled with the [Dancer::Plugin::Swagger](https://metacpan.org/pod/Dancer::Plugin::Swagger) distribution.
70
71## auto\_discover\_skip
72
73List of urls that should not be added to the Swagger document by `swagger_auto_discover`.
74If an url begins with `qr`, it will be compiled as a regular expression.
75
76Defauls to `/swagger.json` and, if `show_ui` is `true`, all the urls under `ui_url`.
77
78## validate\_response
79
80If set to `true`, calls to `swagger_response` will verify if a schema is defined
81for the response, and if so validate against it. [JSON::Schema::AsType](https://metacpan.org/pod/JSON::Schema::AsType) is used for the
82validation (and this required if this option is used).
83
84Defaults to `false`.
85
86## strict\_validation
87
88If set to `true`, dies if a call to `swagger_response` doesn't find a schema for its response.
89
90Defaults to `false`.
91
92# PLUGIN KEYWORDS
93
94## swagger\_path $description, \\%args, $route
95
96 swagger_path {
97 description => 'Returns info about a judge',
98 },
99 get '/judge/:judge_name' => sub {
100 ...;
101 };
102
103Registers a route as a swagger path item in the swagger document.
104
105`%args` is optional.
106
107The `$description` is optional as well, and can also be defined as part of the
108`%args`.
109
110 # equivalent to the main example
111 swagger_path 'Returns info about a judge',
112 get '/judge/:judge_name' => sub {
113 ...;
114 };
115
116If the `$description` spans many lines, it will be left-trimmed.
117
118 swagger_path q{
119 Returns info about a judge.
120
121 Some more documentation can go here.
122
123 And this will be seen as a performatted block
124 by swagger.
125 },
126 get '/judge/:judge_name' => sub {
127 ...;
128 };
129
130### Supported arguments
131
132- method
133
134 The HTTP method (GET, POST, etc) for the path item.
135
136 Defaults to the route's method.
137
138- path
139
140 The url for the path item.
141
142 Defaults to the route's path.
143
144- description
145
146 The path item's description.
147
148- tags
149
150 Optional arrayref of tags assigned to the path.
151
152- parameters
153
154 List of parameters for the path item. Must be an arrayref or a hashref.
155
156 Route parameters are automatically populated. E.g.,
157
158 swagger_path
159 get '/judge/:judge_name' => { ... };
160
161 is equivalent to
162
163 swagger_path {
164 parameters => [
165 { name => 'judge_name', in => 'path', required => 1, type => 'string' },
166 ]
167 },
168 get '/judge/:judge_name' => { ... };
169
170 If the parameters are passed as a hashref, the keys are the names of the parameters, and they will
171 appear in the swagger document following their alphabetical order.
172
173 If the parameters are passed as an arrayref, they will appear in the document in the order
174 in which they are passed. Additionally, each parameter can be given as a hashref, or can be a
175 `name => arguments` pair.
176
177 In both format, for the key/value pairs, a string value is considered to be the
178 `description` of the parameter.
179
180 Finally, if not specified explicitly, the `in` argument of a parameter defaults to `query`,
181 and its type to `string`.
182
183 parameters => [
184 { name => 'bar', in => 'path', required => 1, type => 'string' },
185 { name => 'foo', in => 'query', type => 'string', description => 'yadah' },
186 ],
187
188 # equivalent arrayref with mixed pairs/non-pairs
189
190 parameters => [
191 { name => 'bar', in => 'path', required => 1, type => 'string' },
192 foo => { in => 'query', type => 'string', description => 'yadah' },
193 ],
194
195 # equivalent hashref format
196
197 parameters => {
198 bar => { in => 'path', required => 1, type => 'string' },
199 foo => { in => 'query', type => 'string', description => 'yadah' },
200 },
201
202 # equivalent, using defaults
203 parameters => {
204 bar => { in => 'path', required => 1 },
205 foo => 'yadah',
206 },
207
208- responses
209
210 Possible responses from the path. Must be a hashref.
211
212 swagger_path {
213 responses => {
214 default => { description => 'The judge information' }
215 },
216 },
217 get '/judge/:judge_name' => { ... };
218
219 If the key `example` is given (instead of `examples` as defined by the Swagger specs),
220 and the serializer used by the application is [Dancer::Serializer::JSON](https://metacpan.org/pod/Dancer::Serializer::JSON) or [Dancer::Serializer::YAML](https://metacpan.org/pod/Dancer::Serializer::YAML),
221 the example will be expanded to have the right content-type key.
222
223 swagger_path {
224 responses => {
225 default => { example => { fullname => 'Mary Ann Murphy' } }
226 },
227 },
228 get '/judge/:judge_name' => { ... };
229
230 # equivalent to
231
232 swagger_path {
233 responses => {
234 default => { examples => { 'application/json' => { fullname => 'Mary Ann Murphy' } } }
235 },
236 },
237 get '/judge/:judge_name' => { ... };
238
239 The special key `template` will not appear in the Swagger doc, but will be
240 used by the `swagger_template` plugin keyword.
241
242## swagger\_template $code, $args
243
244 swagger_path {
245 responses => {
246 404 => { template => sub { +{ error => "judge '$_[0]' not found" } }
247 },
248 },
249 get '/judge/:judge_name' => {
250 my $name = param('judge_name');
251 return swagger_template 404, $name unless in_db($name);
252 ...;
253 };
254
255Calls the template for the `$code` response, passing it `$args`. If `$code` is numerical, also set
256the response's status to that value.
257
258## swagger\_auto\_discover skip => \\@list
259
260Populates the Swagger document with information of all
261the routes of the application.
262
263Accepts an optional `skip` parameter that takes an arrayref of
264routes that shouldn't be added to the Swagger document. The routes
265can be specified as-is, or via regular expressions. If no skip list is given, defaults to
266the c<auto\_discover\_skip> configuration value.
267
268 swagger_auto_discover skip => [ '/swagger.json', qr#^/doc/# ];
269
270The information of a route won't be altered if it's
271already present in the document.
272
273If a route has path parameters, they will be automatically
274added as such in the `parameters` section.
275
276Routes defined as regexes are skipped, as there is no clean way
277to automatically make them look nice.
278
279 # will be picked up
280 get '/user' => ...;
281
282 # ditto, as '/user/{user_id}'
283 get '/user/:user_id => ...;
284
285 # won't be picked up
286 get qr#/user/(\d+)# => ...;
287
288Note that routes defined after `swagger_auto_discover` has been called won't
289be added to the Swagger document. Typically, you'll want `swagger_auto_discover`
290to be called at the very end of your module. Alternatively, `swagger_auto_discover`
291can be called more than once safely -- which can be useful if an application creates
292routes dynamically.
293
294## swagger\_definition $name => $definition, ...
295
296Adds a schema (or more) to the definition section of the Swagger document.
297
298 swagger_definition 'Judge' => {
299 type => 'object',
300 required => [ 'fullname' ],
301 properties => {
302 fullname => { type => 'string' },
303 seasons => { type => 'array', items => { type => 'integer' } },
304 }
305 };
306
307The function returns the reference to the definition that can be then used where
308schemas are used.
309
310 my $Judge = swagger_definition 'Judge' => { ... };
311 # $Judge is now the hashref '{ '$ref' => '#/definitions/Judge' }'
312
313 # later on...
314 swagger_path {
315 responses => {
316 default => { schema => $Judge },
317 },
318 },
319 get '/judge/:name' => sub { ... };
320
321# EXAMPLES
322
323See the `examples/` directory of the distribution for a working example.
324
325# SEE ALSO
326
327- [http://swagger.io/|Swagger](http://swagger.io/|Swagger)
328
329# AUTHOR
330
331Yanick Champoux <yanick@cpan.org> [![endorse](http://api.coderwall.com/yanick/endorsecount.png)](http://coderwall.com/yanick)
332
333# COPYRIGHT AND LICENSE
334
335This software is copyright (c) 2015 by Yanick Champoux.
336
337This is free software; you can redistribute it and/or modify it under
338the same terms as the Perl 5 programming language system itself.
339