flask routes not working on gae application - python-2.7

I have the following directory structure for my GAE project:
endpoints/
insights/
insights.py
init.py
lib/
__init__.py
insights.yaml
so in order to get access to the third libraries within lib folder I add the next code in __init__.py file.
import os
import sys
def add_lib_path():
lib_directory = os.path.dirname(os.path.abspath(__file__))
if lib_directory not in sys.path:
sys.path.insert(0, lib_directory)
and I added this code in the insights.py file before the import statements:
from lib import add_lib_path
add_lib_path()
the problem is that now I can import third libraries correctly but my #app.route('/something', methods=['POST']) are not working.
I send a post request and it returns status 200 but it doesn't go inside my #app.route code, I can actually send any route and it just pass out returning 200 but not data and not error.
My imports look like this:
from lib import add_lib_path
add_lib_path()
from flask import Flask, request
And my code inside #app.route('/something', methods=['POST']) looks like this:
def someDef():
some code ...
return response
my yaml file looks like this:
runtime: python27
api_version: 1
threadsafe: false
service: insights
handlers:
- url: /.*
script: endpoints/insights/insights.py
libraries:
- name: ssl
version: latest
Any suggestions about this? Thanks in advance!

The wildcard URL handler in your app.yaml is intercepting the /something post:
handlers:
- url: /.*
script: application.app
You will need to either map out individual urls in your app, or make unique url set for your insights, like /insights/.* in app.yaml. Either way, you can't have a catch-all url handler in your app.yaml if there are other urls you want to give special treatment to, like sending to a separate service.

ok I just changed in the app.yaml file the threadsafe to true, then I added the script like this endpoints.insights.insights.app, using Python module path (with dots not slash) and in my insights.py file I changed #app.route('/something', methods=['POST']) to #app.route('/insights/something', methods=['POST']) .. I added the complete URL that I defined in the app.yaml file and now it's working.
Thanks to #GAEfan for the help, I'll accept the GAEfan answer because it helped me a lot

Related

Static method returning empty list in Django

I am trying to run a Django app on local server. It works fine on mu Ubuntu machine but in mac, I can't get the CSS for
localhost:8000/admin
and
localhost:8000/docs to load.
On digging further, I found out that the static URL in main "urls.py" file
return an empty list instead of a URL pattern.
Does anyone have an idea why it is like that on the new mac system?
I have had the same issue. I was able to fix it manually by adding the following snippet to my urls.py file in the project (the urls.py file next to settings.py)...
from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve
. . .
if settings.TESTING_PRODUCTION:
urlpatterns += [
re_path(r'^static/(?P<path>.*)$', serve, {
'document_root': settings.STATIC_ROOT,
}),
]
I pulled this together from the Django Docs here.
I needed to do this so that I could test the "production" environment with manage.py runserver by manually setting DEBUG = False in settings.py which changes a few other URLs and also turns off trace printing in my code.
In my settings.py file, I have some code to set TESTING_PRODUCTION to True as well. But in actual production with a real web server, the code should set TESTING_PRODUCTION to False so that the static files can be served by the webserver directly and not through Django.

Changing robot.txt in django

I've created a website using Django and added robots.txt using the code :
path('robots.txt', lambda r: HttpResponse("User-agent: *\nDisallow: /", content_type="text/plain")),
in my main urls.py , it works great but now i need to add some rules to it .. how to do it
robots.txt is not just an HttpResponse. It is an actual file.
You can either continue to fabricate the whole response manually using the lambda function. In this case you need to keep building up a string response.
Or you could write a file to server's disk, write rules to it, etc. and serve that file upon request to robots.txt
Further reading on robots.txt (not related to django)
Related SO question: django serving robots.txt efficiently
You can write the robots.txt under your template and then serve it as follows if you want to serve it through Django:
from django.conf.urls import url
from django.views.generic import TemplateView
urlpatterns = [
url(r'^robots.txt$', TemplateView.as_view(template_name="robots.txt", content_type="text/plain"), name="robots_file")
]
However recommended way is to serve through your web server directives.
Nginx:
location /robots.txt {
alias /path/to/static/robots.txt;
}
Apache:
<Location "/robots.txt">
SetHandler None
Require all granted
</Location>
Alias /robots.txt /var/www/html/project/robots.txt
in your main app urls.py
from django.urls import path, include
from django.views.generic.base import TemplateView
urlpatterns = [
# If you are using admin
path('admin/', admin.site.urls),
path(
"robots.txt",
TemplateView.as_view(template_name="robots.txt", content_type="text/plain"),
),
path(
"sitemap.xml",
TemplateView.as_view(template_name="sitemap.xml", content_type="text/xml"),
),
]
Then go to your template root folder and create a robots.txt file and you can add something like this
User-Agent: *
Disallow: /private/
Disallow: /junk/
Got to your tempalte root folder again and create another file sitemap.xml and you can add somemthing like this or get it done properly with sitemaps generator here is an example:
<url>
<loc>https://examplemysite.com</loc>
<lastmod>2020-02-01T15:19:02+00:00</lastmod>
<priority>1.00</priority>
</url>
Now if you run python manage.py runserver you can test it 127.0.0.1:8000/sitemap.xml and /robots.txt and it will work. But this won't work in your production server because you will need to let nginx know about this and give the paths.
So you will need to ssh into your server and for example in nginx you should have a configuration file that you named when you built it. You should cd into /etc/nginx/sites-available in that folder you should have the default file (which you should leave alone) and there should be another file there that you named, usually should be named same as your project name or website name. Open that file with nano but take a back up first. Next you can add your paths for both files like this:
Be aware of the paths, but obviously you can look at the file and you should get an idea you should see the path to static file or media. So you could do something like this.
location /robots.txt {
root /home/myap-admin/projects/mywebsitename/templates;
}
location /sitemap.xml {
root /home/myap-admin/projects/mywebsitename/templates;
}
/home/myap-admin/projects/mywebsitename/templates you should know the path to your mywebsitename. This is just an example path that leads to templates folder.
Make sure you then run service nginx restart

