I'm new to python and Flask, and I have a project from the production ENV which I'm trying to run on my local.
I was able to install all the packages and bring them up on http://127.0.0.1:5000, but the problem is that is the only page that actually works on my local. and when I try to do Authorization or even simple post, it does not do anything on my local ( I put some print on the other files and none of them get fire) so I assume they keep going to production as it does have some APIs as well.
Here is the main page (application.py) which is working on my local.
import os
import jwt
import logging
from datetime import datetime, timedelta
from http import HTTPStatus
from pydantic import BaseModel
from passlib.context import CryptContext
from flask import Flask, request, jsonify
from flask_restplus import Api, Resource, fields
from werkzeug.middleware.proxy_fix import ProxyFix
from applicationinsights.flask.ext import AppInsights
app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
api = Api(app, doc='/')
ns = api.namespace(name='Room Parsing', path='/')
swaggerTokenParser = api.parser()
swaggerTokenParser.add_argument('username', location='form')
swaggerTokenParser.add_argument('password', location='form')
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
rtp = RoomTitleParser(room_prototype_XX_path)
ALGORITHM = "HS256"
app.config["SECRET_KEY"] = os.getenv('SECRET_KEY')
app.config["APPINSIGHTS_INSTRUMENTATIONKEY"] = os.getenv('APPINSIGHTS_INSTRUMENTATIONKEY')
appinsights = AppInsights(app)
app.logger.setLevel(level=logging.INFO)
logger = app.logger
#ns.route("/api/room/parser")
class RoomParser(Resource):
#api.expect(swaggerRoom)
#api.doc(description='Process a JSON object with a room description and a unique identifier in order to run it through the parser. This will result in a list of keywords which will be extracted from the description. The result will be returned in a JSON format')
def post(self):
try:
room_desc = "deluxe suite queen ocean view"
room_id = "ID123"
print('11111111111')
if not room_desc or not room_id:
return make_json_error_message("Please send a a room with description and id",HTTPStatus.BAD_REQUEST)
room_dict = dict(Room(description=room_desc, id=room_id))
print(parsed)
parsed = rtp.parse_title(room_dict)
print(parsed)
return jsonify(parsed['room'])
except Exception as e:
logger.error("Error parsing a room: " + repr(e))
return make_json_error_message("We have encountered an error. Please try again later",HTTPStatus.BAD_REQUEST)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
As you can see I have some print statements and all of them are working on my local consol. But when I track down the code for Example this line,
parsed = rtp.parse_title(room_dict)
and put some print command inside the parse_title() function which is located in another file, I do NOT see any output in the console as well as webpage!
Why? I have no idea!!! LOL and that is why I'm here.
I believe it might be related to the #ns.route("/api/room/parser") that I have on top of the class, but not sure.
Can you guys please drop some knowledge here so I can learn and get this code to work on my local completely?
Thanks for your help!
With what you've provided, there doesn't appear to be any reference to the production environment.
The only thing that sticks out to me is
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
The Werkzeug Documentation states that this middleware can set REMOTE_ADDR, HTTP_HOST from X-Forwarded headers. You might try removing that for a bit and see if that helps. There might be some reference to production in that proxy. I don't know enough about that middleware to know for sure however.
It might be helpful to know of any other configuration information or environment you have setup.
It tuned out to be related to my conda env,
So I uninstalled the Anaconda and then installed the plain python and installed pyCharm as well and setup a new env in pycharm. Then it worked like a charm!
Thanks
Related
I'm working on updating an existing university department internal website to run using Flask. Before we completely release the project where it will use shibboleth to manage authentication, I've been trying to setup authentication for testing using htpassword using this tutorial. I'm able to get authentication using htpasswords working for a single file, but I can't figure out how to add the authentication to separate files. Currently, the project looks like this:
This is my main file called app.py:
#app.py
from flask import Flask
from flask_htpasswd import HtPasswdAuth
app = Flask(__name__)
app.config['FLASK_HTPASSWD_PATH'] = '.htpasswd'
app.config['FLASK_SECRET'] = "Super secret key that I will change later"
htpasswd = HtPasswdAuth(app)
import exampleRoute
#app.route('/')
#htpasswd.required
def home(user):
return "This is the homepage"
This is an example of one of my route files called exampleRoute.py:
# exampleRoute.py
from app import app
from flask import Flask
#app.route('/exampleRoute')
def exampleRoute():
return "This is an example route in another file"
When I place the #htpassword.required decorator in front of exampleRoute(), I get an error saying that htpassword is not defined (which makes sense). I've tried to import the app configuration a few different ways and at best, I end up with a circular dependency. I know that I could place the authentication code in a separate file and then import that into all my endpoints, but I didn't think this was possible since this method is incorporated into the app configuration.
I ended up getting an answer from the reddit user alexisprince. The solution was to use Blueprints that import htpasswd from another file (called extensions.py).
I am running Pyramid as my API server. Recently we started getting query string parameters out of order when handed to the RESTful API server. For example, a GET to /v1/finishedGoodRequests?exact=true&id=39&join=OR&exact=false&name=39
is logged by the RESTful api module upon init as request.url:
v1/finishedGoodRequests?join=OR&name=39&exact=true&exact=false&id=39
with request.query_string: join=OR&name=39&exact=true&exact=false&id=39
I process the query params in order to qualify the search, in this case id exactly 39 or 39 anywhere in the name. What kind of possible server setting or bug could have crept in to the server code to cause such a thing? It is still a MultiDict...
As a simple example, this works fine for me, and the MultiDict has always preserved the order and so I suspect something is getting rewritten by something you're using in your stack.
from pyramid.config import Configurator
from pyramid.view import view_config
from waitress import serve
#view_config(renderer='json')
def view(request):
return list(request.GET.items())
config = Configurator()
config.scan(__name__)
app = config.make_wsgi_app()
serve(app, listen='127.0.0.1:8080')
$ curl http://localhost:8080\?join=OR\&name=39\&exact=true\&exact=false\&id=39
[["join", "OR"], ["name", "39"], ["exact", "true"], ["exact", "false"], ["id", "39"]]
Depending on which WSGI server you are using, often you can view environ vars to see the original url which may be handy. Waitress does not, so instead just put something high up in the pipeline (wsgi middleware) that can log out the environ['QUERY_STRING'] and see if it doesn't match somewhere lower down in your stack.
i follow the tutorial based on a service i wan't to use ( Drone Deploy) :
https://dronedeploy.gitbooks.io/dronedeploy-apps/content/server_example.html
i made a topic on their forum for this issue 2 days ago.( and repo on Github)
But maybe someone can help me here.
I got an issue with an Heroku server app i do.
i use Python and the Tornado module.
The fact is i got a 404 error
My terminal ( when test it localy ) ask me :
"WARNING:tornado.access:404 GET / (::1) 0.75ms"
so the "GET" function is not working , maybe because of HTTP access control (CORS) i try many fix , but none worked.
Maybe i made something wrong ,or forgot something.
update :
Recently someone of the Drone deploy said my tornado routes aren't being picked up by heroku.
After following many tutorial and read the Tornado documentation i have no idea how to routes this.
the url of the server : https://stardrone-server.herokuapp.com/
this the code :
import os
import requests
import tornado.ioloop
import tornado.web
GEOCODE_FMT = 'https://maps.googleapis.com/maps/api/geocode/json?address={address}&key={key}'
class GeocodeHandler(tornado.web.RequestHandler):
"""Proxy a call to the Google Maps geocode API"""
def set_default_headers(self):
# allow cross-origin requests to be made from your app on DroneDeploy to your web server
self.set_header("Access-Control-Allow-Origin", "https://www.dronedeploy.com")
self.set_header("Access-Control-Allow-Headers", "x-requested-with")
# add more allowed methods when adding more handlers (POST, PUT, etc.)
self.set_header("Access-Control-Allow-Methods", "GET, OPTIONS")
def get(self):
api_key = os.environ.get("MyApiKey")
address = self.get_query_argument("address")
url = GEOCODE_FMT.format(address=address, key=api_key)
# fetch results of the geocode from Google
response = requests.get(url)
# send the results back to the client
self.write(response.content)
def options(self):
# no body
self.set_status(204)
self.finish()
def main():
application = tornado.web.Application([
(r"/geocode/", GeocodeHandler)
])
port = int(os.environ.get("PORT", 5000))
application.listen(port)
tornado.ioloop.IOLoop.current().start()
if __name__ == "__main__":
main()
Maybe i missed something.
Any help, advices are appreciated
Thanks
John
Sorry for ambiguous question, I'm not sure how better I can put it. So let me do the explanation of my problem.
I've the Flask application libindic, which has 2 Flask application one is frontend and other is api. So I've wsgi.py as follows
from werkzeug.serving import run_simple
from werkzeug.wsgi import DispatcherMiddleware
from silpa import api, frontend
import os
conffile = os.path.join(os.path.dirname(__file__), "etc", "silpa.conf")
application = DispatcherMiddleware(frontend.create_app(conffile),
{'/api': api.create_app(conffile)})
if __name__ == "__main__":
run_simple('0.0.0.0', 5000, application,
use_reloader=True, use_debugger=True)
The front end access works properly but when I hit /api/JSONRPC I get 404 error returned. This rule is defined as follows in silpa/api/jsonrpc.py
bp = Blueprint('api_jsonrpc', __name__, url_prefix='/api')
#route(bp, '/JSONRPC', methods=['POST'])
def handle_jsonrpc_call():
...
And when I print value of application and application.app and application.mounts in python interpreter I see folllowing
>>> application.app
<Flask 'silpa.frontend'>
>>> application.mounts
{'/api': <Flask 'silpa.api'>}
I'm unable to figure out why /api/JSONRPC results in 404. I'm not sure how can I debug it. I did check the app.url_map for api application and I can see rule for /api/JSONRPC registered there.
If some one can tell me what I might be doing wrong it would be a great help.
OK after debugging and stepping through Flask code I figured out the reason for the problem. The following line actually caused the problem
bp = Blueprint('api_jsonrpc', __name__, url_prefix='/api')
url_prefix should not be present in code because I'm already mounting this app at /api. Adding a /api url_prefix will result in following url instead /api/api/JSONRPC. Removing the above line fixed the issue.
So if you are mouting your app at different mount point than / using DispatcherMiddleware you should not url_prefix in blueprint.
So, following the examples for swagger ui usage with flask blueprints (https://github.com/rantav/flask-restful-swagger/blob/master/examples/blueprints.py), I have the following code:
app = Flask(__name__)
test_blueprint = Blueprint('tests', __name__)
test_api = swagger.docs(restful.Api(test_blueprint), apiVersion='0.1',
basePath='http://localhost:5000',
produces=["application/json", "text/html"],
api_spec_url='/api/spec')
# Operation TestOp defined here
test_api.add_resource(TestOp, '/')
if __name__ == "__main__":
app.register_blueprint(test_blueprint, url_prefix='/test')
app.run(debug=True)
However, when I try to access the api spec docs, the URL cannot be located.
I've tried...
localhost:5000/api/spec
localhost:5000/test_api/api/spec
localhost:5000/test_api
...all of which return a 404. I've also tried creating the app without blueprints, creating the docs with
swagger.docs(restful.Api(app)...)
instead. When there this is done and no blueprints are involved, I can reach the docs at
localhost:5000/api/spec
So, am I creating my application incorrectly with blueprints, or am I just not hitting the right URL to get access to the docs?
I know this thread is old, but I ran into this exact problem today, trying to use flask-restful-swagger with my (somewhat) modern flask + python3 app that uses blueprints. Same problem, no errors, just no spec available no matter what i tried.
I finally abandoned this package (as it seems like it hasn't been very active anyway), even though I like the markup better with this package.
I chose Flasgger, which seemed to be updated more recently. In 10 minutes I had it up and running. Code and short tutorial are here: https://github.com/rochacbruno/flasgger
It looks like you're just not hitting the right URL. Because your blueprint url_prefix is "/test", the Swagger spec url should be at:
localhost:5000/test/api/spec
something wrong in swagger.docs()
from flask_restful import Api
test_blueprint = Blueprint('tests', __name__)
test_api = swagger.docs(Api(test_blueprint)...)
app.register_blueprint(test_blueprint)
what'more
main_blueprint = Blueprint('api', __name__, url_prefix='/demo')