GWT, AppEngine and pretty url (human url) - google-app-engine

Can anybody show a working example of how to get pretty urls on a GWT project over AppEngine.
I know that you will suggest to look at UrlRewriteFilter. I have been burning it for 3 days and get no succedd.
Please, could help?

Maybe what you're looking for: Pretty URLs in Google App Engine

This will work, and it's really easy:
def main():
application = webapp.WSGIApplication([('/', MainHandler), ('/(.*)', PostHandler)], debug=True)
class PostHandler(webapp.RequestHandler):
def get(self, slug):
As explained in the article on Pretty Urls with Google App Engine

I followed that link till urlrewrite filter, wich is what i am using at the moment.
I get to transform domain/?user=43434&mensage=89898 to domain/user43434-mensage89898 which is quite good for me.
But i can not transform it to domain/43434/8989.
When i try to do this i always get a fail consisting on my services cannot find an *.wgt.rpc file.
In other words, I am not able to run the next example when i use GWT:
http://zenoconsulting.wikidot.com/blog:16

You can do it on the client side with the History class if you're willing to have a # at the beginning of your URLs. In my app teachers can access their grades at http://activegrade.com/#calculus/grades, for example. The History object receives "calculus/grades" and you can parse it from there.
GWT 2.1 introduces the concept of Places - you could look into that as well.

Related

how to put backend and frontend together - returning react frontend from fastapi backend endpoint

