cleanest way to glue generated Flask app code (Swagger-Codegen) to backend implementation
The following approach worked for me:
created three directories:
src
- for my code,src-gen
for the swagger generated code,codegen
in which I have put a script that generate the server along with a few tricks.
I copied all the templates (available in the swagger build) to
codegen/templates
and edited thecontroller.mustache
to refer tosrc/server_impl
, so it can use my own code. The editing uses the template language so it is generic. Still it is not perfect (I would change a few naming conventions) but it does the job. So, first add tocontroller.mustache
:
from {{packageName}}.server_impl.controllers_impl import {{classname}}_impl
then add instead of return 'do some magic!'
the following:
return {{classname}}_impl.{{operationId}}({{#allParams}}{{paramName}}{{^required}}=None{{/required}}{{#hasMore}}, {{/hasMore}}{{/allParams}})
- Script:
- The
src
has aserver_impl
directory. - It creates a symobolic link so that
server_impl
can be imported as a python module
- The
cd ../src-gen/swagger_server/ln -s ../../src/server_impl/cd ../../codegenjava -jar swagger-codegen-cli.jar generate \-i /path_to_your_swagger definition.yaml \-l python-flask \-o ../src-gen \-t ./templatescd ../src-gen/python3 -m swagger_server
I was tempted to use swagger-codegen
before and ran into the same conundrum. Everything is fine until you update the spec. Although you can use custom templates, this just seemed like a lot of overhead and maintenance, when all I want is a design first API.
I ended up using connexion instead, which uses the swagger specification to automatically handle routing, marshaling, validation, etc. Connexion is built on flask, so you would not need to worry about switching frameworks or anything, you will just get the benefit of portions of your application being automatically handled from swagger instead of having to maintain auto-generated code.
For now I am working around this by doing the build in these steps
- run the codegen
- sed-script the generated code to fix trivial stuff like namespaces
- hand-edit the files, so that instead of returning
'do some magic'
(thats the string all the generated controller endpoints return) they simply call a corresponding function in my 'backend' - use
git format-patch
to make a patch of the preceeding changes, so that when i re-generated code the build can automatically apply the changes.
Thus, i can add new endpoints and I only have to hand-code the calls to my backend ~once. Instead of using patch files, i could do this directly by writing a py-parsing grammar for the generated code and using the parsed generated code to create the calls to my backend ... that would take longer so I did this all as a quick hack.
This is far from optimal, i'm not going to mark this as accepted as I'm hoping someone will offer a real solution.