161 comments

[ 4.7 ms ] story [ 227 ms ] thread
I'm surprised RAML isn't suggested as na alternative. http://raml.org/
Or API Blueprint. Markdown is a really nice format for documenting your interfaces and you don't really need special tools to render the documentation for the web. Just checking the file into GitHub creates a link to human-readable documentation.
> The Problems with Swagger

> This is a Swagger misusage problem, not a problem from Swagger per sé.

The TL;DR is a list of gotchas and best practices the author has learned from using Swagger.

My problem with Swagger is the Swagger editor. It just works sometimes, but sometimes everything is just red for no reason. Tried with Safari, ChrOme, Ff on different Macs. Am I the only one who thinks this tool is unusable?

Edit: Cheers to you guys at Novatec, have to take a look on InspectIT again.

It's definitely buggy. I've had more luck with it in Firefox than other browsers. Refreshing and changing a line or two [usually] snaps it back into shape.

Export your file frequently.

This is a bit off topic, but I feel that Swagger etc... and actually most API docs are to human centric. You can't auto chain APIs together without a lot of developer intervention. The one thing I saw that allowed that was SADI services [1]. An awesomely pragmatic use of the semantic web. Pity it did not get picked up by Google etc...

[1] http://sadiframework.org/

I really like the idea of HATEOAS but I have never seen hypermedia controls done in the wild across any companies I've worked for nor on any client projects. I think it's very cool but a lot of development patterns don't consider it.
I agree that HATEOAS is never deployed anywhere, but I think I'd go further than that.

It's impossible for me to see how it would be possible to write a HATEOAS client, and I can't in practice see anyone doing so.

Optimizing for HATEOAS seems to me to be optimizing for entirely the wrong metrics, and a complete waste of development time and effort.

A few counterpoints as I drift by:

The HAL hypermedia format is in use at Comcast, powering the Xfinity TV API. Not only does it take advantage of hypermedia and HATEOAS, it also splits requests/responses in order to make the most use of HTTP caches. https://boston2016.apistrat.com/speakers/ben-greenberg

Dunno if you're serious about not seeing how one could write a HATEOAS-driven client library or if I'm being trolled, but here's one that I wrote a couple of years ago: https://github.com/gamache/hyperresource There are many others as well (especially for the HAL format).

I'm definitely not trolling - it's just that's not how clients work.

I don't write a client by doing a random walk through the API until I get to the information I need, I want to call the API that I know I need to give me the information that I want, and for performance, I want it all to be returned on a single call ideally.

e.g. If I want user B's playlist, I don't want to have to crawl:

/friends/ => ['b': { 'links': {'info': '/friends/619'} }]

/friends/619 => {'links': {'playlist': '/friends/619/playlist' } }

/friends/619/playlist

But it's not a random walk. And it sure beats custom apis returning random bags of data for any given UI screen.

Sometimes you do a few more web calls than you might otherwise. If you can get away with it then great! Because the benefits are plenty

Hell! Even just having the uri of where the resource came from is useful enough. That's before you've introduced related resources.

At this point aren't you still hard coding commands, but using "links" rather than URLs? And doesn't the dependency on every link in the chain outweigh one - easily maintained - URL?
You're hard-coding 'terms' from a hypermedia 'vocab'.

The thing is, if you use well-known terms, your client will work against ANY API that uses those terms, not just the one that you coded it to work against.

Not only that, but the APIs will have flexibility to move things around, or delegate functionality to other hosts by linking through.

As for the cost of walking the chain, once a target resource has been found the can be cached, and you only need to rewalk if the resource 404/410s.

> It's impossible for me to see how it would be possible to write a HATEOAS client, and I can't in practice see anyone doing so.

There's nothing complicated about a client that understands Hypermedia links. You start at the root, it'll give you a set of links to follow, and you recurse. Here's a browser that can take a HATEOAS-compatible API and will let you work your way through the API: http://dracoblue.github.io/hateoas-browser/

> Optimizing for HATEOAS seems to me to be optimizing for entirely the wrong metrics, and a complete waste of development time and effort.

Correct. HATEOAS is a neat parlor trick: point a dumb client at your API and watch it enumerate all the possible operations. Wow! The problem is that APIs aren't consumed that way, they're consumed by humans who need to decide which API calls to make based on user actions in the application... so developers will resort to consulting documentation in order to piece together the correct calls in the correct order. That's not something you can encode through Hypermedia. At best you can just model the relations between calls, but not the "how" or "why" of everything.

I meant a user friendly client, not something aimed at API developers. Sure you can create something which is aimed at Developers, but it's not presenting the data in a way any user would understand, or in a way that a UX expert can flex.

