Full transcript
0:00[Music]
0:06hello everyone it's arnold roy the api
0:08handyman and author of the designer web
0:10apis i can't wait to show you my first
0:13ever live coding session showing open
0:15api specification tips and tricks at the
0:17upcoming running api conference i really
0:20look forward to see you there
0:24hello everyone i'm arno roy the api
0:26handyman that's my twitter handle i'm
0:28the author of the design of web api a
0:30book published by manning in my book
0:33there is a chapter about the open api
0:35specification it's a format that allows
0:37to describe web apis if you are working
0:40on api design or documentation it's a
0:42must have in your toolbox
0:44during this session my very first ever
0:47live coding session i want to show you a
0:50few tips and tricks that will help you
0:52describe your apis efficiently using
0:54this format so let's go ahead and switch
0:56open api specification document that
0:58describes a fictitious api providing
1:01information about characters and toys
1:04from the masters of the universe from
1:06sheets
1:07but first thing first
1:10what we see here is an open api document
1:12it's composed of three main parts the
1:14first one is
1:16the version of the spec we are using so
1:18we'll be using 3.0 there is a brand new
1:203.1 but it is not yet supported by over
1:24tooling so i will stick to this one a
1:26second part information about the api
1:29its name and its version
1:30and then the most important one the path
1:33this is where you will describe all your
1:36get slash these and post slash paths
1:39for now we only have in single path and
1:42operation get characters which is to
1:44post two search characters
1:46it will if everything is okay it will
1:49respond with some content in json format
1:53and the data returned will conform to a
1:57json schema which is defined here and
1:59this schema is an array of elements
2:03which are objects that contains various
2:05properties
2:07this document can be rendered using
2:09various tools such as
2:12the good old
2:14swagger ui
2:16so you have the title version the
2:18operation
2:20and the data
2:21there is another one what that i like to
2:24use which is called
2:26relock so we have the same information
2:29it's just a different look and feel
2:33uh another interesting thing
2:35to do with
2:38open api document is to generate mock
2:40dynamically
2:41so you can do that
2:43using
2:44tools such as prism there are
2:47other ones
2:50this one is open source and all it needs
2:52is
2:53a very basic open api document so it has
2:56started
2:58and now i can call
3:04this smoke
3:08so we'll do a get
3:10characters
3:13and voila
3:14uh we have randomly generated data based
3:18on these very basic documents
3:27but this document is too basic actually
3:30it does not take full advantage of the
3:33open api specification
3:35uh let me show you how we can fix that
3:38for example on arrays you can provide
3:41the minimum or maximum size let's see
3:44let's say that we'll have three items
3:46maximum it's not really realistic but
3:49let's do that we can also say that id
3:52and name will always be written by
3:56adding them to the required lists
4:00we could say that type is
4:03conforms to
4:06a specific
4:08regex
4:10we can say that name
4:12as a minimum length
4:14of 3 a maximum
4:19length
4:20of 36
4:22we can say that birth date is actually
4:25a date
4:27in iso
4:288601 format we can say that age is
4:32between
4:340
4:36and
4:38128
4:41and we could say that side as
4:44three
4:45possible values which are hero
4:48not zero hero
4:50filane
4:53and
4:54neutral
4:58let's look at
5:00how it looks in the documentation now
5:03that looks better we see what is
5:06required what will be always returned we
5:08have information about format constraint
5:11possible values
5:13and
5:14on the mock side
5:16it's interesting now because we are more
5:20we have more interesting data based on
5:22what we have said
5:31an important thing to realize when you
5:33use the open api specification is that
5:35if you don't use specific features you
5:39will
5:40quickly generate inconsistencies
5:43so let's add a new
5:45operation
5:47that will allow us to read a specific
5:49character based on its character id
5:53of type string
5:55note that
5:57in the path here you have curly brackets
5:59to indicate that this is a path
6:01parameter and so it is defined that
6:05so what we want to return is an object
6:07uh an object that is actually the same
6:10as the one we have in the list here so
6:12let's copy that
6:16and last
6:18let's pass it
6:20there fix invitation
6:23and uh let's go back to the mock
6:29so when we read the list of something
6:31characters we get a list of characters
6:34and when we read a specific character
6:38we get character
6:40same format on both sides but what
6:42happen if i modify
6:45a response of get a specific character
6:48by using adding a hack enemy id
6:54on the list
6:55no arc enemy
6:57on the element
6:58and arcane it's inconsistent we don't
7:01want to see that
7:03so
7:04how can we fix that
7:06we can fix that by
7:09defining
7:11a reusable schema
7:13so the components property
7:16will hold all reusable things in your
7:19open api document
7:21and schemas will hold all reasonable
7:23schemas
7:24so let's define the character schema
7:27based on the return
7:29of read an element
7:37so character is a reusable schema and to
7:40use it we will use dollar ref
7:44followed by
7:46a json pointer so this
7:48pointer components schema character
7:52targets components schema character this
7:56and we will use this reference
8:00every time we need
8:02to represent a character and especially
8:04in the list
8:05of elements written by
8:08get characters
8:10i just need to fix indentation
8:15and now if we go back to the mock
8:19in the list
8:20we have the arc enemy id and when we
8:22read an element we have an arc enemy id
8:25simply because they use exactly the same
8:28schema
8:35another way to add inconsistency in
8:38european api specification is when you
8:41work with
8:42parameters especially path parameters
8:47so let's add a delete correct delete
8:50character operation inside the
8:52character's character id path
8:56so we want to delete a character
8:59[Music]
9:00with a character id of type integer
9:05so i just introduce an inconsistency
9:08because to delete a character you need a
9:09character id which is an integer and to
9:12read a character you need a character
9:13lee which is a string
9:15it's not normal
9:17to fix that all we have to do is to move
9:21the definition of the character id path
9:24parameter at the path level
9:27so every parameter that are in this list
9:31will be used for all underlying http
9:35method so for both get
9:38and
9:39delete so i can remove
9:43this one
9:44so no more inconsistency inside this
9:47path
9:48but
9:49what happened if i had
9:52um
9:55a new operation which is based on
9:58characters
10:02for example to list all the enemies of a
10:06specific
10:07character
10:08so i want to add
10:11a character id here
10:14enemies and i'm
10:17looking for
10:19characters enemy
10:21um
10:22i could
10:23copy that
10:25but
10:26i know that it's not a good idea
10:28uh instead i will define
10:31a reusable
10:34parameter inside components
10:36and i will call it
10:39character
10:40id
10:45fix indentation
10:49that way and to use it
10:52i will use
10:54a dollar ref so i define my parameters
10:58lists
11:04so now instead of schemas i put
11:07parameters
11:09and character id
11:12and i can do the same
11:16here that way i'm sure that if i do any
11:20modification character id or path
11:22parameters will be impacted
11:28but
11:29there is still inconsistency regarding
11:31the character id
11:32indeed
11:34in the schema of the character schema we
11:37have an id here which is basically the
11:40character id and it has a pattern
11:43the character id path parameter is just
11:45a string without the button
11:48how to fix that how to be sure that they
11:51will be consistent with each other
11:54you can ensure that by defining a
11:57character id reusable schema
11:59that will be
12:00[Music]
12:02a string
12:08with the correct characteristics and you
12:10can use it
12:12like we have seen before
12:15so it's important to note that a schema
12:18a reusable schema can be anything it's
12:21not a mandatory that
12:23this
12:24is an object it could be a string it
12:26could be a number it could be a boolean
12:28or whatever
12:29and a schema can be used inside the
12:32schema but also here inside a parameter
12:36so we'll put the same
12:38reference that way i'm sure that the
12:40character id
12:42path parameter is consistent with the
12:44character id
12:46property
12:51um
12:52another way to introduce inconsistency
12:55is when you deal with uh
12:58generic responses like 401 you're
13:01supposed to get when you forgot to
13:03provide an access token
13:06so let's define one and of for
13:10christ
13:12it has some content which is in
13:17application
13:18json schema
13:21as i have learned my lesson i know that
13:23i should define a reusable schema
13:26because all my errors will share
13:29the same structure
13:30and so i can use it
13:33here
13:35by the way
13:36uh in another operation i could also
13:39define for one
13:41with a description
13:43that would be different
13:45i could use another schema whatever but
13:47i want to be sure that all my 401 look
13:50the same
13:52and so as we have defined reasonable
13:54schema usable parameter we can define
13:57reusable responses
14:00so we take that
14:03and we will now add a reusable
14:06unauthorized
14:08response
14:11that will contain this
14:13let's fix
14:14indentation and again
14:19we will
14:20use dollar ref
14:22to target
14:25this usable
14:27component of rised
14:31in that way if i had
14:34another response another 401
14:37let's say here
14:39i'm sure that
14:41i can modify in one place all my 401
14:45another way of introducing inconsistency
14:50is to
14:51um
14:53when you have to deal with list versus a
14:56single element because sometimes in the
14:59list you want to provide less
15:00information than when you read the full
15:02element
15:04so
15:05let's see
15:05[Music]
15:07let's illustrate that by modifying the
15:10way
15:11we return the list of characters we had
15:15a character
15:16summary
15:19which
15:20basically is a character but only
15:22focusing on
15:24id
15:25name
15:27now let's move to
15:30get characters which return a list of
15:32characters and we will return
15:34list of characters summary
15:37if we look at the mark now when we got
15:40list we have only id and name
15:44and here we have all the data
15:47what happened if i modify
15:51the character summary
15:53this way
15:55to add a sidekick
15:57id
16:02in the list i have a sidekick id so here
16:05we are supposed to see us a subset of
16:09the properties of the full resource we
16:11have here
16:12unfortunately there is no side quick id
16:14here
16:15it's a little bit awkward
16:17how can we avoid that how can we be sure
16:19that the complete resource will be in
16:21synced with the summarized rufus
16:25let me show you
16:27so we'll keep the characters summary as
16:29it is but we'll modify slightly the
16:32character and we'll introduce a magic
16:35json keywords which is olaf olaf will
16:38allow you to merge values schema
16:42together
16:43so we'll provide the first schema which
16:45is
16:49the summary
16:53and as a second schema we will provide
16:57the original
17:01character id
17:02character schema sorry
17:04stripped off everything we already have
17:06in the summary so we don't have
17:09we don't need id
17:12and name but we give the rest
17:15so now the character schema is the sum
17:19of the summary
17:21and all these properties
17:24if we go back to the mark
17:26we check the list we still have id name
17:28and psychic id
17:29and if we read an element now we have a
17:32psychic id
17:34there are things
17:35no more inconsistency
17:45last example of a possible inconsistency
17:49uh it's when you add a
17:52read
17:53write
17:54operation
17:55so let's add
17:58a hat character operation so this is
18:00done by adding
18:02post
18:03on the
18:05slash characters path
18:08what
18:09so let's see a little bit how it looks
18:11uh it's almost like a get we have a
18:14response with a status code a
18:17schema and so on but now we have a
18:19request body
18:21uh the request body will be sent by the
18:24consumer and it looks like basically a
18:26response we have a content
18:29uh which is in json and the schema
18:33of the dzl
18:34what people usually do when you create
18:36something they
18:38take
18:39they copy the schema the full resource
18:42strip of the properties that are
18:45generated by the server and we have the
18:48body of the request the problem with
18:50that is that i can add typos i can
18:53change
18:54everything and if i
18:58uh don't take attention i introduce
19:00inconsistency
19:02um
19:03how can we avoid fight we can avoid
19:05fight by actually using the exact same
19:09schema
19:11in a request and response
19:17use character
19:19if we do that without any modification
19:22it will be a little bit awkward actually
19:25because
19:26so to create
19:27or is it add a character
19:30uh so to add a character i have to
19:32provide an id it's not my job as a
19:34consumer it's server's job
19:37so to fix that we need to
19:40make
19:41the id
19:43read-only
19:44and this is done by
19:46modifying the id property or more
19:48precisely the character id
19:51and all we have to do is add read only
19:56to true
19:59just for the example we can also let's
20:02say for example
20:03make birth date
20:05right only
20:08and age
20:11read
20:13only
20:14that way people will provide the first
20:17date the birthdate
20:19but it will
20:20only be used to compute the h
20:23and the age will be written
20:25afterward
20:26and so how does it look in redux now
20:30if everything is correct
20:32i go to add character
20:35so
20:35in the request i need to provide name
20:37above that but no age there is no id and
20:41in the response
20:42there is the id
20:44name
20:45no birth date but
20:47thanks to the read-only and writing
20:49effects
20:53uh
20:54that's cool we have seen
20:56many different tips
20:58in order to
21:00allow describing uh really accurately
21:03your interface contract
21:06but this is sometimes not enough
21:10you have to provide
21:11more information
21:13like meta information about your
21:15contract in order to
21:17make this open api document actually
21:20useful especially when generating
21:22documentation
21:24and
21:24that starts with organizing the
21:27operations
21:29let's see that with solo ui
21:33uh so i magically loaded a slightly
21:36modified version of the document and now
21:39all the operations
21:40have been added
21:42are grouped under the character
21:45folder here
21:47this is done by adding
21:50tags on each operation so all these
21:52operations have a tags named characters
21:56what happen if we had other operation uh
21:58let's say regarding
22:00toys
22:03now that we have toys
22:06operations
22:07two of them for our group under the toys
22:10category or tags
22:12what if we want to put toys
22:15above character
22:17to do that without actually modifying
22:20all this
22:25all we have to do
22:26is add
22:27tax information at the root level
22:30when you add tag information at root
22:32level you identify you identify the tags
22:34by the names you can add a description
22:36which can be interesting
22:38and the order you have here
22:40will be the order
22:42in the render so now the toys are both
22:45characters
22:50um
22:51another way
22:53to
22:54[Music]
22:55enhance euro
22:57open api files to make better
22:59documentation is to have example
23:02so on every single property you can add
23:05a single example for example in the name
23:09you can had
23:11an example like skeletor
23:13and immediately
23:14[Music]
23:16the um
23:19let's read a character
23:21renderer will take advantage on it in
23:24the example that's interesting but here
23:27i want more i want to be able to see a
23:29hero and a villain example
23:33to do that
23:34we will add
23:37reusable
23:39example
23:42just let me find the beginning of
23:46components
23:47so i'm adding reusable example i'm
23:50having a hero and a vlan
23:52you see here that each example has a
23:54summary and a value
23:57to use them
24:01all i have to do is to go back to read a
24:05character
24:06and
24:08near the schema
24:10i have to add
24:13reference to those
24:15examples
24:19hate that for a moment
24:21[Music]
24:24components
24:26examples slash hero
24:30and i will take that
24:33you had
24:35the villain example
24:41and now if i go back to redoc
24:4412 yes better
24:46characters with a character and now
24:50yes
24:52i have the hero example and i can see
24:54the billion example which is very useful
24:57for people who want to learn how to use
24:59via your api uh having such a various
25:02example it's very interesting
25:06and last but not least uh descriptions
25:10uh so you can put descriptions
25:11everywhere you can at apr level
25:14tags operations properties and so on i
25:17want to show you two useful tips the
25:20first one is
25:22how to actually put a description near a
25:25dollar ref
25:26so let's go to
25:28uh the characters summary
25:31what people do when we want to hide a
25:33description near arrive is this
25:36unique
25:38id
25:40near
25:42near
25:43ref
25:46this
25:47will actually not work to
25:50have a description near dollar ref and
25:52let's do that on sidekick transform it
25:55in
25:57a character id
25:59you have to use this trick
26:01this trick you use olaf
26:03the first schema will contain
26:06description
26:07bff id
26:10olaf
26:12trick
26:13and the second schema is
26:16the true schema
26:18so now if we go back here
26:22and we look at
26:24with a character
26:26and description
26:27you can see here that there is no
26:29description
26:31and here is a description
26:34hopefully there are good news because in
26:363.1 this will actually work
26:41and so no more of this ugly trick
26:46second things you need to know about
26:48descriptions is that
26:51descriptions can be
26:54multi-line adding a pipe
26:58so you can have longer descriptions and
27:01you can use
27:04markdown so you have uh
27:08here it's italic sections you can add
27:11image let me show you
27:13how it looks
27:14in uh
27:15redux
27:17actually i will smart
27:23yes so you have here
27:25the sections coming from the description
27:28the header in the description you can
27:29have sections sub sections uh you can
27:32add image like this using a link you can
27:35embed image because markdown supports
27:38html so you can use the old base64 image
27:41data image trick image and that helps to
27:44make your api
27:47your open api file
27:49without any dependencies to anything
27:51else
27:55so that's it and
27:57now we move on to
27:59[Music]
28:01the end um
28:03but what i wanted to show about tips and
28:05tricks uh concerning the open api
28:07specification
28:09um
28:10in order to
28:11speed up how you write open api
28:14specification i recommend you to read
28:16the documentation
28:18sometimes it can be a little bit
28:19complicated so i created this tool i
28:23would show you the structure of an open
28:25api document and you
28:28you can go directly to the documentation
28:31of something here so we have info object
28:33and so on
28:34uh and it's really useful to discover
28:37how all this works and you can see
28:39i have not showcased everything every
28:43usable comparison component for example
28:46another thing
28:47you could use in order to speed up the
28:49writing is actually not writing up an
28:52api specification because nowadays there
28:54are more and more graphical user
28:56interface that allows you to
28:59use forms and other stuff but
29:03let you describe your apron very quickly
29:07but knowing how the specs works will
29:09help to take advantage this tools and
29:12sometimes these tools do not support all
29:15of open api's features actually there is
29:18no tools on the market that supports all
29:20of the functions so sometimes you have
29:22to mingle in the code
29:25and that's a wrap-up
29:28so if you
29:29retain only a few things
29:32when you
29:33describe an api with the open api
29:35specification on each property use all
29:38of the features to describe them
29:40accurately minimum maximum patterns or
29:43whatever
29:44take advantage of usable components in
29:46order to keep your api definition
29:49consistent so you use components you use
29:51rf
29:53use also hold off because merging schema
29:56is very very useful and then go beyond
29:59the interface contract and add some
30:00documentation add tags add meaningful
30:03and rich description and add examples
30:06that's all for today thank you very much