running cron in google app engine gives 404 error

My cronjob does not run when I click Run Now in http://localhost:8000/cron
My app contains the following files
hello.py
import webapp2
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers["Content-Type"] = "text/plain"\
self.response.write("Congratulations, it's a web app!")
routes = [('/', MainPage)]
my_app = webapp2.WSGIApplication(routes, debug=True)
app.yaml
application: hello
version: 1
runtime: python27
api_version: 1
threadsafe: false
handlers:
- url: /.*
script: hello.my_app
- url: /tasks/summary
script: hello.application
cron_script.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class CronTask(webapp.RequestHandler):
def get(self):
f = open("test.txt","w") #opens file with name of "test.txt"
f.write("I am a test file.")
f.write("Maybe someday, he will promote me to a real file.")
f.write("Man, I long to be a real file")
f.write("and hang out with all my new real file friends.")
f.close()
application = webapp.WSGIApplication([('/tasks/summary', CronTask)],
debug=True)
if __name__ == '__main__':
run_wsgi_app(application)
cron.yaml
cron:
- description: daily summary job
url: /tasks/summary
target: beta
schedule: every 1 minutes
Your cron.yaml file will make requests to /tasks/summary.
Your app.yaml directs them to your hello.application.
But your matching hello.py file doesn't have a matching route for /tasks/summary.
You could expand your existing route pattern to match that path:
routes = [('/.*', MainPage)]
But more likely you'll add specific route for it (and you'll need to add the matching handler code for it as well):
routes = [('/tasks/summary', CronHandler)]

Where to place a robots.txt file in a Python 2.7/Bottle application on OpenShift?

Environment
Python 2.7
OpenShift
Application Structure:
.git
.openshift
data
libs
wsgi
- static
- views
- application
- my_bottle_app.py
README.md
setup.py
setup.pyc
setup.pyo
Desired Behaviour
I'm wanting to create robots.txt rules for files in the location:
wsgi/static/file_1.txt
wsgi/static/file_2.txt
For example:
User-agent: *
Disallow: /file_1.txt
Disallow: /file_2.txt
Question
Should the robots.txt file be placed in either
wsgi
wsgi/static
or the 'root' of the application structure?
Edit:
To clarify, the app is a Bottle application so there are a number of routes that serve different content.
Additionally, all pages are served via https with a custom function:
def redirect_http_to_https(callback):
'''Bottle plugin that redirects all http requests to https'''
def wrapper(*args, **kwargs):
scheme = request.urlparts[0]
if scheme == 'http':
# request is http; redirect to https
redirect(request.url.replace('http', 'https', 1))
else:
# request is already https; okay to proceed
return callback(*args, **kwargs)
return wrapper
install(redirect_http_to_https)
So I'm trying to understand where robots.txt should be placed so that it is served correctly.
It doesn’t matter where you place the robots.txt file in your backend.
It only matters where the robots.txt is accessible from the Web.
For each host, the file must be available at /robots.txt. So it must always be in the host’s root, never in a sub-folder.
Examples:
When a bot wants to crawl http://example.com/wsgi/static/file_1.txt, it should look for a robots.txt on http://example.com/robots.txt.
If it is https://example.com/wsgi/static/file_1.txt (https instead of http), the location must be https://example.com/robots.txt.
If it is http://www.example.com/wsgi/static/file_1.txt (with subdomain), the location must be http://www.example.com/robots.txt
Solution
This was the specific solution that seems to have worked informed by user unor's answer.
Add the Bottle route in Python app:
#route('/robots.txt')
def serve_robots():
return static_file('robots.txt', root='app-root/repo/wsgi/static/')
And then add robots.txt to wsgi/static/.
The robots.txt file is then accessible at.
https://app-username.rhcloud.com/robots.tx

Flask: render_template with path

I have several different templates that I'm trying to use for my flask app.
I have tried the following but it seems to only look directly inside /templates and not /templates/folder1, templates/folder2 etc.
return render_template('index.html', template_folder='folder1')
return render_template('folder1/index.html')
both do not work as expected, how can I specify the sub folder of different templates.
The template folder can be specified when creating the Flask app (or Blueprint):
from flask import Flask
app = Flask(__name__, template_folder='folder1')
Source: http://flask.pocoo.org/docs/0.12/api/#application-object
from flask import Blueprint
auth_blueprint = Blueprint('auth', __name__, template_folder='folder1')
Source: http://flask.pocoo.org/docs/0.12/blueprints/#templates
The template_folder is relative to where the app/blueprint is located.
Use the os library to create paths to template folders outside of the app/blueprint directory.
eg.
import os
APP_PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATE_PATH = os.path.join(APP_PATH, 'templates/')
run from subdirectory of app root
APP_PATH retrieves parent directory path (app root)
Be sure the Python file and Template folder are all under the same working directory folder.
I think Sean is right, but also: have you tried double quotes? I'm using Blueprint, so it may be different, but this is what mine looks like:
return render_template("users/register.html")
so yours may be:
return render_template("folder1/index.html")