Fundamentally, your display logic should not be linked to your API schema, but HATEOAS essentially enforces that, because you can't predict what links will be available.

your display logic should not be linked to your API schema

Why not? The whole point of HATEOAS is to design your API schema in function of your application flow. You know, just like we do on websites.

> I meant a user friendly client, not something aimed at API developers. Sure you can create something which is aimed at Developers

Just for clarity, are you talking about API Developers or API Client Developers? I would see the primary beneficiaries of HATEOAS being developers consuming your API - i.e. client developers.

every web browser you use is a hateoas client

you get some html with embedded links and then the browser automatically goes and fetches css, js, images...

the remaining links it just presents to you, the user, to follow or not as you choose

hateoas is not a complicated idea. it's not meant to replace SOAP or gRPC or thrift. it's something else

Except the browser really isn't. It has strict behavior, and the list of what happens as it loads that hypermedia is deterministic and known to both the client and server. The difference between what happens when the browser sees a "stylesheet" link reference and a "icon" one is significant, and not something the browser is expected to figure out on its own.

The HATEOAS idea is that you throw that out, just use some aribitrary XML (sorry, "hypermedia") to return your application state, and that this somehow magically empowers the client to be able to puzzle out all the things that can be done to your state.

Except it can't. It's just arbitrary junk if you don't have a schema and a spec. And it will always be so. Discoverability is (1) not something you can get from a data structure and (2) something best provided by documentation, not runtime behavior.

You obviously need SOME spec or schema to be able to understand what to do with hypermedia, but it really comes down to how many things you have to define. It lets you define a smaller number of pieces and their functionality, and then lets you compose those smaller pieces into larger functions, and even create new combinations after a client is created without having to update the client.
I think you have a completely wrong idea about HATEOAS. The application is certainly expected to be able to handle the data format, not figure out by magic. As Fielding writes in his dissertation, REST components communicate by transferring a representation of a resource in a format matching one of an evolving set of standard data types. The client is certainly supposed to understand these data types, that's why they must be standard (like HTML). The dynamic part comes from the formats themselves, which may have variable or optional elements depending on the state of the resource.
Someone needs to fix the wikipedia page on HATEOAS then, because it says exactly the opposite of what you just did in its third sentence.

(One of the other problems with Fielding's work is precisely this word-salad of new jargon and usages, leading to exactly this kind of what-does-it-REALLY-mean-anyway confusion. But that's an argument for a different thread.)

From the wikipedia page: "The media types used for these representations, and the link relations they may contain, are standardized."

As for Fielding's work having a word-salad of new jargon and uses, I frankly didn't get that by reading his dissertation, which I found quite clear. There are a few concepts (Resources, Representations), but I think they make sense in the context.

The browser is driven by advanced AI wetware that understands the semantics of the data and can make decisions on what to do next.

I think REST/HATEOAS purists have always overplayed the browser example.

Pure machine to machine interaction is hard to automate.

You can use game AI techniques like needs-based-AI to create smart, resilient clients. What fun!
> Optimizing for HATEOAS seems to me to be optimizing for entirely the wrong metrics, and a complete waste of development time and effort.

It depends, it's just a way to reduce coupling between a webservice and its client apps. Instead of hardcoding all the URL endpoints into the client, the client has to follow the links provided by the webservice instead. If this layer of indirection has advantages for you depends on your use case. You could compare it to using DNS instead of static IPs. Static IPs work fine but you end up with more coupling than using DNS.

If I remove the reference to a link in the response, it doesn't remove the clients need to:

a) know how to retrieve that link (i.e. what resource do I need to retrieve in order to get that response)

b) requirement for that link to exist (they still need that link).

Requiring that a client know that to get data Bar, they need to retrieve resource A, follow the link at foo[n]._link to retrieve resource B, and then following the link at _link.bar feels like a total non starter, and actually increases coupling.

I am not sure I get your example. But yes the client still has to know what to do in advance.
>But yes the client still has to know what to do in advance.

