Flask adding a slash when a URL has a get parameter - python

Flask seems to be not adding a slash at the url end before the get parameters in every case. But is doing it only in this case.
it changes /users?uid=1 to /users/?uid=1
After changing it to tha it even gives me a 404 error. "The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again."
Here's the code:
from flask import Flask, render_template, jsonify, Response, request
app = Flask(__name__)
#app.route("/users")
#app.route("/post")
#app.route("/bookmarks")
#app.route("/<target>")
def category_browser(target = ""):
if(target != "" and target not in ['categories']):
return render_template("404.html")
else:
return render_template("view.html")
if(__name__ == "__main__"):
app.debug = True;
app.run(port=int(80))

You had a stale cache entry in instance of Chromium when you had the route defined as #app.route("/users/"). You later changed to #app.route("/users") which Chrome still had it cached with the trailing /. Try accessing this simple example using incognito mode and see that /users?uid=1 remaining unchanged and that no 404 is reported. This is what happens when I first accessed it initially (using Chrome 42).
127.0.0.1 - - [07/Jul/2015 14:02:39] "GET /users?target=1 HTTP/1.1" 200 -
Then stopping that script (thanks for that complete almost self-contained example) and add #app.route("/users/") to the list of routes, below the original #app.route("/users/") route (to have a higher order of precedence so that Flask first trigger the redirect), i.e.:
#app.route("/users")
#app.route("/users/")
(Or simply remove the #app.route("/users") decorator)
Now try accessing the same page again in your incognito session, note that in your console:
127.0.0.1 - - [07/Jul/2015 14:04:11] "GET /users?target=1 HTTP/1.1" 301 -
127.0.0.1 - - [07/Jul/2015 14:04:11] "GET /users/?target=1 HTTP/1.1" 200 -
Ah, there's your redirect. Remove that extra line we just added, try going to /users?target=1 again, this is what happens:
127.0.0.1 - - [07/Jul/2015 14:07:22] "GET /users/?target=1 HTTP/1.1" 404 -
Chrome silently rewrites the URL to /users/?target=1 based on the cache entry in the incognito mode, and is reflected because only that URL is showing up on the Flask access log.
If you wish to support both methods, you have to do it this way:
#app.route("/users/")
#app.route("/users")
Then both access methods work:
127.0.0.1 - - [07/Jul/2015 14:08:49] "GET /users/?target=1 HTTP/1.1" 200 -
127.0.0.1 - - [07/Jul/2015 14:08:59] "GET /users?target=1 HTTP/1.1" 200 -
Rather than resulting in:
127.0.0.1 - - [07/Jul/2015 14:10:00] "GET /users?target=1 HTTP/1.1" 301 -
127.0.0.1 - - [07/Jul/2015 14:10:00] "GET /users/?target=1 HTTP/1.1" 200 -

Related

Flask api server not working across local network [duplicate]

This question already has answers here:
Configure Flask dev server to be visible across the network
(17 answers)
Closed 4 months ago.
I have a Flask api server running, worked absolutely fine on 127.0.0.1 right up until I started tinkering with trying to get it working across the LAN. I can see the connections from other devices on the LAN in the debug log, and it is receiving the connections fine, but not serving any pages, only 404, but not even my custom 404.
I have enabled Network Discovery, set network to Private, allowed Python through the firewall and tried using a non standard port (51234), disabled firewalls but I still get 404 errors.
127.0.0.1 - - [20/Oct/2022 12:38:00] "GET / HTTP/1.1" 404 -
192.168.1.205 - - [20/Oct/2022 12:38:11] "GET /api/companies?id=1 HTTP/1.1" 404 -
192.168.1.168 - - [20/Oct/2022 12:38:25] "GET / HTTP/1.1" 404 -
192.168.1.113 - - [20/Oct/2022 12:38:41] "GET / HTTP/1.1" 404 -
192.168.1.205 - - [20/Oct/2022 12:43:58] "GET / HTTP/1.1" 404 -
So in order to test it, I went back to basics and only allowed localhost again, and now nothing is working!
* Serving Flask app 'training_server' * Debug mode: on * Running on http://127.0.0.1:5155 Press CTRL+C to quit * Restarting with stat * Debugger is active! 127.0.0.1 - - [20/Oct/2022 12:44:54] "GET / HTTP/1.1" 404 - 127.0.0.1 - - [20/Oct/2022 12:45:12] "GET / HTTP/1.1" 404 - 127.0.0.1 - - [20/Oct/2022 12:45:12] "GET /favicon.ico HTTP/1.1" 404 - 127.0.0.1 - - [20/Oct/2022 12:50:09] "GET / HTTP/1.1" 404 -
from flask import Flask, json, jsonify, request
companies = [{"id": 0, "name": "ACME", "state":"Essex"},
{"id": 1, "name": "Bluebell", "state":"Hertfordshire"}
]
users = [{"company":"ACME","name": "Steve Herbert", "employeeID":"125785", "email":"sherbert#acme.com"},
{"company":"ACME","name": "Steve Herbert", "employeeID":"125785", "email":"sherbert#acme.com"}
]
api = Flask(__name__)
api.config["DEBUG"] = True
api.config['JSON_SORT_KEYS'] = False
api.run(host='127.0.0.1', port=5155)
#api.route('/', methods=['GET'])
def home():
return "<h1>Company Directory</h1><p>This site is a prototype API for company directory listing.</p>"
#api.route('/api/companies/all', methods=['GET'])
def get_companies():
return jsonify(companies)
#api.route('/api/companies', methods=['GET'])
# Check if a param was provided as part of the URL.
# If param is provided, assign it to a variable. If not, display an error in the browser.
def get_company():
print('req' + str(request.args))
print('hello' + next(iter(request.args.keys())))
#print([elem[0:] for elem in request.args.keys()])
if 'id' in request.args:
filter = next(iter(request.args.keys()))
param = int(next(iter(request.args.values())))
elif 'name' in request.args:
filter = next(iter(request.args.keys()))
param = str(next(iter(request.args.values())))
else:
return "Error: No param field provided. Please specify a value."
results = apiParam(param, filter, companies)
return jsonify(results)
def apiParam(param, filter, list):
print('filter' + str(filter))
results = []
# Loop through the data and match results that fit the requested parameter.
for li in list:
if li[filter] == param:
results.append(li)
return results
if __name__ == '__main__':
api.run()
Fixed it after some more research/Googling while I waited for answers
Moved the host declaration to underneath the if name call
import os
if __name__ == '__main__':
port = int(os.environ.get("PORT", 5155))
api.run(host='0.0.0.0', port=port)
The problem comes from run.api() at the start. This is blocking the script so the route handlers are never reached.
Move that line to the end, inside the if __name__ block.

Flasgger: Swagger App - http://127.0.0.1:5000/apidocs/ - Fetch errorINTERNAL SERVER ERROR /apispec_1.json

I created a Flasgger/Swagger App in Spyder and got returned:
127.0.0.1 - - [28/Mar/2021 21:49:13] "GET /apispec_1.json HTTP/1.1" 500 -
127.0.0.1 - - [28/Mar/2021 21:49:13] "GET /flasgger_static/favicon-32x32.png HTTP/1.1" 200 -
When trying to visit this app in my Google Chrome browser via http://127.0.0.1:5000/apidocs/ I got back this error:
Fetch error
INTERNAL SERVER ERROR /apispec_1.json
What do I have to change here?

Flask is loading static files from a different path when a route is called [duplicate]

This question already has answers here:
Link to Flask static files with url_for
(2 answers)
Why use Flask's url_for?
(1 answer)
Closed 3 years ago.
I have 2 route functions, one to get all users and one to get a specific user. Both functions render the same template. The first function works fine, the problem is with the second one. When rendering the template it tries to load static files from another directory.
I tried using a different template for each one and the problem remained.
Get all users route:
#app.route('/users')
def list_users():
users = Users.query.all()
return render_template('users.html', users=users)
Get one user route:
#app.route('/users/<username>')
def get_user(username):
user = Users.query.filter_by(name=username).first()
if user:
return render_template('users.html', users=[user])
Template rendered by get_user route function:
127.0.0.1 - - [07/Aug/2019 13:35:56] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [07/Aug/2019 13:35:57] "GET /favicon.ico HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/Ana HTTP/1.1" 200 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/vendor/fontawesome-free/css/all.min.css HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/css/sb-admin-2.min.css HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/img/uatronica_black_transparent.png HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/vendor/jquery/jquery.min.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/vendor/bootstrap/js/bootstrap.bundle.min.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/vendor/jquery-easing/jquery.easing.min.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/js/sb-admin-2.min.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/vendor/chart.js/Chart.min.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/js/demo/chart-area-demo.js HTTP/1.1" 404 -
127.0.0.1 - - [07/Aug/2019 13:36:06] "GET /users/static/js/demo/chart-pie-demo.js HTTP/1.1" 404 -
It is trying to load css files from /users/static/ instead /static/. Why is that?
You are using relative paths in your template, so the final URL is relative to whatever URL you're at. When viewing /users, if the template links to static/css/admin.css, it becomes /users/static/css/admin.css. If the path starts with a /, it is an absolute URL and won't do this.
Instead, use url_for, which generates absolute URLs no matter where you are and how the app is deployed.
<link rel="stylesheet" href="{{ url_for('static', filename='css/admin.css') }}>
This becomes /static/css/admin.css.
Please use the below code.
Get one user route:
#app.route('/users/<username>')
def get_user(username):
user = Users.query.filter_by(name=username).first()
return render_template('users.html', users=user)
Additionally please share the html page users.html for review.

Flask - Having more than one static folder (the static folders are actually dynamic)

Im currently working on a project that has the following structure:
ROOT
-js
-dist
-index.html
-bunch of other files that index.html uses
-src
-main.py
-doc_apps
-app1
-index.html
-other resources that index.html needs
-app2
-index.html
-other resources that index.html needs
Now my flask configuration is:
ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
COMPONENT_FOLDER = os.path.abspath(os.path.join(ROOT_DIR, '../'))
DIST_FOLDER = os.path.join(COMPONENT_FOLDER, 'js\\dist')
DOCUMENTATION_FOLDER = os.path.join(COMPONENT_FOLDER, 'documentation_data')
app = Flask(__name__, static_folder=DIST_FOLDER, template_folder=DIST_FOLDER, static_url_path='')
my_loader = jinja2.ChoiceLoader([
app.jinja_loader,
jinja2.FileSystemLoader(DOCUMENTATION_FOLDER),
])
app.jinja_loader = my_loader
#app.route('/')
def index():
"""
This the main entry to the application
Returns
-------
out
renders the 'index.html' file
"""
return render_template('index.html')
#app.route('/get_index_html', methods=['GET'])
def get_index_html():
index_html_path = request.args.get('path')
full_root = os.path.join(index_html_path).replace('\\','/')
return render_template(full_root)
When I start my app and go to the main page im able to render the index.html (the one in the js/dist folder) and everything works great
the problem starts when I try to render one of the inner index.html.
Im able to render the index.html by itself but I get the following errors
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/css/theme.css HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/pygments.css HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/js/modernizr.min.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/jquery.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/underscore.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/doctools.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/js/theme.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/jquery.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:43] "GET /_static/underscore.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:44] "GET /_static/doctools.js HTTP/1.1" 404 -
127.0.0.1 - - [02/Aug/2018 18:08:44] "GET /_static/js/theme.js HTTP/1.1" 404 -
I can tell that the problem is that it cant find the static files that are needed in order to generate this index.html correctly.
How can I tell it that for this specific index.html use some_static_folder?
I was wondering if there is something like render(html, static_folder=...)
I would like to mention that each one of the App1/index.html
has its own links and those links rely on the inner structure of App1, so how can I configure that when I send App1/index.html it will use some static_folder for everything that will be invoked from that App1/index.html
Some more info, App1/2 can be added also after the server is already running.
thank you very much for your help

