Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ SPRINGONE2GX WASHINGTON, DC Documenting RESTful APIs Andy Wilkinson @ankinson
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ How RESTful is your API? 2
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ REST maturity model 3 Hyper media HTTP verbs Separate Resources XML-RPC SOAP RPC Level 0 Level 1 Level 2 Level 3 http://www.crummy.com/writing/speaking/2008-QCon/act3.html http://martinfowler.com/articles/richardsonMaturityModel.html
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ How RESTful do you want it to be? 4
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Making your API easy to document 5
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Consistency 6 HTTP status codes HTTP verbs
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Uniqueness 7 Use distinct relations on your links
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What should you document? 10
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Cross-cutting concerns 11 HTTP status codes HTTP verbs (PUT vs PATCH) Authentication and authorisation Rate limiting …
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Resources 12 What do the represent? What input do they accept? What output do the produce?
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Links 13 Where can you go? What will you find when you get there?
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What shouldn’t you document? 14
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ What does it look like when you get it wrong? 16 Learning from my mistakes
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ And when you get it right? 18
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ RESTful API documentation tools 20
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Swagger 21 http://swagger.io springfox/springfox
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ You get a lot for little effort 22
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ It doesn’t support hypermedia 24 https://github.com/swagger-api/swagger-core/issues/97
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Always playing catch up – ResponseEntity 26 https://github.com/springfox/springfox/issues/532
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Always playing catch up – HttpHeaders 27
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ The writing experience is unpleasant 28 @RequestMapping(method=RequestMethod.POST, consumes=MediaType.APPLICATION_JSON_VALUE) @ApiOperation(value = "Create a new user", notes = "The name " + "of the user must be at least four characters in length.") @ApiResponses({ @ApiResponse(code=400, message="Bad request"), @ApiResponse(code=201, message="User created")}) @ResponseStatus(HttpStatus.CREATED) public HttpHeaders create(@RequestBody UserInput userInput) { … }
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Swagger2Markup 32 Swagger2Markup/swagger2markup
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ HAL and HAL Browser 33 http://stateless.co/hal_specification.html mikekelly/hal-browser
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Spring REST Docs 35 spring-projects/spring-restdocs http://projects.spring.io/spring-restdocs
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Write as much as possible in a format that’s designed for writing 36
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Don’t use the implementation to provide the documentation 37
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Provide some guarantees that the documentation is accurate TDD – Test-Driven Documentation 38
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Asciidoctor Spring MVC Test Maven or Gradle 39 spring-projects/spring-restdocs
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 41 [source,bash] ---- $ curl 'http://localhost:8080/' -i ----
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 45 this.mockMvc.perform(get("/")) .andExpect(status().isOk()) .andDo(document("index", links( linkWithRel("notes").description( "The <<resources-notes, Notes resource>>"), linkWithRel("tags").description( "The <<resources-tags, Tags resource>>") ), responseFields( fieldWithPath("_links").description( "<<resources-index-links,Links>> to other resources") ) )); 4 3 2 1 5 6
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 46 |=== | Relation | Description | notes | The <<resources-notes,Notes resource>> | tags | The <<resources-tags,Tags resource>> |===
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 48 |=== |Path|Type|Description |_links |Object |<<resources-index-links,Links>> to other resources |===
Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ Thank you 51 @ankinson wilkinsona [email protected]