Don't be fooled kids, this may sound great but it is in fact the gate to hell. Back when I was young the same thing was called SOAP and it also promised standardized APIs in a vendor neutral description format and code generation. It was pure misery. I still have nightmares about it. They may say they only bring the good parts of SOAP, but there are no good parts in SOAP.
I used a service once, just recently, whose API was SOAP (I think it was the one for VoIP.ms?)
Instead of documenting their API, they gave me a WSDL file to download and told me to plug it into any WSDL-supporting SOAP client.
So I threw it into http://fagiani.github.io/savon/ in a Pry session, got back an object representing the API gateway, and then just... started exploring the API using it and Pry, treating the objects and their properties the way I would those of a regular Ruby library.
It was honestly a nice experience, and it would have been even nicer if I had to deal with more than one API, because I could have just kept dealing with Savon rather than finding a new (maybe not-very-well-written) client library for each new service.
So, I don't get the hate for SOAP/WSDL. Is it the process of building the SOAP service that's frustrating? The process of creating the WSDL document? I didn't have to deal with either of these, so maybe that's where the hatred boils up from.
Was it integrating code-generation into the build process? Again, since I was using a dynamic language (Ruby) whose SOAP library (Savon) parsed WSDL and built up its client-proxies in memory at runtime, I didn't have to deal with this.
Or was it dealing with brittleness and edge-cases and a lack of fidelity in the types you could pass through such APIs? I didn't have a problem with this personally, but I might have just been dealing with a uniquely-well-architected backend service.
I think it was the crappy auto-generated wrappers from back then that was the downfall. Both in c# and Java, there was too much magic, where they tried to hide too much and make it look like regular local function calls. People associated soap with the magic and when rest came along everyone jumped ship. But the problem was never with soap itself.
This swagger stuff is actually a step backwards, as rest was never meant to be used for api specifications anyway. Or at least the primary focus of it seemed to be hypermedia and evolutionary interfaces.
Neither swagger nor soap are really what I'd expect after 20 years of trying to come up with something though. Would have expected something far more powerful that has more of a functional style, allowing for various combinators and such to be generated.
> I think it was the crappy auto-generated wrappers from back then that was the downfall. Both in c# and Java, there was too much magic, where they tried to hide too much and make it look like regular local function calls.
I'd expand this a bit further too: they tried to make them look like regular function calls in an age where asynchronous/callback programming in general was a nightmare.
At least in C# today, a lot of the debug pain I recall helping other developers through with the old SOAP/WSDL WCF auto-gen code would be solved with async/await. Practically no one understood the Begin{FunctionName}Async/End{FunctionName}Async pattern that the best of those wrappers used at the time and so many developers settled for synchronous blocking and deadlocking anti-patterns instead.
Which again leads to the more general problem with such things that: when they worked right they were magic, and when they didn't work they were (practically) impossible to debug.
There is something to be said that, too, that no one wanted to write a WSDL definition file or a SOAP wrapper by hand, so you were always fighting your tooling to produce what you needed and had a hard time correcting it when it did something sub-optimal.
I don't think swagger is a terribly huge step backwards as in general what I've seen of swagger is lot more descriptive than prescriptive. I've seen some swagger-described APIs that are heavily hypermedia and take a strong REST approach, and I've seen some swagger-described APIs that might as well be SOAP for as much as they resemble "proper" REST and/or hypermedia. It certainly feels more pragmatic than SOAP/WSDL, in trying to describe a lot of the variety in how people build REST-ish APIs, and maybe in that way it's a step forwards from a once-sized-fits-all prescriptive approach. (In that way it too is a step backwards in that sometimes a good prescriptive approach might lead people more easily down a "happy path" of best practices, but that's always the hard balance: pragmatism versus theoretical purity. The pendulum swings.)
This. To expand on it a little more, if you ran into a poorly define wsdl, you'd get horrible looking objects back. Some even generate ambiguous "data" objects that essentially contain an xml string you'd have to parse yourself.
CORBA's IDL was great; we're using a home grown variant for C++/C#/Java/JS interop, and it's much, much better than SWIG.
Maybe the problem with a lot of RPC tools is that they conflate serialization format and remote call semantics (or "complect" these two factors, if I were inclined to mimic the pretentiousness of Rich Hickey).
I look at SOAP failures from a different perspective of ground truths rather than the ecosystem's potential.
In my experiences with SOAP and WSDLs, the code-generated java2wsdl and such wrappers were a way for many vendors to claim "we have an API to support your SOA!" when all they were doing was dynamically generating a WSDL file from a database schema (a lot of service desk and CMDB software like BMC Remedy and Atrium, HP Service Desk, etc. do this) and for a lot of enterprise applications that were basically made to sell a cash cow stack like an ITIL stack with CMDB. So your WSDLs constantly changed because every time someone changed a table's schema you'd need to generate and distribute the WSDL to everyone - this is a guaranteed workflow in an enterprise software situation with dozens of partners comparable to what happens when you get a call from your doctor that you have an STD. This pattern should also sound really familiar to the folks from the mid-90s - it's exactly the hell that began with CORBA objects and other systems that inevitably required everyone to recompile and redeploy their services whenever there was any schema change whatsoever, and unless you had a super-duper effective object AND service registry with accompanying object repositories all provided by some expensive vendor, your class definitions would routinely get desynced and you'd be forced to update your WARs and EARs if you didn't have more expensive hot-loading JVM plus correctly working lifecycle management that wouldn't leak memory (almost none did because of how difficult it was to write decent classloaders that would correctly use ephemeral and weak references for high-concurrency DBs). Thank goodness we had other options with message passing architectures in enterprise (Protocol Buffers, Thrift, etc. all got around the tyranny of class serialization that the distributed object enterprise architect Mafia wanted) but messaging has its own problems from a deployment perspective that made SOAP-based endpoints more attractive then.
This kind of centralized, byzantine, top-down design was the Holy Grail of enterprise application architecture that has ultimately failed in basically every single implementation I've seen or heard of except for the most trivial implementation cases or that required extremely authoritarian, didactic approaches resembling the Crusades or Gallic Wars rather than (now more common) collectivist collaboration toward software development. Either way, innovation slowed to a crawl as internal compliance and standardization become the only output of the software organization or nobody wanted to even try to evolve the system much over time. Open Source is not immune to this kind of bikeshedding culture.
The easier decoupling of services and ability for services to move at their own pace while freeing themselves from the data schema ERD-UML-death-squad-by-committee is what moving from the SOAP ecosystem bought us. The Enterprise Software Apocalypse's Four Horsemen surely included at least the names UDDI, ESB, and SOAP. While I sometimes miss a WSDL to make getting started with an API easier there is no way I miss the typical SOAP service that typically wrapped legacy command line applications older than myself and misrepresented them as something actually scalable or added 25 layers of class hierarchy to express a custom integer or string type for no apparent reason besides a Antediluvian form of input validation that combines the pedantry of Haskell typing with none of the power and elegance. These are not features that deliver business value to anyone besides enterprise software vendors and independent consultants seeking to overcomplicate every software system beyond the comprehension of its own engineers.
TL;DR - I'm afraid that we're starting to regress back to what the J2EE ecosystem tried and failed to do even within monolithic companies because many people never had to design and (more importantly) operate and maintain these centralized, specification-first APIs that have historically hurt innovation and collaboration, not helped.
I remember playing with the SOAP API of gforge advanced (PHP), and it was not a pleasant experience.
What specially bothered me was how this API tended to return internal IDs instead of resolving them server side and directly give high level and useful information. And there was other issues like returning html escaped text instead of the raw text directly.
It really gave me the impression of an API exposing the raw sql tables.
In the end, I managed to do what I wanted (export the tickets to automatically generate a changelog), but it took me quite a lot of time and a disproportionate amount of code (vs an API like the github one).
AFAIK one of the sources of hatred for SOAP is people building the message bodies by hand using browser JS instead of using a code generator (one might not have existed for browser JS at that time). Not only was it complicated by being XML, but SOAP bodies are especially verbose XML.
It's usually extra hostile for things like caching. I've (on multiple occasions) seen one URI endpoint, http posts and method as a separate header. Pretty much as far away from a sane caching best practice as you can go. Also; a lot of these older web services doesn't support deflate, gzip (accept-encoding, vary, ..) so your average responses are 500kb and up. :'(
In a recent project, a client saturated their wire as a result of just this.
My main frustration with soap services is that when it works it's great, but when something is wrong and you don't control the server side it's really frustrating to figure out what's wrong. Too often wsdl descriptions for 3rd party apis are desperately out of date, and debugging api call by looking at xml with auto-generated type definitions is hell. SOAP is just not human-friendly enough, it's too complex. In the end the most popular formats always end up being the ones that are easiest for humans to process & debug: plain text commands in telnet/pop3/smpt, html, json, restful calls, etc.
I think it's quite "fun" to keep track of different versions in SOAP, though there's probably a WS-VERSIONING spec plugin that describes a way to do it. That was certainly the source of cursing that I picked up from sitting adjacent to colleagues who maintained a SOAP API.
Also having integrated against a couple SOAP APIs, it's a bit annoying to write API client tests using recording / mocking of HTTP requests -- since the first thing your client has to do is actually grab the WSDL, your recordings are bloated. (I use VCRpy a lot for this use-case, and it's very convenient for REST APIs.)
Not sure where the best practices are on bundling a copy of the WSDL with your binary; not sure if your app can survive the WSDL spec changing under your feet, but at the same time, if the API changes its spec using a cached version of the WSDL won't work either.
The Swagger/OpenAPI spec format is its own special little hell. Just enough "user friendly" features to make it difficult to parse, yet still complicated enough that it's a pain to write.
I thought I was the only one! As far as I can tell the sentiment regarding Swagger/OpenAPI is generally positive, but I am starting to think that's just because it's an improvement over the status quo of "nothing" for most people.
I personally prefer API Blueprint, but even there is room for improvement.
I prefer RAML tbh - using Markdown as the basis of an API specification language is a pretty terrible idea. RAML's syntax is much more structured and pleasant, and the type syntax is far nicer to write than JSON Schema. Alas it seems to have lost the battle of network effects...
I would assume most people would use an extension to generate swagger off their endpoints on demand. Thats what I do in ASP.NET, via a library called Swashbuckle: Swagger and Swagger UI in three lines of code.
What does the complexity matter? Either way you're running some service description file through some build tooling to generate some human unfriendly code. Who cares how big or complex the code in the middle is?
Because in most cases that I have experienced, no, you are not running the sdl through a generator to create a client. You are instead instantiating a http client, setting the right headers, urls, package bodies etc, all by hand. Something which is done in lieu of using a code generator because its trivial with an HTTP web service.
Furthermore, with an http api and depending on your security model, you can test/inspect a good portion of your APIs directly with a browser - a zero-cost client for all http apis that you get for free.
I have never felt the need to write swagger by hand, despite publishing a few API's in it. I always generate them directly from the domain code/function arguments.
It might be a benefit of statically typed languages though. I have no idea how you would automatically generate swagger from Javascript, without adding so much annotations that they become a poor man's types.
1. Having strong and documented boundaries at API level
2. Being able to generate clients from a server spec, so I don't have to write interop code anymore.
3. Being able to generate server client from a design document (the spec) - I did it just last week, and it works magically. Should I do it by hand?
Swagger is bad only if you use it wrong, like it's the case with SOAP, Java, and other things which have good parts but have been misused so many times people got pissed of them.
SOAP is a nightmare, but my experience with Swagger has not been so far. I used flask and marshmallow to create an API and a plug-in to generate the swagger scheme from it. It just worked.
I see it more as an interactive documentation generator than some kind of dynamic API pipe dream.
I was recently tasked with tightening up and documenting an HTTP API I didn't write. The original authors used Django and Django REST Framework[1], but lacking deep experience with either, mostly rolled their own functions for requests, responses, and communications with the back-end databases and other external data sources.
Rather than attempting to sort it out, I used Paw[2] to get my arms around the API from a consumer's POV, had Paw generate a skeleton of an OpenAPI 2.0 (Swagger 2.0)[3] description, converted it to YAML[4] and began putting flesh on the bones manually (yaml-mode[5] in Emacs is pretty decent). In the process of covering all the bases with precise req/res definitions and examples (yay, JSON Schema![6]), I uncovered a lot of corner cases in the API's functionality and made sure they were handled properly or at least documented well.
I co-located the openapi.yaml file and ReDoc[7] with the API, and now it has beautiful web-based documentation. It also has JS, Python and curl code samples for all endpoints, generated with Paw and included in the YAML formatted description. ReDoc displays them nicely, with syntax highlighting.
In short, even though I worked "backwards" — matching the OpenAPI description to the functionality — it was a fruitful exercise and the results seem pretty good. Not to mention, all the above is readily tracked with git and can live right next to the server's source code... compared to, say, an equivalent documentation effort accomplished with MS Word.
Unless I misunderstood your approach I think working from what a consumer would like > what the server produces is forwards not backwards when it comes to API design
In this case "what the server produces" was already defined and I was not given a mandate to change it prior to v1.0. Also, the server implementation was a bit messy and mostly undocumented.
So I worked "backwards" in the sense that I put myself in the perspective of a consumer of the information it serves and then documented the server's behavior with OpenAPI. Certainly, in the process I made much reference to the Python code used to implement the server's endpoints, but some of the endpoints' quirks were discovered in the process of precisely describing (with OpenAPI) their inputs and outputs.
Swagger Editor[1] can spit out the skeleton of a Flask based server from an OpenAPI 2.0 specification. The generated code makes use of the Connexion famework[2].
Paste your specification into the editor, fix it if it's not valid, open the "Generate Server" dropdown in the top menu, and select "python-flask".
Don't have a blog post for you, but I'm pretty sure he's utilitizing Flask-APISpec (https://github.com/jmcarp/flask-apispec). I've been eying it for a while.
But in all seriousness, while I dont believe much in code generation and super smart generic client, a common platform for describing rest apis is more useful than reinventing the wheel for every new service or rather worse - a Word document on Sharepoint with endpoint description.
You define a few data types to communicate about, and call procedures remotely with them. I mean it’s right there in the name!
Unfortunately it doesn’t come with a Methodology you can cram your business or research problem into. It just wants to talk about your problem. Way too on-the-nose for many tastes.
It needs a religion attached, then masses will follow.
We wrote an OpenAPI spec for our existing API and just use it to generate documentation for external parties and it's worlds ahead of what we used to do.
SOAP and swagger are entirely different things. I'm sorry you had a bad experience, but it seems like you're making a strong negative claim with only anecdotal evidence. I am curious if there are concrete examples though.
Hi! Can you detail some of the problems you have with SOAP? I'm superficially familiar with Swagger, but probably below the level of dilettante when it comes knowing about SOAs in general.
SOAP has a lot of really awful implementations in it, and there's much less standardization and a lot more "spaghetti meeting wall" APIs in SOAP than I've seen using standard REST APIs.
I try swaggerbuckle nuget c#. It was easy to consume from ios swift. Then i try on android. Not easy. Then try again on react native js, also not easy. My suggestion is try one or two simple API.
I'm going to answer this despite not being the parent. I've looked into this problem area 2 years apart now. The first time I came across swagger 2 and some Ruby toolings to automatically turn source code annotations (not comments) into my api docs.
I was hoping to not do this 2 years later so really looked hard into it. I was dismayed to find that all of the good looking out of the box tools required writing docs by hand, no generation! I looked back into swagger 2 and found great success this time around. A few things were important:
1. Building the API how I wanted which involved integrating docs into the actual functionality. For instance, all params and response attributes are defined in the code and then turned into documentation later.
2. Spending time to get the docs how we wanted them, not just going with the stock.
3. Not being afraid to break the spec with custom json descriptions when necessary. Not pretty but entirely functional.
We do not use swagger for auto generation or testing, only documentation. I do not think that the current swagger UI implementation is attractive and think they're missing hard by not spending more time on the design style that is trending now. The spec itself is solid.
I'm very confused, the article bills this as news, but this has been true for at least a year, is the news that v3 is now 'current' rather than in development?
I always found Swagger to not be very readable or usable. APIs keep changing, and are meant to be malleable, not rigid. IMO, Swagger always ends up being too much planning, too little implementation.
The one Swagger docs site my team used, we all thought it was completely broken for the first several weeks of trying to access it.
Turns out there was a small red ("error" colored...) header bar near the top, collapsed by default. You need to click that to expand out all the API docs. Fun design.
Which editor do you use to edit Swagger? Writing Swagger specification by hand is a nightmare because of the poor online editor. The error messages are hard to understand.
Also Swagger.io people decided to replace the old editor with the new editor and it doesn't have many useful features the old has. Thankfully they kept the old one live.
Is there any standard as to how to do some of these thing - API versioning? actions like login/logout? doing a GET on multiple IDs? spinal casing? common response object format? application specific error codes?
It works nicely with the django-rest-framework (both created by the same person) and has clients for python, javascript, and a command line tool to interact with the API. I have written a small python script that takes our CoreAPI specification and then generates markdown documentation around it.
The catch is that it is not as well documented as Swagger so working with it would require digging into its source code.
API Builder [https://www.apibuilder.io] integrates many of the end to end tools teams need to manage APIs at scale. JSON remains first class and support for swagger is native (also supports avro idl… protobufs to come).
API Builder was started in 2014 as a free and open source project to build a community around best practices we learned scaling gilt.com and building flow.io.
Managing great APIs end to end at scale and over time take a huge investment in culture and tooling. API Builder solves a number of those problems.
A few reasons why teams adopt API Builder.
- Very, very high quality generated clients: Teams that use API Builder end up relying 100% on the generated clients - ie. the developers STOP writing and managing their own client SDKs, freeing up time to focus on product improvements.
- Resource centric: API Builder is resource first - instead of defining an operation explicitly, you define resources and then expose operations on that resource.
- Simple service specification: API Builder at its core separates the notion of the input format (e.g. api.json, swagger, avro) from the service description (service.json). This is a huge advantage: regardless of input format, the service specification can be fully expanded and complete.
- Simple input format: The default api.json format is simple for humans to write. It is JSON, but more than that it is approachable by a novice and designed to be both simple and easy.
- Easy to add code generators: Code generators in API Builder are themselves REST services which accept a service description (in JSON) and essentially return a string. Teams often write their own code generators - even small disposable ones - to systematically solve problems in an automated fashion.
- Testability of clients: With generated mock clients built from the same interface definition, teams can rely on mocks when building automated tests - and further use the provided mock clients to override only the specific features needed for a given test.
- Workflow that works with micro or mono repos and allows for concurrent, branched development of spec, service and client
So far as documentation goes, OpenAPI does include fields for human consumption - such as "example". I've been using Swaggerhub to validate my OpenAPI documents and it clearly demonstrates what the automatically-generated documentation might look like.
It won't help you at all with unit testing (you shouldn't be using HTTP for that). You can theoretically use it to generate a client library in your language of choice for integration tests (true for Swagger, not yet for OpenAPI). Finally, there are tools built around it that let you play around with APIs that have these specs - Microsoft PowerBI comes to mind.
There are ways you could use it to build an API, but I wouldn't consider them a good idea. Edit: You could completely automate the process of ensuring that your semantic versions are compliant (i.e. you aren't breaking compatibility when you are claiming that you are not).
I'd be curious about implementation support as well. I was able to get it to work with earlier versions, but IIRC it involved using the apiKey in header auth type and manually adding "Bearer" to the auth header.
Still the best option is the unix philosophy: "Write programs to handle text streams, because that is a universal interface." - Peter H. Salus in A Quarter-Century of Unix (1994)
It really isn't the universal interface. At some point, most of us need to transfer more than just "text", even if we end up representing the data as text. For example, if I need to describe the name, breed, and sex of a set of dogs, I can transfer that as JSON:
etc. The list goes on. The concept of "text" fails to capture both the higher-lever format (JSON, CSV) and the lower-level details (what the keys are in JSON, what values might be valid for enumerations such as "sex", etc.; what units for numeric types, how do we represent null (esp in CSV), etc.).
For JSON HTTP APIs, Swagger makes a not-that-bad (IMO) attempt at describing the format of the structure.
The Unix philosophy, while it works well in specific cases, does not lend itself well to the creation of robot solutions. Parsing text streams with tools like sed/grep which are not the right tool for the job, in that they cannot understand the corner-cases of JSON/CSV/etc., leads to brittle solutions. (e.g., a use of sed/awk on the above CSV might work, until we get a more complicated format in a later iteration with a field containing an embedded newline, and our awk script falls down b/c we're not using a real CSV parser.)
That quote is actually by Doug McIlroy, who also gave this longer phrasing of it: "Expect the output of every program to become the input to another, as yet unknown, program. Don't clutter output with extraneous information. Avoid stringently columnar or binary input formats. Don't insist on interactive input."