{"id":1616,"date":"2019-06-25T22:21:54","date_gmt":"2019-06-25T14:21:54","guid":{"rendered":"https:\/\/www.techcoil.com\/blog\/?p=1616"},"modified":"2020-05-12T10:56:42","modified_gmt":"2020-05-12T02:56:42","slug":"how-to-solve-no-api-definition-provided-error-for-flask-restplus-app-on-cloud-foundry","status":"publish","type":"post","link":"https:\/\/www.techcoil.com\/blog\/how-to-solve-no-api-definition-provided-error-for-flask-restplus-app-on-cloud-foundry\/","title":{"rendered":"How to solve &#8220;No API definition provided&#8221; error for Flask-RESTPlus app on Cloud Foundry"},"content":{"rendered":"<p>When you <a href=\"https:\/\/www.techcoil.com\/blog\/how-to-create-an-api-endpoint-that-generates-a-qr-code-image-with-python-3-flask-restplus-and-python-qrcode\/\" rel=\"noopener\" target=\"_blank\">create an API endpoint that generates a QRCode with Flask-RESTPlus<\/a>, you may want to deploy it onto Cloud Foundry. <\/p>\n<p>However, when I first tried to do so, I was greeted with a \"<strong>No API definition provided<\/strong>\" when I accessed the <a href=\"https:\/\/swagger.io\/\" rel=\"noopener\" target=\"_blank\">Swagger<\/a> Api portal page. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/qrcodeapp-showing-No-API-definition-provided.jpg\" alt=\"qrcodeapp showing No API definition provided\" \/><\/p>\n<p>So why is there a \"<strong>No API definition provided<\/strong>\" error for <a href=\"https:\/\/flask-restplus.readthedocs.io\/en\/stable\/\" rel=\"noopener\" target=\"_blank\">Flask-RESTPlus<\/a> app on <a href=\"https:\/\/www.cloudfoundry.org\/\" rel=\"noopener\" target=\"_blank\">Cloud Foundry<\/a>? <\/p>\n<p>In case you are facing such a problem, this post discuss how I had managed to solve the \"<strong>No API definition provided<\/strong>\" error for my Flask-RESTPlus app on Cloud Foundry.<\/p>\n<h2>Having an idea of how the Flask-RESTPlus app was deployed on Cloud Foundry<\/h2>\n<p>Before diving into the solution, it is helpful to know how the Flask-RESTPlus app was deployed onto Cloud Foundry. <\/p>\n<p>In addition to the python file, the QRCode app was pushed to a Cloud Foundry environment with the following manifest file:<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\n---\r\napplications:\r\n- name: QRCodeApp\r\n  memory: 256MB\r\n  disk_quota: 256MB\r\n  random-route: true\r\n  buildpack: python_buildpack\r\n  command: python run_app.py\r\n  instances: 1\r\n<\/pre>\n<p>Given that, Cloud Foundry will make the Flask-RESTPlus app accessible via https:\/\/qrcodeapp.somcfurl.com. <\/p>\n<p>Whenever <a href=\"https:\/\/www.techcoil.com\/glossary\/http-request\/\" rel=\"noopener\" target=\"_blank\">HTTP request<\/a> is made to that endpoint, the <a href=\"https:\/\/www.techcoil.com\/blog\/the-reverse-proxy-server\/\" rel=\"noopener\" target=\"_blank\">reverse proxy server<\/a> will proxy HTTP requests to the web application that was started with the following command:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\npython run_app.py\r\n<\/pre>\n<h2>Finding out why there is a \"<strong>No API definition provided<\/strong>\" error with Chrome Inspector<\/h2>\n<p>Whenever there is a problem with a web page that you are accessing, the <a href=\"https:\/\/developers.google.com\/web\/tools\/chrome-devtools\/\" rel=\"noopener\" target=\"_blank\">Chrome Inspector<\/a> is a tool that can tell you more about the problem.<\/p>\n<p>Given that, I started the Chrome Inspector and found the following error message:<\/p>\n<blockquote><p>\nMixed Content: The page at 'https:\/\/qrcodeapp.somcfurl.com\/api\/' was loaded over HTTPS, but requested an insecure resource 'http:\/\/qrcodeapp.somcfurl.com\/api\/swagger.json'. This request has been blocked; the content must be served over HTTPS.<br \/>\n(anonymous) @ index.js:1\n<\/p><\/blockquote>\n<p>So what does this error message mean?<\/p>\n<p>Since Cloud Foundry had served our portal page over HTTPS, our Chrome browser expects that subsequent requests should be made via HTTPS.<\/p>\n<p>However, our command had started the Flask-RESTPlus app serving HTTP requests over HTTP.<\/p>\n<p>Therefore, there was a call made to retrieve a resource (http:\/\/qrcodeapp.somcfurl.com\/api\/swagger.json) via HTTP in the HTML document that was returned as a <a href=\"https:\/\/www.techcoil.com\/glossary\/http-response\/\" rel=\"noopener\" target=\"_blank\">HTTP response<\/a> to the browser.<\/p>\n<p>Since that call was block, the bootstrapping JavaScript code from Swagger was <strong>unable to replace<\/strong> the \"<strong>No API definition provided<\/strong>\" text with the elements of the API portal.<\/p>\n<h2>Instructing the Flask-RESTPlus Api object to generate urls with the HTTPS scheme instead of HTTP<\/h2>\n<p>Since there is a mismatch of scheme used, we have to configure the <a href=\"https:\/\/flask-restplus.readthedocs.io\/en\/stable\/api.html\" rel=\"noopener\" target=\"_blank\">Flask-RESTPlus Api<\/a> object to generate urls with HTTPS instead of HTTP.<\/p>\n<p>In addition to that, we want to be able to test our Flask-RESTPlus app in our development machine when we access the API portal via HTTP. <\/p>\n<p>Given that, we need a way for our Flask-RESTPlus app to know when to generate urls with HTTPS.<\/p>\n<p>As I had mentioned previously, we can <a href=\"https:\/\/www.techcoil.com\/blog\/getting-the-environment-variables-supplied-to-your-cloud-foundry-application-with-python-3-flask\/\" rel=\"noopener\" target=\"_blank\">get the environment variables supplied to our Cloud Foundry application with Python 3 Flask<\/a>. Given that, we can get a list of environment variables that are supplied to our Flask-RESTPlus app on Cloud Foundry. We can then check the existence of one of the environment variables to determine whether our app is on Cloud Foundry.<\/p>\n<p>For example, the following code checks for the <strong>VCAP_SERVICES<\/strong> environment variable before instructing the Flask-RESTPlus Api object to generate urls with HTTPS instead of HTTP:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom flask import url_for\r\nfrom flask_restplus import Api\r\n\r\nif os.environ.get('VCAP_SERVICES'):\r\n    @property\r\n    def specs_url(self):\r\n        return url_for(self.endpoint('specs'), _external=True, _scheme='https')\r\n\r\n    Api.specs_url = specs_url\r\n<\/pre>\n<p>Putting the above code fragment with our QRCode app, we yield the following code:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom flask import Flask, Blueprint, request, send_file, url_for\r\nfrom flask_restplus import Api, Namespace, Resource, fields\r\nfrom io import BytesIO\r\n \r\nimport os, qrcode\r\n \r\n# Create Flask app\r\napp = Flask(__name__)\r\n \r\n# Associate Api with Blueprint\r\napi_blueprint = Blueprint('API', __name__)\r\n\r\nif os.environ.get('VCAP_SERVICES'):\r\n    @property\r\n    def specs_url(self):\r\n        return url_for(self.endpoint('specs'), _external=True, _scheme='https')\r\n\r\n    Api.specs_url = specs_url\r\n\r\napi = Api(api_blueprint,\r\n    title='Api for QR code app',\r\n    version='1.0',\r\n    description='This is an API for QR code app',\r\n    # All API metadatas\r\n)\r\n \r\n# Create namespace for containing Qr Code related operations\r\nqrcode_namespace = Namespace('QrCode', description='Qr code related operations')\r\n# Specify uri of qrcode namespace as \/qrcode\r\napi.add_namespace(qrcode_namespace, path='\/qrcode')\r\n# Specify uri of api blueprint as \/api\r\napp.register_blueprint(api_blueprint, url_prefix='\/api')\r\n \r\n# Define input model\r\nqrcode_creation_input = qrcode_namespace.model('QRCode creation Input', {\r\n    'value': fields.String(required=True, description='The value that is supposed to be encoded into qrcode'),\r\n})\r\n \r\n \r\n# Define API endpoint for creating Qr Code image\r\n@qrcode_namespace.route('\/')\r\n@qrcode_namespace.doc('Creates a QRCode image based on a string value.')\r\nclass QrCodeRoot(Resource):\r\n \r\n    @qrcode_namespace.expect(qrcode_creation_input)\r\n    @qrcode_namespace.produces(&#x5B;'image\/png'])\r\n    @qrcode_namespace.response(200, description='Return QR Code png image file.')\r\n    @qrcode_namespace.response(400, description='Invalid input provided.')\r\n    def post(self):\r\n \r\n        # Get value to encode into QR Code\r\n        json_input = request.get_json()\r\n        value_to_turn_into_qrcode = json_input&#x5B;'value']\r\n \r\n        # Create qr code image and return it as HTTP response\r\n        pil_img = qrcode.make(value_to_turn_into_qrcode)\r\n        img_io = BytesIO()\r\n        pil_img.save(img_io, 'PNG')\r\n        img_io.seek(0)\r\n        return send_file(img_io, mimetype='image\/png')\r\n \r\n \r\nif __name__ == '__main__':\r\n    port = int(os.getenv(&quot;PORT&quot;, &quot;5678&quot;))\r\n    app.run(host='0.0.0.0', port=port)\r\n<\/pre>\n<p>Once I had deployed the code changes to Cloud Foundry, I am able to access the API portal without the \"<strong>No API definition provided<\/strong>\" error.<\/p>\n\n      <ul id=\"social-sharing-buttons-list\">\n        <li class=\"facebook\">\n          <a href=\"https:\/\/www.facebook.com\/sharer\/sharer.php?u=https%3A%2F%2Fwp.me%2Fp245TQ-q4\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n            <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Facebook.png\" alt=\"Facebook icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"twitter\">\n          <a href=\"https:\/\/twitter.com\/intent\/tweet?text=&url=https%3A%2F%2Fwp.me%2Fp245TQ-q4&via=Techcoil_com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Twitter.png\" alt=\"Twitter icon\"> Tweet\n          <\/a>\n        <\/li>\n        <li class=\"linkedin\">\n          <a href=\"https:\/\/www.linkedin.com\/shareArticle?mini=1&title=&url=https%3A%2F%2Fwp.me%2Fp245TQ-q4&source=https:\/\/www.techcoil.com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/linkedin.png\" alt=\"Linkedin icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"pinterest\">\n          <a href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Fwww.techcoil.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F1616&description=\" class=\"pin-it-button\" target=\"_blank\" role=\"button\" rel=\"nofollow\" count-layout=\"horizontal\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Pinterest.png\" alt=\"Pinterest icon\"> Save\n          <\/a>\n        <\/li>\n      <\/ul>\n    ","protected":false},"excerpt":{"rendered":"<p>When you <a href=\"https:\/\/www.techcoil.com\/blog\/how-to-create-an-api-endpoint-that-generates-a-qr-code-image-with-python-3-flask-restplus-and-python-qrcode\/\" rel=\"noopener\" target=\"_blank\">create an API endpoint that generates a QRCode with Flask-RESTPlus<\/a>, you may want to deploy it onto Cloud Foundry. <\/p>\n<p>However, when I first tried to do so, I was greeted with a <strong>No API definition provided<\/strong> when I accessed the <a href=\"https:\/\/swagger.io\/\" rel=\"noopener\" target=\"_blank\">Swagger<\/a> Api portal page. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/qrcodeapp-showing-No-API-definition-provided.jpg\" alt=\"qrcodeapp showing No API definition provided\" \/><\/p>\n<p>So why is there a &#8220;No API definition provided&#8221; error for <a href=\"https:\/\/flask-restplus.readthedocs.io\/en\/stable\/\" rel=\"noopener\" target=\"_blank\">Flask-RESTPlus<\/a> app on <a href=\"https:\/\/www.cloudfoundry.org\/\" rel=\"noopener\" target=\"_blank\">Cloud Foundry<\/a>? <\/p>\n<p>In case you are facing such a problem, this post discuss how I had managed to solve the &#8220;No API definition provided&#8221; error for my Flask-RESTPlus app on Cloud Foundry.<\/p>\n","protected":false},"author":1,"featured_media":1617,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"footnotes":""},"categories":[375],"tags":[607,584,640,226,233],"jetpack_featured_media_url":"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/qrcodeapp-showing-No-API-definition-provided.jpg","jetpack_shortlink":"https:\/\/wp.me\/p245TQ-q4","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/1616"}],"collection":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/comments?post=1616"}],"version-history":[{"count":0,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/1616\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media\/1617"}],"wp:attachment":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media?parent=1616"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/categories?post=1616"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/tags?post=1616"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}