override wildcard dispatch.yaml entry with a specific path in app engine - google-app-engine

I am in a situation where I have one app engine service (service-a) that needs to handle a particular path (domain.com/some/particular/path) and I have another app engine service on the same domain (service-b) that needs to handle all other traffic to that domain (domain.com/*).
I've tried structuring my dispatch.yaml as follows, however no matter what I do the domain.com/some/particular/path ends up getting handled by service-b rather than service-a. In other words, all paths are being routed to service-b.
dispatch:
- url: "domain.com/some/particular/path"
service: service-a
- url: "domain.com/*"
service: service-b
How can I handle this situation?

This seems to be more about your code than the dispatch.yaml file that is roting to service-b. For example, I deployed two services, service 1:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return 'Service 1'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
And service 2:
from flask import Flask
app = Flask(__name__)
#app.route('/')
def hello():
return 'Service 2'
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
With the following dispatch.yaml:
dispatch:
- url: "domain.com/app2/"
service: app2
- url: "domain.com/*"
service: default
If I try to access to domain.com/app2/ it shows NOT FOUND error message. If I change the routing in service 2 from #app.route('/') to #app.route('/app2') it works like a charm.
I think that your dispatch.yaml redirects to your service-a but the code inside that service redirects to domain.com.
BTW, if inside your services all your .yaml files are named app.yaml GAE for an unknown reason redirect to the default service so it's better to name every .yaml as the service it handles.

Related

Mapping Google App Engine service to Cloudflare

I'm having an Google App Engine service residing at https://service-dot-myproject.uc.r.appspot.com/
However I want it to be reachable via https://app.mydomain.com
I have set up the DNS for mydomain.com on Cloudflare and added the custom domain mapping in app engine and set up a dispatch.yaml file
- url: "app.mydomain.com/*"
service: service
Is there a way to somehow map
https://service-dot-myproject.uc.r.appspot.com -> https://app.mydomain.com ?
currently https://app.mydomain.com only resolves to defaultservice
The following dispatch.yaml file resolved the issue
dispatch:
- url: "app.mydomain.com/*"
service: service
Also the file must be separatly deployed via:
gcloud app deploy dispatch.yaml

Issues while deploying Flask-admin module in gcloud app engine

I am trying to deploy a flask application to gcloud app engine. I am trying to use the Flask-Admin module. The code works fine on my local server. But when deployed to gcloud app engine the admin module does not work. Let me know if you need any further details.
Any help is very much appreciated.
Below is the code for the main
if __name__ == '__main__':
admin = admin.Admin(app, 'my application Admin', index_view=MyAdminIndexView(), template_mode='bootstrap3')
admin.add_view(ModelView(ContactUs))
admin.add_view(ModelView(TestimonialsAdmin))
app.run(host='127.0.0.1', port=8080, debug=True)
Below is the error I observe while trying to access admin
Not Found The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
Tried standard python 37 as well as flexible environment.
runtime: python37
service: appname
handlers:
- url: .*
script: auto
Issue resolved after removing the below code from main method.
admin = admin.Admin(app, 'my application Admin', index_view=MyAdminIndexView(), template_mode='bootstrap3')
admin.add_view(ModelView(ContactUs))
admin.add_view(ModelView(TestimonialsAdmin))
placed them in the program like below :-
admin = admin.Admin(app, 'my application Admin', index_view=MyAdminIndexView(), template_mode='bootstrap3')
admin.add_view(ModelView(ContactUs))
admin.add_view(ModelView(TestimonialsAdmin))
if __name__ == '__main__':
app.run(host='127.0.0.1', port=8000, debug=True)

How to proxy an endpoint, using Google App Engine

I used to have an Nginx proxy that would do below :
location /api {
proxy_pass http://www.myapiexample.com;
}
Then if I made a request to my website at www.example.com/api, it would take me to http://www.myapiexample.com.
With the app engine, and I'm using Nodejs as my backend, how I can achieve the same?
Can't find anything in the docs
UPDATE : If I'm understanding correctly, I can't have my Nginx anymore, so I need to find a way to have the same proxying functionality with App Engine.
You can use dispatch.yaml configuration file if both of your web and api modules are on app engine. dispatch.yaml sends incoming requests to a specific service depending on the path or hostname in the URL.
dispatch:
# Default service serves simple hostname request.
- url: " example.com"
service: default
# Send all api traffic to the api backend.
- url: "*/api/*"
service: api-backend
You can read more about how to use dispatch file.
If your api module is not on app engine you can redirect requests on application level
dispatch:
# Send all api traffic to the api backend.
- url: "*/api/*"
script: router.py
You can write your routing code in router.py something like
class RouteHandler(webapp.RequestHandler):
def get(self):
self.redirect("http://www.myapiexample.com;", True)

Google App Engine - Flask Application Bypassing Standard Google Auth on Devserver

I am new to Flask and I am trying to organize my code as a large application for deployment on Google App Engine. I am using Flask-Classy to help organize my application into logical packages.
The application runs on the dev server just fine with one exception. When I set login: required or login: admin in my app.yaml (see app.yaml below), the application appears to skip over the mock Google Login page and automatically signs in as 'test#example.com'.
Normally, I would expect to see the standard Google mock authentication form (below) when login:required or login: admin is set in the app.yaml. However, when I point the browser to the '/' or any other uri, I am directed right to the respective page without authenticating via this form.
I am not sure what I am missing/doing wrong. I am not getting any type of errors.
Below, I have included my application's structure and most of the pertinent code to see if anyone might be able to point out anything I am doing wrong here.
/flask_app
/flask_app
/mod_one
/__init__.py
/forms.py
/views.py
/models.py
/mod_two
/__init__.py
/forms.py
/views.py
/models.py
/static
/css
...
/templates
/index.html
...
/__init__.py
/settings.py
/urls.py
/lib
/app.yaml
/appengine_config.py
/main.py
app.yaml
application: flask-app
version: 1
runtime: python27
api_version: 1
threadsafe: yes
default_expiration: "30d"
builtins:
- deferred: on
- admin_redirect: on
handlers:
- url: /css
static_dir: flask_app/static/css
- url: /admin/.*
script: main.app
login: admin
- url: /.*
script: main.app
login: required
appengine_config.py
import sys
import os.path
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'lib'))
main.py
from flask_app import app
app = app
flask_app/init.py
import os
from flask import Flask
from flask_bootstrap import Bootstrap
from werkzeug.debug import DebuggedApplication
app = Flask(__name__)
if os.getenv('FLASK_CONF') == 'TEST':
app.config.from_object('flask_app.settings.Testing')
elif 'SERVER_SOFTWARE' in os.environ and os.environ['SERVER_SOFTWARE'].startswith('Dev'):
# Development settings
app.config.from_object('flask_app.settings.Development')
app.wsgi_app = DebuggedApplication(app.wsgi_app, evalex=True)
else:
app.config.from_object('flask_app.settings.Production')
# Instantiate Flask-Bootstrap.
Bootstrap(app)
import urls
flask_app/urls.py
from flask import render_template
from flask_app import app
#app.route('/')
def index():
params = {
'page_title': 'Home'
}
return render_template('index.html', **params)
#app.route('/contact')
def contact():
params = {
'page_title': 'Contact'
}
return render_template('contact.html', **params)
#app.route('/about')
def about():
params = {
'page_title': 'About'
}
return render_template('about.html', **params)
# Error handlers
# Handle 404 errors
#app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
# Handle 500 errors
#app.errorhandler(500)
def server_error(e):
return render_template('500.html'), 500
# Register Flask Classy Classes
import mod_one.views as mod_one
import mod_two.views as mod_two
mod_one.OneView.register(app)
mod_two.TwoView.register(app)
As #Greg pointed out in a comment to the question, I was already 'logged in' to the dev_appserver (which threw me off since I never saw the mock login page) so authentication was happening using the default 'test#example.com' user.
Once I went to /_ah/login I was able to access the mock login page and proceed as usual from there.

URL with trailing slash in Google App Engine

This is my app.yaml:
- url: /about|/about/.*
script: about.py
This is my `about.py':
application = webapp.WSGIApplication([(r'^/about$', AboutPage),
(r'^/about/$', Redirect),
(r'.*', ErrorPage)],
debug = True)
I want to redirect all requests for /about/ to /about. I'd like all other requests to be sent to the error page.
It works in the development server on localhost, but I cannot access /about/ after I deployed the app on GAE - it just shows an empty page.
I adjusted the order of URL patterns in app.yaml.
It works now on GAE.
If you don't want trailing slashes for GET requests anywhere in your application, you can implement a global redirect at the top of your app.yaml. Note that POST requests will NOT redirect, but this is ok (for me anyway) because users don't generally hand-write POST URLs.
app.yaml:
application: whatever
version: 1
api_version: 1
runtime: python
handlers:
- url: .+/
script: slashmurderer.py
slashmurderer.py
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
class SlashMurdererApp(webapp.RequestHandler):
def get(self, url):
self.redirect(url)
application = webapp.WSGIApplication(
[('(.*)/$', SlashMurdererApp)]
)
def main():
run_wsgi_app(application)
I see that this question has already been answered, but I ran into the same problem and wanted to see if there was a "lazier" solution.
If you're using the Python 2.7 runtime, then the webapp2 library is available, and I believe the following will work:
import webapp2
from webapp2_extras.routes import Redirect Route
class MainHandler(webapp2.RequestHandler):
def get(self):
self.response.out.write("This is my first StackOverflow post")
app = webapp2.WSGIApplication([
RedirectRoute('/', MainHandler, name='main', strict_slash=True),
('/someurl', OtherHandler),
])
strict_slash=True means that if the client doesn't supply the slash it will be redirected to the url with the slash (to match the first argument).
You can combine the special Route classes from webapp2_extras with normal (regex, handler) tuples as shown above. The "name" parameter is required for the constructor for RedirectRoute. More details here: webapp2_extras documentation for RedirectRoute

Resources