According to Roy Fielding[1] (who came up with the concepts of ReST and HATEOAS:

"A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience"

So if an application doesn't rely on "standardized media types", and "the client still has to know what to do in advance", then it seems like whatever you're doing, it isn't HATEOAS after all.

[1] http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hyperte...

I don't think you and your parent mean the same thing. The client "has to know what to do in advance" in the sense that the human building the application needs to know what user interface they want to build, and know how the API works (in advance) in order to use it to populate the interface.

If you have an extremely dumb interface that just displays fields in API responses, then ok... but that's a very trivial UI that accounts for... basically no useful products ever.

It's called a browser.
I'll be honest, I stopped reading the article as soon as it mentioned Hypermedia, because I instantly saw the problem as the author being upset that Swagger is not Hypermedia.

I have a really hard time seeing APIs ever reaching that level of standardization, and I'm tired of having the Hypermedia discussion. I generally support logically organized APIs with good documentation. As long as those things are true, I'm happy for the API.

HATEOAS if your API needs to maintain state AND you want links AND you want a standard. A game API would be a good use case.

REST if your API should not maintain state between requests. If you want links as a part of your response (and want to use a standard) use e.g. HAL or JSON API.

I view them as mutually exclusive.

This seems more like, "issues with how Swagger is used in Java". A lot of Java developers are used to the SOAP APIs of yesteryear, and thus try to create clients with Swagger when they should be using gRPC or Thrift.

In other language paradigms, I haven't faced this issue. Swagger is _just_ documentation, and a nice front-end on top. The Java annotations definitely make it easy to generate, though, I'll give it that.

> A lot of Java developers are used to the SOAP APIs of yesteryear,

Hmm way to paint Java developers as old dinosaurs...

> and thus try to create clients with Swagger when they should be using gRPC or Thrift.

They're trying to create clients with Swagger because they've made a REST API (yes you can do that in Java!). If you're using gRPC or Thrift, you're not making a REST API.

REST, if one insists on using it, should really be layered over top of something saner like gRPC or Thrift.

Personally, I've always found REST troublesome and overhyped. There's always a few incidents where you spend hours trying to figure out why something isn't working before realizing you had the wrong method on the request. There's no reason the thing you actually want to do to a resource should be tucked away in some header that's not always easy to access or see, it's just asking for trouble.

What HTTP servers and clients are you using that don't clearly log the request method? I've never seen one where it's easier to read the body of the request than the method.
How about urllib, the Python default?

    def handle_thing(thing):
        r = urllib.request.Request(url='example.com',
                                   data={'stuff': 1})
        return urllib.request.urlopen(r)
Just one example.

I know the tooling has improved somewhat since REST has become extremely common, so this is less of an issue now than it used to be (for example, most people use the Python requests module now, which makes it harder to use the wrong method (though many other HTTP libs still have the older urllib-style design)), but it's still annoying in principle. Combine with the fact that people tend to have different ideas about what the HTTP verbs and response codes mean, and it's pretty yucky.

Compare with Thrift, where you define an interface, list the possible exceptions, and generate stubs that auto-handle all of this communication exchange for you. All you have to do is make sure that you're calling the correct function, which should be pretty obvious.

This differs from setting the correct method in the HTTP headers in a couple of ways: first, HTTP clients usually assume a default method of GET. With a different protocol, there is no default "method", your action has to be defined somewhere. There will be no assumption (unless you code something implicit like this on top).

Second, a more conventional method has increased code locality, meaning the code that affects the operation is likely to be in the same source file/area. You'll normally be calling an ordinary function name like SaveThing inside the application logic flow, and it will be easier to debug, easier to realize the problem, etc.; the operation to perform is not tucked away in some other contraption that affects the headers.

Is it possible to design REST codebases so that such errors are hard to cause? Sure. But why do it the REST way and make it harder on yourself?

It should be just as easy to see what function you're asking the API to perform on a resource as it is to see what you're sending it. The operation I want to perform is an intrinsic part of what I'm doing. There's no reason to separate it and make it hard. I'd even prefer url-based actions, like example.com/string_save, because then at least the resource and operation are defined in the same spot.

A simple JSON envelope that has an "operation" key separate from a "data" key would make this easy, but then it's not in your header anymore, so it's not "real REST".

You're going on about the value of "conventional methods" in a criticism of using HTTP verbs?

Understanding the difference between a GET and a POST isn't some new-fangled idea, it's decades old. Like Tim Berners Lee old.

I didn't even know what Thrift was until I Googled it, and found out it was developed at Facebook. Okay.

I'm stunned. Do you write code that runs on the internet? How did you even get employed?

>You're going on about the value of "conventional methods" in a criticism of using HTTP verbs?

Yes? These have some intrinsic value that is defined in the domain. There is no potential of vocabulary contamination because everyone comes into the domain with a clean state. An ambiguous, abused common vernacular is worse than a clean domain-specific one.

>Understanding the difference between a GET and a POST isn't some new-fangled idea, it's decades old. Like Tim Berners Lee old.

GET and POST usually work out OK; it's stuff like HEAD, PUT, and PATCH that people usually argue about, not to mention response codes.

GET, POST, and the HTTP intricacies are fine as a concern for HTTP clients. REST has shot through that and made it something that everyone has to worry about.

The issue is not only that no one can agree on how to do REST, but it's also, as stated in my other comment, that REST makes it harder to see what's going on. It requires important information (the verb) to be tucked away into something that takes extra steps to access. I'm not saying it's impossible to access that; I'm just saying it's error prone to do it this way.

>I didn't even know what Thrift was until I Googled it, and found out it was developed at Facebook. Okay.

I hate most "Project-By-BigCo" projects, but not everything that comes out of Google or Facebook is automatically evil.

Thrift is now controlled by the Apache Foundation, not Facebook. And it's a very common IDL, but I'll refrain from returning your snark. ;)