Firstly, I just wanted to say that this is my first web application project. I've spent the past few days trying to find answers on how to essentially put the frontend and backend together. I have a lot of questions, but the main one I want answered is on how to return my frontend 'final product' from a backend endpoint.
This is what I understand (please correct me if I'm wrong):
The frontend code is run by the client (browser).
When the client interacts with the webpage, the frontend makes API calls to the backend to retrieve/modify data, as necessary.
The backend and frontend is often developed separately, and could be hosted on separate servers.
It is, however, possible (and maybe simpler) to host it on a single domain/server. I am hoping to do this, in order to avoid a whole set of issues with CORS.
Then comes the following problem:
When I want to test out my front end and see how it's coming along, I just run npm run start. I then go to the given url (usually http://localhost:8080/) and I have access to the frontend that I've developed. And when I want to deploy it, I run npm run build, which gives me a dist folder (bundled together and minified).
If I want to run and test my backend locally, as I am using FastAPI, I simply run uvicorn main:app --reload.
How to put the two together? More specifically, in my backend code, how do I return the product of my frontend work (i.e., the dist folder?). I've tried the following (simplified):
#app.get("/", response_class=HTMLResponse)
def root():
return open("../frontend/dist/index.html", "r").read()
but, of course, this only gives me the static html without the React components.
I realize this post may be loaded with incorrect assumptions and poor practices (in which case, my apologies! and I would appreciate any corrections/suggestions.) However, if the following questions could be answered, I would greatly appreciate it. These are questions I have that will hopefully help me test my whole web application locally on my computer.
How do I return the product of my frontend work for the GET request at the domain root endpoint?
If there is a page A, page B, and page C for my web app, each with url www.example.com/A, www.example.com/B, and www.example.com/C do I have to create three separate React frontend projects? I.e., equivalent of having three dist folders? What is the standard way this is handled?
These are good questions and it is certainly possible. I will tell you what I do, with the caveat that there may be a better way...
I'm using Vue instead of React, but its build process also sends static html, js and css to a dist/ directory, so the process should be about the same.
First you can copy the dist/index.html file you mention into your FastAPI templates/ directory. You will use your FastAPI route to serve that file as a Template.
Then copy your js and css into a static/ directory and make sure FastAPI knows about both static and templates.
from fastapi import FastAPI, Request
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")
#app.get("/")
async def serve_spa(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
You may need to set something in React in order for your build to know that the js and css will live in a dir called static. For Vue, there is the assetsDir option within vue.config.js
For your question about handling different paths, like example.com/a and example.com/b, it depends how you want to handle those requests. Are you wanting your single react app to handle all of those routes?
If that is the case, you may want to see also: How to capture arbitrary paths at one route in FastAPI?
One option is to copy the serve_spa() route above and handle your routes, like /a, /b, etc.
Or use a catch-all route:
#app.route("/{full_path:path}")
async def catch_all(request: Request, full_path: str):
print("full_path: "+full_path)
return templates.TemplateResponse("index.html", {"request": request})
The "traditional" approach to running a web application is to have a server that serves your web application (i.e. your React app). Usually you'll hear about nginx being used as the web server being used for modern day single page applications. When you run npm run start you start up a local server on your machine and it makes your app available at http://localhost:8080 (the port and hostname are of course configurable).
When it comes to your API, it should be it's own server available at a different endpoint/url, and then your web app will make API calls to that endpoint/url in order to fetch data.
The way you're describing things, it sounds like you're trying to use FastAPI to server render your web app, but I'm not sure how feasible that is, especially considering there is an entire framework solely dedicated to server rendering react applications.
I've also struggled with this and here's an approach that worked for me
import logging
from fastapi import FastAPI
from starlette.responses import RedirectResponse
from starlette.staticfiles import StaticFiles
app = FastAPI()
#app.get("/")
async def index():
return RedirectResponse(url="/index.html")
app.mount("/", StaticFiles(directory="backend/ui/"), name="ui")
Note: Please observe that app.mount is called after registering the / route. From my experience if the mount is called before the registration then it will simply not redirect to index.html
Note: I use react-scripts to generate the app.
Dear hainabaraka
Your question resembles this one: How do I serve a React-built front-end on a FastAPI backend?. In that one, I contributed an answer, but I'd like to also refer you to Mike Chaliy's answer, which updates mine.
In any case, here are two thoughts on that solution (that I should really update) and the answers you get here:
the nginx approach: this removes responsibility from your code, meaning that it also removes control from you. DevOps love this kind of "you do your thing and let me worry about that" approach, but let's just say that this is a good solution... not for your case. You want to serve from your API.
By the way, "it should be it's own server" has no apostrophe!
the Jinja2 approach: I'm not sure this would work, and even if it did, it would be introdsucing a lot of CPU waste. Jinja2 is an excellent tool for Python based backend tremplate rendering. I used it extensively to generate HTML medical reports to be then PDF-rendered but in this case it always sounds like a "Yes, it works, but...". Rule of thumb for "but"-sentences: everything to the left of the "but" is irrelevant.
the FastAPI RTFM approach: I am a HUGE fan of FastAPI and I'm (extremely slowly) trasnslating its documentation to European Portuguese, but the examples there are very very limited. Referring you to the FastAPI docs is assuming you're an idiot that never thought of that.
other approaches: I saw a bungh of these that, while well intentioned, did not really work because they were either produced by that kinf of people here in SO that don't really test their answer before answering, or by pure back-end devs that have no clue how a React (or a SPA) app works. Some can even serve a home page but then routing kills it.
The solution I present works and has been working for me for years now, both with Vue and React SPAs. The caveat is that you either serve your app from a special endpoint (I suggest /my-spa, which is quite lame), or, if you want the app to come from /, you have to do the
app.mount('/', SPAStaticFiles(directory='folder', html=True), name='whatever')
after all other endpoints, and you cannot obviously have other endpoints conflicting with either / or any React route within it. This perhaps adds to why APIs are recommended to hang from an /api endpoints, and possibly versioned, like /api/v1/.... Please let me know if this works for you.
For that, there an excellent resource in Zalando RESTful API and Event Guidelines.

user / session variables appengine with python

I'm new to app engine, python an web development in general. I have an issue that i don't know how to solve. I want to maintain in the server an tuple with values that the user select. I pass this values to the server in the parameters of the page.
But the problem is that this tuple is modified by all the users and I want that each user can have his own values. The users aren't identified.
I've been looking for how to solve it, and I found some answers here in stackoverflow, but major part of them are more than 2 years old, and I think that I need to use the library gaeutilities, but not sure about it, and If Google have an “official” solution to maintain session variables with python in app engine.
I defined the var “categoria” as a class variable,
class returnElements(webapp2.RequestHandler):
categoria = []
def get(self):
…...
cat = str(self.request.get("cat"))
self.categoria.append(cat)
…...
app = webapp2.WSGIApplication([
('/returnElements', returnElements),
…....
and here the url
http://localhost:13080/returnElements?cat=Sudaderas
It works fine, but just with one user at time :-(
By the way Im new to stackoverflow, sorry in advance if the question isn't accurate or solved in another thread.
In any web app, you must never store user-specific data in module or class-level variables as they will be shared by all users.
If you need to persist data for a user, save it in the datastore! That's what it's for. There are various implementations of user-specific sessions, such as the gaeutilities library which you link to. That library has full documentation which you should read.

why i couldn't see any text in "http://crawlservice.appspot.com/?key=123456&url=http://mydomain.com#!article"?

Ok, i found this link https://code.google.com/p/gwt-platform/wiki/CrawlerSupport#Using_gwtp-crawler-service that explain how you can make your GWTP app crawlable.
I got some GWTP experience, but i know nothing about AppEngine.
Google said its "crawlservice.appspot.com" can parse any Ajax page. Now I have a page "http://mydomain.com#!article" that has an artice that was pulled from Database. Say that page has the text "this is my article". Now I open this link:
crawlservice.appspot.com/?key=123456&url=http://mydomain.com#!article, then i can see all javascript but I couldn't find the text "this is my article".
Why?
Now let check with a real life example
open this link https://groups.google.com/forum/#!topic/google-web-toolkit/Syi04ArKl4k & you will see the text "If i open that url in IE"
Now you open http://crawlservice.appspot.com/?key=123456&url=https://groups.google.com/forum/#!topic/google-web-toolkit/Syi04ArKl4k you can see all javascript but there is no text "If i open that url in IE",
Why is it?
SO if i use http://crawlservice.appspot.com/?key=123456&url=mydomain#!article then Can google crawler be able to see the text in mydomain#!article?
also why the key=123456, it means everyone can use this service? do we have our own key? does google limit the number of calls to their service?
Could you explain all these things?
Extra Info:
Christopher suggested me to use this example
https://github.com/ArcBees/GWTP-Samples/tree/master/gwtp-samples/gwtp-sample-crawler-service
However, I ran into other problem. My app is a pure GWTP, it doesn't have appengine-web.xml in WEB-INF. I have no idea what is appengine or GAE mean or what is Maven.
DO i need to register AppEngine?
My Appp may have a lot of traffic. Also I am using Godaddy VPS. I don't want to register App Engine since I have to pay for Google for extra traffic.
Everything in my GWTP App is ok right now except Crawler Function.
So if I don't use Google App Engine, then how can i build Crawler Function for GWTP?
I tried to use HTMLUnit for my app, but HTMLUnit doesn't work for GWTP (See details in here Why HTMLUnit always shows the HostPage no matter what url I type in (Crawlable GWT APP)? )
I believe you are not allowed to crawl Google Groups. Probably they are actively trying to prevent this, so you do not see the expected content.
There's a couple points I wish to elaborate on:
The Google Code documentation is no longer maintained. You should look on Github instead: https://github.com/ArcBees/GWTP/wiki/Crawler-Support
You shouldn't use http://crawlservice.appspot.com. This isn't a Google service, it's out of date and we may decide to delete it down the road. This only serves as a public example. You should create your own application on App Engine (https://appengine.google.com/)
There is a sample here (https://github.com/ArcBees/GWTP-Samples/tree/master/gwtp-samples/gwtp-sample-crawler-service) using GWTP's Crawler Service. You can basically copy-paste it. Just make sure you update the <application> tag in appengine-web.xml to the name of your application and use your own service key in CrawlerModule.
Finally, if your client uses GWTP and you followed the documentation, it will work. If you want to try it manually, you must encode the Query Parameters.
For example http://crawlservice.appspot.com/?key=123456&url=http://www.arcbees.com#!service will not work because the hash (everything including and after #) is not sent to the server.
On the other hand http://crawlservice.appspot.com/?key=123456&url=http%3A%2F%2Fwww.arcbees.com%2F%23!service will work.

GaeUtilities: Session Problem

I'm programming an application with google app engine, with django 1.1 (no django pacth or others), well as you know is impossible use django login and session features so I download
Gae utility and use Session Object (http://gaeutilities.appspot.com/) but some time this object create 2 sessions instead 1 session ... here's code
def index(request):
aSWrap = SWrap(SWrap.createSession())
....
def login(request):
aSWrap = SWrap(SWrap.createSession())
....
class SWrap(object):
#classmethod
def createSession():
return Session(cookie_name='my_cookie',session_expire_time=7200)
and for setting session no expiration or really long expiration...enter code here
Thanks
Judging by the code, you're calling createsession twice within the same request. That will cause problems with David's library as well.
Also, gaeutilties session included a config file where you can modify all the default values as you like.
https://github.com/joerussbowman/gaeutilities/blob/master/appengine_utilities/settings_default.py
gaeutilities session also has security features lacking in gae-sessions. I'm afraid David didn't attempt to answer you question, rather just suggested you use his library which under your current implementation would have the exact same problem. You need to be sure you only initiate the session once per http request no matter what session library you're using.
I'm moving gaeutilities session to a decorator in order to address this issue as well and provide better performance. You can watch the master branch on Github for updates. https://github.com/joerussbowman/gaeutilities
I suggest using a different sessions library. Check out this comparison of the available sessions libraries for GAE.
I'd recommend gae-sessions - it presents an API almost identical to the library you are currently using, but it is much faster and shouldn't give you headaches like the bug you've encountered above.
Disclaimer: I wrote gae-sessions, but I'm not the only one who would recommend it. Here is a recent thread discussing sessions on the google group for GAE python.
What are you trying to do with SWrap(SWrap.createSession())? It looks like the result of SWrap.createSession() is passed to the SWrap() constructor. Have you omitted part of the definition of SWrap?
Perhaps this is more what you are wanting:
def index(request):
mysession = SWrap.createSession()
....
def login(request):
mysession = SWrap.createSession()
....
class SWrap(object):
#staticmethod
def createSession():
return Session(cookie_name='my_cookie',session_expire_time=7200)

How to run the CherryPy web server in the Google App Engine

The CherryPy web server can supposedly be deployed in the Google App Engine.
Who has done it, and what was the experience like?
What special effort was required (configuration, etc.)?
Would you recommend it to others?
The article is a good example but its slightly out of date now as the patch is no longer required, the latest version of Cherrypy should run without it, I've gotten the sample below running in the development environment.
I've included cherrypy inside a zip file as the google app engine has a limit of one thousand files per application, it also makes it easier to deploy.
I'm also using the cherrypy dispatch handler to route the request.
import sys
sys.path.insert(0, 'cherrypy.zip')
import cherrypy
import wsgiref.handlers
class Root:
exposed = True
def GET(self):
return "give a basic description of the service"
d = cherrypy.dispatch.MethodDispatcher()
conf = {'/':
{
'request.dispatch': d
}
}
app = cherrypy.tree.mount(Root(), "/",conf)
wsgiref.handlers.CGIHandler().run(app)
So far I've not come across any particular issues but I have read some people have had issues with sessions.
See boodebr.org article (missing, but here on the Wayback machine) It works for me.
If you are looking for an example, look for the condition that accepts ServerMode.GAE in ServerInterface.auto in this example.
There is a good article on how to do this over here now here. I haven't actually tried this yet, I stuck with django on App Engine, but it seems to be a solid example.

Resources