Redirect BaseHTTPServer stdout to logging

I wrote a quick webserver using BaseHTTPServer, and it's working nicely, so now I'm trying to implement logging, and I noticed, hey, seems like BaseHTTPServer already has some logging information that it spits out to the stdout, is there a way to implement my logging to also include this stdout.
i.e. Have logging record all information from the stdout.
Note: I am not explicitly printing anything to the console window, when a GET request is made, BaseHTTPServer handles printing this to the console.
Example:
127.0.0.1 - - [02/May/2014 20:51:52] "GET /postTest.html HTTP/1.1" 200 -
127.0.0.1 - - [02/May/2014 20:51:52] "GET /assets/foundation.js HTTP/1.1" 200 -
127.0.0.1 - - [02/May/2014 20:51:52] "GET /assets/bootstrap.css HTTP/1.1" 200 -
127.0.0.1 - - [02/May/2014 20:51:57] "GET /index.html HTTP/1.1" 200 -
127.0.0.1 - - [02/May/2014 20:51:57] "GET /assets/foundation.js HTTP/1.1" 200 -
127.0.0.1 - - [02/May/2014 20:51:57] "GET /assets/bootstrap.css HTTP/1.1" 200 -
According to the BaseHTTPServer documentation, you can override the log_message method to do this. By default, it just writes to stderr, but you can make it write to your logger instead (or have it write to both).

Categories