>I'm stunned. Do you write code that runs on the internet?

I'm not the only one. [0]

>How did you even get employed?

Just lucky I guess.

[0] https://twitter.com/skamille/status/588713316358475776

The edit timeout is expired on my other comment, but it just occurred to me that, since you were unfamiliar with what is arguably the most-used IDL today, you may not understand that interface definition language like Thrift defines the interface, not just the objects. You'll have a section like (adapted from the Apache Thrift tutorial file [0])

    service Calculator extends shared.SharedService {
       void ping(),
       i32 add(1:i32 num1, 2:i32 num2),
       i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch)
    }
which lists the method name, parameters and types, return type, and possible exceptions. The objects are defined elsewhere in the file (or in an include). The method name is not just a value that is randomly assigned by the developer (and how could it be? the interface has to name the things so they can be referenced).

To be a firm REST religionist, as you seem to be, you must not have worked with it very often, but you can see that an actual IDL, and Thrift is just one of several, would make things much easier than the loose "My REST is purer than your REST" dick-measuring contests.

[0] https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob_...

I'm not even sure what you mean. RPC is fundamentally different than REST and I don't know how you can layer on over top of the other?
RPC is not fundamentally different from REST. REST is a form of RPC. (/me ducks tomatoes thrown among boos and hisses from the crowd)

The difference is that the processes behind REST speak with HTTP. You're still doing a "remote procedure call"; you're asking for a remote process to execute some function on your behalf and return the result. RPCs facilitate the same exact thing. How is this a "fundamental" difference?

