[feature][python-flask] Add CORS support to python-flask server (#8472)

* Add CORS support to python-flask server generator

* Documentation update and CORS support for other generators using the same base class

* Trivial sample changes
This commit is contained in:
Petr Tůma 2021-01-29 03:54:02 +01:00 committed by GitHub
parent 64f5dc8077
commit 061552f5d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 66 additions and 3 deletions

View File

@ -12,6 +12,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|defaultController|default controller| |default_controller|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|featureCORS|use flask-cors for handling CORS requests| |false|
|legacyDiscriminatorBehavior|Set to true for generators with better support for discriminators. (Python, Java, Go, PowerShell, C#have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|packageName|python package name (convention: snake_case).| |openapi_server|
|packageVersion|python package version.| |1.0.0|

View File

@ -12,6 +12,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|defaultController|default controller| |default_controller|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|featureCORS|use flask-cors for handling CORS requests| |false|
|legacyDiscriminatorBehavior|Set to true for generators with better support for discriminators. (Python, Java, Go, PowerShell, C#have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|packageName|python package name (convention: snake_case).| |openapi_server|
|packageVersion|python package version.| |1.0.0|

View File

@ -12,6 +12,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|defaultController|default controller| |default_controller|
|disallowAdditionalPropertiesIfNotPresent|If false, the 'additionalProperties' implementation (set to true by default) is compliant with the OAS and JSON schema specifications. If true (default), keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.|<dl><dt>**false**</dt><dd>The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.</dd><dt>**true**</dt><dd>Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.</dd></dl>|true|
|ensureUniqueParams|Whether to ensure parameter names are unique in an operation (rename parameters that are not).| |true|
|featureCORS|use flask-cors for handling CORS requests| |false|
|legacyDiscriminatorBehavior|Set to true for generators with better support for discriminators. (Python, Java, Go, PowerShell, C#have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|packageName|python package name (convention: snake_case).| |openapi_server|
|packageVersion|python package version.| |1.0.0|

View File

@ -49,6 +49,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
public static final String CONTROLLER_PACKAGE = "controllerPackage";
public static final String DEFAULT_CONTROLLER = "defaultController";
public static final String SUPPORT_PYTHON2 = "supportPython2";
public static final String FEATURE_CORS = "featureCORS";
// nose is a python testing framework, we use pytest if USE_NOSE is unset
public static final String USE_NOSE = "useNose";
public static final String PYTHON_SRC_ROOT = "pythonSrcRoot";
@ -61,6 +62,7 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
protected String defaultController;
protected Map<Character, String> regexModifiers;
protected boolean fixBodyName;
protected boolean featureCORS = Boolean.FALSE;
protected boolean useNose = Boolean.FALSE;
protected String pythonSrcRoot;
@ -165,6 +167,8 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
defaultValue("false"));
cliOptions.add(new CliOption("serverPort", "TCP port to listen to in app.run").
defaultValue("8080"));
cliOptions.add(CliOption.newBoolean(FEATURE_CORS, "use flask-cors for handling CORS requests").
defaultValue(Boolean.FALSE.toString()));
cliOptions.add(CliOption.newBoolean(USE_NOSE, "use the nose test framework").
defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(PYTHON_SRC_ROOT, "put python sources in this subdirectory of output folder (defaults to \"\" for). Use this for src/ layout.").
@ -213,6 +217,9 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
additionalProperties.put(SUPPORT_PYTHON2, Boolean.TRUE);
typeMapping.put("long", "long");
}
if (additionalProperties.containsKey(FEATURE_CORS)) {
setFeatureCORS((String) additionalProperties.get(FEATURE_CORS));
}
if (additionalProperties.containsKey(USE_NOSE)) {
setUseNose((String) additionalProperties.get(USE_NOSE));
}
@ -236,6 +243,10 @@ public abstract class AbstractPythonConnexionServerCodegen extends DefaultCodege
controllerPackage = packageName + "." + controllerPackage;
}
public void setFeatureCORS(String val) {
this.featureCORS = Boolean.valueOf(val);
}
public void setUseNose(String val) {
this.useNose = Boolean.valueOf(val);
}

View File

@ -1,6 +1,8 @@
import os
import connexion
{{#featureCORS}}
import aiohttp_cors
{{/featureCORS}}
def main():
options = {
@ -12,4 +14,20 @@ def main():
arguments={'title': '{{appName}}'},
pythonic_params=True,
pass_context_arg_name='request')
{{#featureCORS}}
# Enable CORS for all origins.
cors = aiohttp_cors.setup(app.app, defaults={
"*": aiohttp_cors.ResourceOptions(
allow_credentials=True,
expose_headers="*",
allow_headers="*",
)
})
# Register all routers for CORS.
for route in list(app.app.router.routes()):
cors.add(route)
{{/featureCORS}}
app.run(port={{serverPort}})

View File

@ -7,3 +7,6 @@ connexion[aiohttp,swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=
werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4"
swagger-ui-bundle == 0.0.6
aiohttp_jinja2 == 1.2.0
{{#featureCORS}}
aiohttp_cors >= 0.7.0
{{/featureCORS}}

View File

@ -7,3 +7,7 @@ setuptools >= 21.0.0
bp2hookutil==3.3.0
plansdk
twigjack
{{#featureCORS}}
# should support both Python 2 and Python 3
flask-cors >= 3.0.10
{{/featureCORS}}

View File

@ -6,6 +6,9 @@
{{/supportPython2}}
import connexion
{{#featureCORS}}
from flask_cors import CORS
{{/featureCORS}}
from {{packageName}} import encoder
@ -14,6 +17,12 @@ def main():
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('swagger.yaml', arguments={'title': '{{appName}}'})
{{#featureCORS}}
# add CORS support
CORS(app.app)
{{/featureCORS}}
app.run(port={{serverPort}})

View File

@ -6,6 +6,9 @@
{{/supportPython2}}
import connexion
{{#featureCORS}}
from flask_cors import CORS
{{/featureCORS}}
from {{packageName}} import encoder
@ -16,6 +19,12 @@ def main():
app.add_api('openapi.yaml',
arguments={'title': '{{appName}}'},
pythonic_params=True)
{{#featureCORS}}
# add CORS support
CORS(app.app)
{{/featureCORS}}
app.run(port={{serverPort}})

View File

@ -10,6 +10,10 @@ connexion[swagger-ui] == 2.4.0; python_version<="2.7"
werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4"
swagger-ui-bundle >= 0.0.2
python_dateutil >= 2.6.0
{{#featureCORS}}
# should support both Python 2 and Python 3
flask-cors >= 3.0.10
{{/featureCORS}}
{{#supportPython2}}
typing >= 3.5.2.2
# For specs with timestamps, pyyaml 5.3 broke connexion's spec parsing in python 2.

View File

@ -1,7 +1,6 @@
import os
import connexion
def main():
options = {
"swagger_ui": True
@ -12,4 +11,5 @@ def main():
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True,
pass_context_arg_name='request')
app.run(port=8080)

View File

@ -1,7 +1,6 @@
import os
import connexion
def main():
options = {
"swagger_ui": True
@ -12,4 +11,5 @@ def main():
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True,
pass_context_arg_name='request')
app.run(port=8080)

View File

@ -9,6 +9,7 @@ def main():
app = connexion.App(__name__, specification_dir='./swagger/')
app.app.json_encoder = encoder.JSONEncoder
app.add_api('swagger.yaml', arguments={'title': 'OpenAPI Petstore'})
app.run(port=8080)

View File

@ -11,6 +11,7 @@ def main():
app.add_api('openapi.yaml',
arguments={'title': 'OpenAPI Petstore'},
pythonic_params=True)
app.run(port=8080)