I have this web app and the very first page that loads is the login page:
app.appspot.com
after successfully login the app redirects to:
app.appspot.com\foo
I'd like to know if there is a way to map
app.appspot.com\foo to app.appspot.com
UPDATE
Here's my app.yaml:
handlers:
- url: /js
static_dir: static/js
- url: /css
static_dir: static/css
- url: /fonts
static_dir: static/fonts
- url: /img
static_dir: static/img
- url: .*
script: handler.app
secure: always
This answer assumes you're using the python environment.
You could have a login_required decorator to check if the user is logged in, redirect to a login page if not and then back after login completes. An example of such decorator which uses the GAE users API as authentication method can be found in webapp2_extras.appengine.users:
from google.appengine.api import users
def login_required(handler_method):
"""A decorator to require that a user be logged in to access a handler.
To use it, decorate your get() method like this::
#login_required
def get(self):
user = users.get_current_user(self)
self.response.out.write('Hello, ' + user.nickname())
We will redirect to a login page if the user is not logged in. We always
redirect to the request URI, and Google Accounts only redirects back as
a GET request, so this should not be used for POSTs.
"""
def check_login(self, *args, **kwargs):
if self.request.method != 'GET':
self.abort(400,
detail='The login_required decorator '
'can only be used for GET requests.')
user = users.get_current_user()
if not user:
return self.redirect(users.create_login_url(self.request.url))
else:
handler_method(self, *args, **kwargs)
return check_login
You could map your handler currently handling the '/foo' path to '/' and apply such decorator to its get() method, obtaining the result you desire (your decorator would actually perform the login function by your '/' current handler).
And you can apply such decorator to any other handler/path in your app.
Related
I have a backend Django REST API that also helps serve my React frontend. I currently have an issue with my API requests url paths to my Django API in production for every page except my home page...
API URL's that work:
I'm able to visit my home page, within my home page, I have a GET request to my API which works great and loads data as expected. This is the only working GET request of my website because the API URL path is correct to my urlpatterns syntax.
API URL's that DON'T work:
The issues arise when I visit a page OTHER than the home page of my React app. My API requests to Django on other pages are using the wrong URL path according to my network panel (they are also responding with index.html), which has me believe I set up my django URLs wrong.
Please checkout my configuration below:
main urls.py:
def render_react(request):
return render(request, "index.html") #<---- index.html from React
urlpatterns = [
path('auth/', include('drf_social_oauth2.urls', namespace='drf')),
path('admin/', admin.site.urls),
path('api/', include('bucket_api.urls', namespace='bucket_api')),
path('api/user/', include('users.urls', namespace='users')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]
urlpatterns += [
re_path('',render_react) #<---- Serving React index.html
]
Here is an example of the issue:
When I visit this subpage URL:
https://mywebsite.com/try-demo/ra4r7n7mdb
A GET request should be firing off too this URL:
https://mywebsite.com/api/demo/ra4r7n7mdb
However instead of sending the request to the correct URL above, it's sending to this url:
https://mywebsite.com/try-demo/api/demo/ra4r7n7mdb
This is the same problem for other parts of my website that are requesting data from my django api. So when I visit my login page (https://mywebsite.com/login), and enter my details to request an authentication token. The request for the token should be:
https://mywebsite.com/auth/token/
but instead its requesting the data through this:
https://mywebsite.com/login/auth/token/
How to fix this?
my url patterns has a catch all request, my react is then able to 404 pages that don't exist. The only problem I have is how my React app is requesting data to my API in production. (again the API request on my homepage works fine) Why are my other requests appending the first URL path of my React router URL's?
I don't want to clog this post with code, so please let me know what other information I should present here to help solve this problem?
UPDATE
I have solved the API request issues to my server. The paths are now correct according to the network panel. However, the issue still remains where I seem to be only getting my index.html as the response for these API requests (they should be data responses, not index.html)
Here is my catch all regex for Django
re_path(".*/", render_react),
re_path(r"^$", render_react)
NEW EDIT
I am now able to get one of my API data requests to respond with JSON data (as should be expected)
Here is the URL of the API request that works:
https://mywebiste.com/api/demo/idoyem1l4k/
These still don't work:
https://mywebsite.com/api/demo/tabledata/idoyem1l4k
https://mywebsite.com/api/demo/graphdata/idoyem1l4k
How I make requests:
import axios from 'axios';
const baseURL = `https://mywebsite.com/api`;
const axiosInstance = axios.create({
baseURL: baseURL,
timeout: 9000,
headers: {
Authorization: 'Bearer ' + localStorage.getItem('access_token'),
'Content-Type': 'application/json',
accept: 'application/json',
},
});
export const getData = async (dispatch, slug, cancelToken) =>
{
try
{
console.log('fired demo request')
const response = await axiosInstance.get("demo/graphdata/" + slug, { cancelToken });
dispatch({ type: 'FETCH_SUCCESS', payload: response.data });
} catch (err)
{
if ('isCancel' in err && err.isCancel())
{
return;
}
dispatch({ type: 'FETCH_ERROR' });
}
}
How can I return the actual data requested instead of my index?
It makes sense, that it always returns the index.html. Your catch all regex prevents your API calls to be called, so it always resolves to render_react. I think you have 3 options.
You try to put the catch-all patterns to the bottom of all urlpatterns - I'm not sure how reliable this is though
You do not catch all by deleting re_path(".*/", render_react), and explicitly name every react page you want to use
You change the catch-all regex to exclude your Django apps with something like re_path("(?!api).*/", render_react),
I would choose option 2, as it gives you most control of your urls
Hi I have an angular 2 application which i would like to deploy to gae. So back end I am using app engine python. I am trying to do a simple post request from angular front end to app engine python. So following is my app.yaml
runtime: python27
api_version: 1
threadsafe: true
service: federation-bipedal-hominids
handlers:
- url: /.*
script: main.app
- url: (.*)/
static_files: federation-bipedal-hominids/src/app\1/index.html
upload: app
- url: (.*)
static_files: app/home\1
upload: app
main.py
import json
import webapp2
import time
# app = StaticURLParser("federation-bipedal-hominids")
def AsDict():
return {"Hello World !": "try now"}
class RestHandler(webapp2.RequestHandler):
def dispatch(self):
#time.sleep(1)
super(RestHandler, self).dispatch()
def SendJson(self, r):
self.response.headers['content-type'] = 'text/plain'
self.response.write(json.dumps(r))
class HelloWorld(RestHandler):
def post(self):
r = AsDict()
self.SendJson(r)
class QueryHandler(RestHandler):
def get(self):
r = AsDict()
self.SendJson(r)
app = webapp2.WSGIApplication([
('/HelloWorld', HelloWorld)
], debug=True)
now, how should i do it from angular front end ?
So I am using Stamplay facebook login. But it looks like I can not change the redirect URI. So after successfully login on facebook end, it redirect to this URI:
https://actorreels.stamplayapp.com/?jwt=[token]#/_=_
This will trigger my main route instead of the admin route - where I want user to land after login. Here is my stateProvider setting:
$stateProvider
.state('people', {
url: '/:nameUrl',
templateUrl: 'app/frontend/page.tmpl.html',
params: {
nameUrl: {squash: true},
},
controller: "PageController",
controllerAs: 'vm'
})
.state('admin', {
url:'/admin/:userId',
templateUrl:'app/frontend/admin/admin.html',
controller:'AdminController',
controllerAs: 'admin'
})
As you see, the return URI will trigger people route with nameUrl = "=". I want user to go to admin route instead with jwt as JSON token. How can I do that?
I understand there is $urlRouterProvider.when() I can use to make "/?jwt=" into my admin route. But I do not know how to do that (either in Regex or function...). Could someone help me to figure this out? Greatly appreciated!
You can change the redirect URI for Stamplay inside the editor.
First go to the editor inside the USERS > AUTHENTICATION.
Here you will see icons for all the social logins.
On the far right, you can select the cog icon to manage setting for your login flow. Here you can changed the redirect URI for login, and logout.
Note that for your angular application, include the route beginning with the #. For example. https://mystamplayapp.stamplayapp.com/ is the base url, so your need to enter #/route inside the editor to go to the "route" route.
I am developing an app with AngularJS frontend + GAE backend (Python and Flask). I am having troubles to setting app.yaml for routing my API endpoints created with Flask-Restless extention. My app.yaml file looks like this:
application: myAppID
version: 1
runtime: python27
threadsafe: true
api_version: 1
handlers:
# handler 1
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
# handler 2
- url: /api/.*
script: main.app
# handler 3
- url: /test
script: main.app
# handler 4
- url: (.*)/
static_files: app\1/index.html
upload: app #this is the frontend folder for Angular
# handler 5
- url: (.*)
static_files: app\1
upload: app #this is the frontend folder for Angular
In Angular, the routes configuration looks like this:
App.config(['$stateProvider', '$locationProvider', '$urlRouterProvider', 'RouteHelpersProvider',
function ($stateProvider, $locationProvider, $urlRouterProvider, helper) {
'use strict';
$locationProvider.html5Mode(false);
// default route
$urlRouterProvider.otherwise('/app/dashboard');
// other routes ...
}]);
The main.py file looks like this:
from flask import Flask
import os
from werkzeug import debug
from flask import jsonify
from google.appengine.ext.webapp.util import run_wsgi_app
app = Flask('myApp')
if os.getenv('SERVER_SOFTWARE') and os.getenv('SERVER_SOFTWARE').startswith('Google App Engine/'):
app.debug = False
else:
app.debug = True
if app.debug:
app.wsgi_app = debug.DebuggedApplication(app.wsgi_app, True)
#app.route('/test')
def test():
return jsonify(test={"json": "test"})
import models
run_wsgi_app(app)
models is the file that contains Flask-SQLAlchemy models and Flask-Restless endpoints.
The Angular part loads correctly, for example this URL works fine:
A) http://localhost:8080/#/app/dashboard
But the GAE backend part responses with a 500 error for URLs like these:
B) http://localhost:8080/api/person
C) http://localhost:8080/test
If I remove the handler 4 and handler 5 then B and C URLs works fine but Angular frontend stop working.
What I'm doing wrong?
Im on the go, so writing from my phone isn't that fun...
Any way, what i did in my app is that i have only one handler that triggers the flask app.
In the flask app usually the / route will return the angular web app as a static file.
You need to configure your Flask app , that it will know about the statics (HTML, JS etc.) Folder.
EDITED:
app.yaml should look like this:
handlers:
- url: .* # This regex directs all routes to main.app
script: main.app
main.app is the flask app..
now lets see how to serve the angular app from the route '/'
from flask import Flask, render_template
app = Flask(__name__, static_folder='/templates') # This sets /templates to be the folder for all JS HTML CSS files
#app.route('/')
def wellcomePage():
return app.send_static_file('index.html')
angular routing configuration in your app.js file:
app.config(['$routeProvider', '$locationProvider',
function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/views/home.html'
}).... Some More Routes..
Note that templateUrl: 'templates/...'
Please take a look at my app. I think it will help you understand what I'm trying to say here...
SE Hub at github
Ill edit this answer when i get to a freaking keyboard :)
Let me know if this helps.
Using ui-router in Angularjs users can accesses resources from my DB with a unique code in the URL like this:
http://example.com/abc123
with the state:
.state('show', {
url: '/:resourceID',
templateUrl: '/views/resource.html',
controller: 'ResourceController'
})
However, I'm not sure how to render the 404.html when a resource isn't found in the DB. At the moment I am returning a 404 error from Expressjs and I have an interceptor that then redirects using:
//detect 404 and redirect url
$window.location.href = "/error/404";
but this isn't ideal - you have to wait for the redirect and the URL changes.
How can I show a static 404.html and not affect the URL in the browser?