[I'm speaking here of the practical difference, not some difference that was originally hypothesized in the dissertation.]

Thrift contains both an RPC and an IDL, but they don't necessarily have to be used together. Protobufs is just an IDL; gRPC is the RPC, which was released just a year or two ago.

You would layer Thrift and REST by putting a REST API over the top of an interface defined in the Thrift IDL. You could also run the Thrift RPC for Thrift-compatible clients.

RPC doesn't have an Uniform Interface.

Say you have a user profile, which has a Gravatar associated. Sure you can have a getUserProfile() procedure that fetches the user information, but what about the image? You can write a getUserAvatar() procedure that proxies it, but that's wasteful.

In a RESTful system, you have a Resource Identifier (URL) that you can indicate as an hypermedia reference (link), with which the client can use a standard data fetching verb (GET) to retrieve it directly from the other server.

Of course, in a practical setting the getUserProfile() procedure would return the URL, but that's just an admission of the limitations of RPC vis-a-vis REST.

On the other hand, REST itself has its own problems and limitations, and is certainly not adequate for every use case, as Fielding's dissertation mentions at length.

REST doesn't have a uniform interface in practice, either.

I haven't read the dissertation so I can't really comment on the hypothetical REST (though it is on my reading list now, and not that it really stops anyone else), I can only comment on what, in the real world, passes for a "REST API".

"REST" principles certainly sound nice on paper, but for the most part, it's clear that they're completely implausible to realize in a wide-scale, meaningful way. After over a decade of pro-REST propaganda, people still can't even tell if their interface is "RESTful" or not.

The parts of "REST" that have worked are the two simple basics of HTTP: GETting a resource to read it, or POSTing a resource to write it. Nothing else has really stuck or can be expected to have a uniform meaning (and even POST's behavior will vary, with some doing an upsert-style operation and some accepting it only for new writes and using PUT and/or PATCH for edits). 200 OK means it worked most of the time, but sometimes people will return a plaintext error with it. 404 might mean that the resource is not found, or it might mean that the route is not found/no longer valid (or that it was called with invalid or improperly encoded parameters). There are a bunch of esoteric codes that are used to mean a lot of different things, always depending on who the implementer is.

So the "uniform interface" is just that everyone is using HTTP, to mean all sorts of different things. In practical terms, it doesn't really amount to much, except a lot of blathering over whether something conforms with a theoretical ideal that everyone has already demonstrated they're unwilling to conform to.

REST has been extremely successful, having scaled to billions of services, like the one we're using right now.

"RESTful APIs" have mostly been a failure, I fully agree with you on that. The difference is that I think it's a cultural problem; when people like Licklider sensibly thought about a future wherein computers would learn to talk to each other (of which REST is a first step), as static protocols obviously didn't scale, we proved him wrong by sheer brute force. Watching something like Bret Victor's The Future of Programming, it's hard to miss the giant indictment of our whole profession.

That said, since I know the term is hopelessly lost, I don't push for REST either. Our service uses XML/JSON-RPC.

There is absolutely no reason why you can't implement the same REST concepts on top of another RPC mechanism.
Of course you can. But x86 machine code doesn't have Monads just because Haskelll can be compiled to it. In both cases, the concepts have to be broken up to be implemented, as they are not meaningful at that level.
Can you please explain. Which REST concept cannot be implemented? I think the problems that REST/SOAP solve,is that the "levels" that you speak about, have already been implemented by someone else. I am talking of serialization, transport level details (e.g. SOAP over JMS) etc. If even transport level abstraction has been taken care of by the implementers, then which concept do you think, cannot be implemented.
Thrift and protobufs are underappreciated. Better integration in something similar to the Swagger Editor would give these a much more comfortable home and allow them to see adoption in the web world, where people generally expect things to be a little softer.

I've never really liked the REST paradigm, so I'd be pleased to see it die.

My biggest complaint with Thrift: they still make you do some convoluted hacks to get a two-way ("streaming") connection in the RPC, and when this is discussed, they usually kibosh it pretty quickly by saying it's an unsupported case and that you can find some hacks online, but they don't want to talk about it any further.

This may not have been a big problem for them before gRPC was released for protobufs, but it's definitely something that's worthy of attention and response now. I know lots of people who are going with protobufs instead because of this.

The other thing is that while Thrift boasts a lot of language compatibility, several of these are buggy.

I've never really liked the REST paradigm, so I'd be pleased to see it die.

Don't hold your breath. Fielding's thesis is already 17 years old, so one would expect its philosophy to endure by the Lindy Effect if for no other reason.

If the "Lindy Effect" was a natural law and not simply a shorthand to refer to enduring popularity, nothing would ever die out; its lifetime would continually double. Wikipedia notes this: Because life expectancy is probabilistically derived, a thing may become extinct before its "expected" survival. In other words, one needs to gauge both the age and "health" of the thing to determine continued survival.

There are lots of things in tech that we just stop doing one day. They get replaced by a different hot new thing. I'm sure REST will not go extinct for a very long time, but it definitely could go cold, just like its popular predecessors.

Perhaps REST as the thing you do over http with http verbs won't be around.

But the architectural principle called REST will be around forever because it's essentially the same thing as functional programming.

That REST is cache friendly corresponds exactly to the way that pure functions are memo-ising friendly.

> It's crazy to me that it's harder to write a Swagger file than it is to write the API itself. And there's a lot of tooling that benefits from Swagger, but... I've found they all work 80%. Codegen, documentation, etc get 80% of the way there.

Completely agree. This was one of the reasons I liked using hapijs and joi in the past; they combine to validate and setup your HTTP endpoints and the swagger documentation is literarily generated from that code and not some separate thing you have to write. Unfortunately, outside of that very specific space, very little seems to exist.

Hapijs has its own issues and it's rarely my goto node framework anymore but it's hard to beat doing documentation that way.

I think Swagger is nice--codegen makes it simple to generate API clients for various languages/frameworks. Saves a lot of time and potential sources of errors. If there is something easier/better/more reliable, then I am all ears, but Swagger keeps getting better.
I had these same issues. It took me considerably more time and effort to write a Swagger spec and get the UI to actually behave than it did to write my entire API and some simple docs in markdown.

I also tried out the "codegen" and a few other projects that generate boilerplate from a spec (for Python) - the code it generated was frustrating, lengthy, and much more complex than the simple endpoints that I quickly wrote from scratch.

>I had these same issues. It took me considerably more time and effort to write a Swagger spec and get the UI to actually behave than it did to write my entire API and some simple docs in markdown.

It's definitely going to be faster to just write it at first. Swagger, and everything like it, is an investment.

>I also tried out the "codegen" and a few other projects that generate boilerplate from a spec (for Python) - the code it generated was frustrating, lengthy, and much more complex than the simple endpoints that I quickly wrote from scratch.

That's auto-generated code for you. Can't rival humans (yet), but that doesn't automatically mean it's not useful.

Compare hand-rolled ASM with compiler-rolled ASM for an example. Human-written ASM will often be much more compact and readable, sometimes even more performant, but then you have to write ASM instead of letting the compiler do it for you.

> It took me considerably more time and effort to write a Swagger spec and get the UI to actually behave than it did to write my entire API and some simple docs in markdown.

How long did it take to write API consumer libraries in twenty languages and update every one on API change?

If you don't care about that, then Swagger isn't a good idea for you. But I'd think really hard about whether you should care about it if you think you don't.

> the code it generated was frustrating, lengthy, and much more complex than the simple endpoints that I quickly wrote from scratch

Sure--but you didn't have to write it.

Is whatever value people are getting out of client libraries provided by something generic like http://unirest.io ?

When does it make sense to issue API-specific client libraries for a plain ole RESTful API?

> When does it make sense to issue API-specific client libraries for a plain ole RESTful API?

Any time you have a statically-typed language consuming you. Having to write my own Jackson declarations to pull in your API to a JVM project or my own DataContract barf for a CLR one is a quick way to make me hate you, and me hating you means I'm already looking for an alternative that isn't you that gets out of my way.

I sort of thought the opposite, that the client libraries are what is getting in the way.
So you enjoy writing a bunch of boilerplate class files that are manual translations of somebody else's doc?
No, I just like to get started coding API calls.
All the time? Most "RESTful" (meaningless term, by the way) APIs have a series of convoluted steps that are annoying and tedious to hand-roll.

Authentication is a good basic example. Different APIs will have different requirements for authentication headers. Successful authentication frequently requires multiple steps, like an initial request to get a session token. Many APIs will also require your request to be signed according to their specifications, and to stuff that signature in a header with a special name.

Every API expects to receive data in its own format. I don't want to have to make a bunch of validators that lay on top of your data model. These can and should be provided, and Swagger makes that automatic.

As eropple states, if something is making me do all of that by hand, I'm already looking for something else that will allow me to just say "import project_lib; project_lib.authenticate(); ..."

If you're just talking about something that is read-only and that only emits a single field I care about, sure, no need for a library. Something like the free version of ipinfo.io would be a good example.

Stuff that's more complicated than that, yes, it needs a client library.

One could argue that clients can roll their own damn client implementations, and that autogenerating client libraries is the folly. This is just REST, no?
One could argue that, but one would be creating a really sucky developer experience that can be avoided with comparatively little work.

- "Just REST" doesn't actually encapsulate meaningful behaviors by itself. It's by no means complete. Swagger is a partial patch on this by trying to reduce the scope of what your API is supposed to be doing, and it's not perfect, but it's better than "welp, throw Grape at it."

- Most statically-typed languages are a pain in the ass when it comes to HTTP responses because those responses can't be reified without types, and returning JSON blobs that don't have mapping types on the other end super sucks. I can do it myself if I absolutely have to--but making me waste my time doing it is silly.

> "Just REST" doesn't actually encapsulate meaningful behaviors by itself.

Yes it does: open a socket, speak HTTP, get some data back. Yeah you'll have to feed it into a JSON parser or whatever but apparently people consider that a lot of work now?

I do agree on the points with statically-typed languages. Finagling dynamic types in such a system is a PITA. But I do not see the need for autogenerating tooling if you're consuming REST from a dynamic language; all you've automated is the HTTP call and data parsing (which takes very little time to write oneself)

Maybe I've been living under a rock the past 10 years but REST has never required very much effort, either to implement or consume. Then out of nowhere I begin encountering all these weird-ass tools -- Swagger (and who the F named that one, Old Spice?), Grape, whatever. All this crazy software to do all these crazy things when... it's just HTTP and JSON over the wire :/

At some point people need to ask themselves, 'how much abstraction is too much abstraction?'

Swagger's real value-add to me is in a standard documentation format for REST APIs, but the last instance I used of Swagger made my work more difficult :/

One can argue that, but in practice, this often means that the clients will just take their business and go elsewhere.
> I also tried out the "codegen" and a few other projects that generate boilerplate from a spec (for Python) - the code it generated was frustrating, lengthy, and much more complex than the simple endpoints that I quickly wrote from scratch.

Personally, I don't understand why codegen is even necessary as opposed to a pure object-oriented client that works directly from the Swagger spec. Before I knew Swagger existed, I actually implemented such a client based on my own made-up spec.[0] It's relatively naive, but I attribute that more to my relative youth in development than to the concept itself.

[0]https://github.com/haikuginger/beekeeper

> I also tried out the "codegen" and a few other projects that generate boilerplate from a spec (for Python) - the code it generated was frustrating, lengthy, and much more complex than the simple endpoints that I quickly wrote from scratch.

For Swagger Codegen, you can also customize the mustache templates in whatever way you want (e.g. replacing 4-space with tab in C# client templates). The auto-generated code may sometimes look lengthy but we usually do it with reasons based on feedback from developers. Please share with us more via https://github.com/swagger-api/swagger-codegen/issues/new so that we can further improve the output.

You may find Swagger Codegen a huge time saver in use cases in which the endpoints are growing (e.g. from 20 endpoints in v1 to 40 endpoints in v2) and you will need to provide API clients in multiple langauges (e.g. Python, Ruby, PHP, C#, etc)

Disclosure: I'm a top contributor to Swagger Codegen

Excellent points that are like a breath of fresh air.
Swagger is also a partial solution. I'd rather provide an API client library and clearly document how to use the client library and not the underlying REST API.
Check out Stoplight.io for a good tool for managing swagger documentation. It's a lot easier than managing the YAML itself.
Are there any good alternatives?

I used REST which forced me basically to dig deep into online documentation when I wrote a client, but was rather straight forward to implement a server with.

I used SOAP which forced me to write a giant WSDL file, but was rather nice to work with on the client side.

GraphQL seems to obliterate this problem with its auto discovery mechanisms, but I don't know too much about it.

This is GraphQL's killer feature imo. We describe our schema in easy-to-understand GraphQL Schema Language, use that text file to actually initialize our server, and the included GraphiQL UI automatically provides full documentation and interactive query tool. Our users no longer need nearly as much hand-holding to grok the data model.
I've implemented Swagger with several APIs and agree that it's crazy complex and time-consuming to write Swagger files manually.

I believe the best use-case for Swagger is to develop the API (perhaps just defining the routes with payload and response, but without controllers), and then auto-generating the Swagger files. This way the API consumers always have an up-to-date documentation, and there is only one place which represents the current state of the API.

Exactly. I wrote a project (https://github.com/EverythingMe/vertex) where you define the API with a semi declarative syntax in Go, and it just translates to swagger so you can generate documentation and playgrounds effortlessly. It worked very well.
Swagger yaml is hard to write? Hmm.. relative to the code that services it or consumes it, I find its pretty trivial.
(comment deleted)
One problem... it takes Swagger thirty-freakin-seconds to load its auto-generated whatever for Magento Community, and it has to do this every freakin time!
That's... odd. Even running M2 off of DevBox on my Mac the swagger endpoint renders in 5-10s (first visit).
(comment deleted)
I am working on auto generating clients with built in service subscription based discovery, shock absorbers and circuit breakers based on open api (swagger). We design our APIs with customer focus and therefore haven't run into some of these problems so far.
I use swagger annotations to generate a swagger json automatically from my REST services. It is quite effortless once set up.
In terms of API documentation, the biggest problem is making sure the documentation is in sync with the actual code. I'm looking into using JSON Schema [1] along with Swagger and Dredd [2]. Making it all language-agnostic is a key. If anyone is doing anything similar, please, share your experience.

[1] http://json-schema.org/

[2] http://dredd.readthedocs.io/en/latest/

Ensuring documentation is in sync with code is straightforward if you have tooling in place to generate documentation from code. For example, at edX we use Django REST Framework and django-rest-swagger. Our Swagger docs are always up-to-date.
We have hundreds of APIs, and we use RAML + json schema.

Since Swagger (OpenAPI) seems to be gaining ascendancy, I recently (some months ago) looked at migrating off of RAML, but at that time the Swagger guys had a philosophy that they would only support a subset of json schema.

I get their reasons - they want to be able to generate code. But the things they didn't support (like oneOf - needed whenever you have a set of resources of varying types) are a show stopper for many APIs with even moderately complex payloads.

For us at least, its more important to have a single source of truth for our APIs than to be able to generate code from the specs. Hence we remain on RAML (which seems great - just looking like its losing the popularity contest).

We also use RAML + json schema primarily as the single source of truth. We use https://jsonschema.net to generate json schema by providing it examples.
in my opinion oneOf is bad for interoperability
Do people write Swagger files by hand? That sounds awful. I was under the impression everyone used tools like I use in Clojure (compojure-api[0] and ring-swagger[1]).

[0] https://github.com/metosin/compojure-api

[1] https://github.com/metosin/ring-swagger

I didn't realize Swagger was meant to be an intermediate format.
It's not an intermediate format necessarily, but it reflects information already encoded in your route definitions. It seems silly to maintain that information twice in two different locations.
In my experience (we have a product where people upload Swagger files), most people write it by hand. There's two reasons:

1) Many people use Swagger to design (rather than document), meaning the Swagger comes before the code

2) Most people just prefer to write it out, since the tooling otherwise isn't necessarily great (especially for non-developers)

We ran a poll and "by hand" (either on Swagger Hub/Apiary, or locally) won by a landslide.

How does a non-developer know how to document or design an API?
Perhaps the first pass of the doc is written by a developer but it is later updated by a tech-writer, or you need to produce a translated version.
I do and have, yes. We generally push for design-first specs, which means there's nothing in place to generate the Swagger file yet. If the API is simple, as they should be, then it's not that awful, really.
I've found swagger codegen to be really, really inconsistent between different implementations. A few of them - I recall we had a team using Qt - didn't even generate compilable code. When I looked into the infrastructure of the codegen project, I found... mustache.

Check it out yourself: https://github.com/swagger-api/swagger-codegen/tree/master/m...

Mustache is fine for doing a little view rendering, but for language generation... it's really obnoxious to use. Say you want to customize the output. Well, now you're basically replacing one of those magic .mustache files. And what's the model you use to generate those mustache files? Well, you got to look through the codebase for that.

I ended up just not using swagger-codegen, and created my own StringTemplate based system, which got the job done a lot faster. The swagger core model was really janky to build logic around, however, so this system was really implementation specific.

In the end, were I to do it all over again, I would have probably just built a different mechanism. And honestly, building your own damn little DSL and code generators for your use case will probably be faster then integrating Swagger. Especially if you do not use the JVM as part of your existing toolchain.

I've not found anything to support multiple languages easily. If I were to do something today, I'd probably create a custom API DSL, custom code generators, with an output for asciidoctor (which is awesome) and example and test projects that test the generated code. Once you get the pipeline going the work is pretty straightforward.

> I've found swagger codegen to be really, really inconsistent between different implementations. A few of them - I recall we had a team using Qt - didn't even generate compilable code. When I looked into the infrastructure of the codegen project, I found... mustache.

Yup, some generators (e.g. ActionScript, Qt5 C++) are less mature than the others (e.g. Ruby, PHP, C#). For the issues with Qt5 C++ generator, please open an issue via http://github.com/swagger-api/swagger-codegen/issues/new so that the community can help work on it.

> Mustache is fine for doing a little view rendering, but for language generation... it's really obnoxious to use. Say you want to customize the output. Well, now you're basically replacing one of those magic .mustache files. And what's the model you use to generate those mustache files? Well, you got to look through the codebase for that.

Instead looking through the codebase, you may also want to try the debug flag (e.g. debugOperations, debugModels) to get a list of tags available in the mustache templates: https://github.com/swagger-api/swagger-codegen/wiki/FAQ#how-...

I agree that mustache may not be the best template system in the world but it's easy to learn and developers seem pretty comfortable using it.

> Especially if you do not use the JVM as part of your existing toolchain.

One can also use docker (https://github.com/swagger-api/swagger-codegen#docker) or https://generator.swagger.io (https://github.com/swagger-api/swagger-codegen#online-genera...) to leverage Swagger Codegen without installing JVM.

Thanks for the feedback and I hope the above helps.

(Disclosure: I'm a top contributor to the project)

Mustache is the most limiting (not to mention ugly) template language I've seen in a long time. It allows no logic whatsoever and even writing simple if statements is tedious. We have a Swagger spec from which we generate Asciidoctor documentation via a Gradle plugin which works very nice, and generate basic POJOs for Java and POCOs for C#. That... does not work very well for our purposes.

We wanted to produce named enumerables by using custom extensions and found no way of doing it with Mustache. It didn't help that our custom extension YAML was passed into Mustache as serialized JSON. One of our developers took it upon himself to make it work and ended up writing his own simple version of the Codegen which works well enough for us. He tried modifying one of the backends preparing data for Mustache but then said rewriting it on his own was just simpler.

While Swagger might not be perfect (some pain points are addressed with OpenAPI v3) it works IMHO pretty well for us (Zalando) and myself doing API first:

* use a decent editor to write the YAML e.g. https://github.com/zalando/intellij-swagger * do not write any boilerplate code and do not generate code (if that's possible in your env), e.g. by using https://github.com/zalando/connexion (Python API-first) * follow best practices and guidelines to have a consistent API experience, e.g. https://zalando.github.io/restful-api-guidelines/

Most importantly Swagger/OpenAPI gives us a "simple" (everything is relative!) language to define APIs and discuss/review them independent of languages as teams use different ones across Zalando Tech.

Easy is subjective, simple is objective. You probably meant easy ;)
So many problems in programming are caused by trying to replace code with configuration. I've learned over time that the DRY principle can be harmful. Avoiding repetition is only good when it remains equally readable and powerful.

Defining a DSL is almost alway a better idea (but more difficult) than defining a configuration format.

What is the difference between a DSL and a configuration format?

I mean the essential difference. ;-)