dpgaspar/Flask-AppBuilder

get 404 response when using example api code

taoli-ax opened this issue · 3 comments

If you'd like to report a bug in Flask-Appbuilder, fill out the template below. Provide
any extra information that may be useful

Responsible disclosure:
We want to keep Flask-AppBuilder safe for everyone. If you've discovered a security vulnerability
please report to danielvazgaspar@gmail.com.

Environment

windows 64bit
Python 3.10.11
virtual env

Flask-Appbuilder version:
Flask-AppBuilder==4.3.9
pip freeze output:
apispec==6.3.0 attrs==23.1.0 Babel==2.13.1 blinker==1.7.0 click==8.1.7 colorama==0.4.6 defusedxml==0.7.1 Deprecated==1.2.14 dnspython==2.4.2 email-validator==1.3.1 Flask==2.3.3 Flask-AppBuilder==4.3.9 Flask-Babel==2.0.0 Flask-JWT-Extended==4.5.3 Flask-Limiter==3.5.0 Flask-Login==0.6.3 Flask-OpenID==1.3.0 Flask-SQLAlchemy==2.5.1 Flask-WTF==1.2.1 greenlet==3.0.1 idna==3.4 importlib-resources==6.1.0 itsdangerous==2.1.2 Jinja2==3.1.2 jsonschema==4.19.2 jsonschema-specifications==2023.7.1 limits==3.6.0 markdown-it-py==3.0.0 MarkupSafe==2.1.3 marshmallow==3.20.1 marshmallow-sqlalchemy==0.26.1 mdurl==0.1.2 ordered-set==4.1.0 packaging==23.2 prison==0.2.1 Pygments==2.16.1 PyJWT==2.8.0 python-dateutil==2.8.2 python3-openid==3.2.0 pytz==2023.3.post1 PyYAML==6.0.1 referencing==0.30.2 rich==13.6.0 rpds-py==0.10.6 six==1.16.0 SQLAlchemy==1.4.50 SQLAlchemy-Utils==0.41.1 typing_extensions==4.8.0 Werkzeug==3.0.1 wrapt==1.15.0 WTForms==3.1.1

Describe the expected results

{ "message": "Hello" }
Tell us what should happen.
Should response with correct status code 200

#app/api.py
from flask_appbuilder.api import BaseApi, expose
from . import appbuilder


class ExampleApi(BaseApi):
    @expose('/greeting')
    def greeting(self):
        return self.response(200, message="Hello")


appbuilder.add_api(ExampleApi)

#app/init.py
import logging

from flask import Flask
from flask_appbuilder import AppBuilder, SQLA

"""
 Logging configuration
"""

logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logging.getLogger().setLevel(logging.DEBUG)

app = Flask(__name__)
app.config.from_object("config")
db = SQLA(app)
appbuilder = AppBuilder(app, db.session)


"""
from sqlalchemy.engine import Engine
from sqlalchemy import event

#Only include this for SQLLite constraints
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    # Will force sqllite contraint foreign keys
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()
"""

from . import views

Describe the actual results

web browser show: page not found
stauts code :404
Tell us what happens instead.

Paste the full traceback if there was an exception.

Steps to reproduce

1.Follow the docs installation and create app: https://flask-appbuilder.readthedocs.io/en/latest/installation.html
2. build a new app/api.py , and add example code: https://flask-appbuilder.readthedocs.io/en/latest/rest_api.html
3. test url in broswer : http://localhost:8080/api/v1/exampleapi/greeting
4. get 404 response

Are you accessing: http://localhost:5000/api/v1/exampleapi/greeting ?

Your server logs should show something like:

2023-11-03 10:10:45,376:INFO:flask_appbuilder.base:Registering class ExampleApi on menu
2023-11-03 10:10:45,376:INFO:flask_appbuilder.api:Registering route /api/v1/exampleapi/greeting ('GET',)

Are you accessing: http://localhost:5000/api/v1/exampleapi/greeting ?

Your server logs should show something like:

2023-11-03 10:10:45,376:INFO:flask_appbuilder.base:Registering class ExampleApi on menu
2023-11-03 10:10:45,376:INFO:flask_appbuilder.api:Registering route /api/v1/exampleapi/greeting ('GET',)

I just found the root cause, I didnt import api inapp/__init__.py
now it works

# app/__init__.py
import logging

from flask import Flask
from flask_appbuilder import AppBuilder, SQLA

"""
 Logging configuration
"""

logging.basicConfig(format="%(asctime)s:%(levelname)s:%(name)s:%(message)s")
logging.getLogger().setLevel(logging.DEBUG)

app = Flask(__name__)
app.config.from_object("config")
db = SQLA(app)
appbuilder = AppBuilder(app, db.session)

"""
from sqlalchemy.engine import Engine
from sqlalchemy import event

#Only include this for SQLLite constraints
@event.listens_for(Engine, "connect")
def set_sqlite_pragma(dbapi_connection, connection_record):
    # Will force sqllite contraint foreign keys
    cursor = dbapi_connection.cursor()
    cursor.execute("PRAGMA foreign_keys=ON")
    cursor.close()
"""
TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6dHJ1ZSwiaWF0IjoxNjk5MDA0NzUzLCJqdGkiOiI1NjYxZWNjOC1hZWUzLTQwZDEtOWI3My0xZDVjNDBhYmMzMGYiLCJ0eXBlIjoiYWNjZXNzIiwic3ViIjoxLCJuYmYiOjE2OTkwMDQ3NTMsImV4cCI6MTY5OTAwNTY1M30.4GFrF8oAA0gJPiVh8I7LDwiEah6fZ3GP9LTVdjbLlB0'
from . import views
from . import api

Thanks for reply!

cool