Proper app.yaml handlers configuration for Google App Engine for a static html website - google-app-engine

Here is the file structure of my website:
public
│ 404.html
│ app.yaml
│ index.html
│ index.xml
│ prereqs.zip
│ sitemap.xml
│ sof2018.py
|
├───categories
│ index.html
│ index.xml
├───css
│ styles.css
├───home
│ index.html
├───js
│ scripts.js
├───prerequisites
│ index.html
├───scripts
│ │ index.html
│ │ index.xml
│ │
│ ├───page
│ │ └───1
│ │ index.html
│ │
│ └───sof2018
│ index.html
├───tags
│ index.html
│ index.xml
└───usage
index.html
Basically I need to ensure the following:
if any folder is called with trailing slash (say /scripts/page/1/ or /home/), it should look for index.html inside that folder
if any folder is called without trailing slash (say /scripts/page/1 or /home), it should look for index.html inside that folder
if any file (say /css/styles.css or /prereqs.zip) is called, it should return the file
The way to differentiate between files and folders could be to simply to check if there is a period(.) since all my files have extensions. Though I guess someone else might benefit with a solution that handles extension-less files also.
I have tried a number of different regexes, all of them seem to missing out some case or the other. Also tried all the solutions proposed in previous questions on stackoverflow on pretty much the same thing.
I'm not looking for an app.yaml tailor-made for my website, that can be done by manually dealing with each of the folders, cases, etc.
I'm looking for a general solution that would work exactly how a traditional web host would work, since I'm guessing that would benefit others as well. Then I'll be free to add/change content/structure without having to update app.yaml every time.
P.S. In all honesty, google should have themselves provided the solution, but they haven't. I'm guessing even proper web devs aren't regex masters.
P.S.2 The website is made using the Hugo static site generator. I can confirm it is working on a traditional web host (GoDaddy). Also I don't know enough html/css/js to tell for sure what is the actual internal working of the site; if required I can provide the source files.

You cannot achieve all of this on (standard environment) GAE with a completely static website. That's because you have no way of telling ahead of time (i.e. when creating the app.yaml config) if /some/path/item is a file or a folder and thus /some/path/item or /some/path/item/index.html should respectively be returned.
It's not a matter of writing the right regex, it's a matter of wanting 2 different outcomes for the same regex.
To achieve what you want you need the app to check the condition at runtime and make the decision - not a static site anymore.
If you drop your 2nd bullet you can achieve the rest with this:
- url: /(.*)/
static_files: public/\1/index.html
upload: public/.*/index.html
- url: /(.*)$
static_files: public/\1
upload: public/.*
If you have a way of differentiating files from folders you may be able to come up with a scheme. For example by specifying that all filenames must have extensions (and directories cannot have . in their names), then you can do something like this:
# /optional/path/folder/ - serve index.html inside
- url: /(.*)/
static_files: public/\1/index.html
upload: public/.*/index.html
# /optional/path/name.extension => files - serve them
- url: /((.*\/)*[^\/]+\.[^\/]+)$
static_files: public/\1
upload: public/.*
# anything else is a folder - serve index.html inside
- url: /(.*)$
static_files: public/\1/index.html
upload: public/.*/index.html

Related

How to host a project built with adapter-static and dynamic routes?

I have a Sveltekit project with a similar structure
src/
├ routes/
│ ├ [...unknown]
│ │ └ +page.svelte
│ ├ category/
│ │ ├ [...path]/
│ │ │ └ +page.svelte
│ │ └ +page.svelte
│ └ normal/
│ └ +page.svelte
With the following config
import adapter from '#sveltejs/adapter-static';
/** #type {import('#sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
prerender: {
entries: [
'*',
'/[...unknown]',
'/category/[...path]',
]
},
},
};
export default config;
the project can be built without errors and in preview mode the routing works as expected.
After deploying it to firebase hosting the dynamic routes give a Page not found error described in this question Sveltekit [...slug] dynamic routing returns 404 error after deployment Trying the provided solution the error on the page changes to Dynamic Link Not Found
So besides hoping to solve this, I'm first of all interested in understanding what exactly is going on here with the dynamic routes and what server and setup is needed to host the project where these routes/files will be correctly resolved
/[...unknown].html
/category/[...path].html

Vercel - Deploy Flask Backend + React Frontend

I have a webapp that has React frontend with a Flask backend. I want to deploy this application onto a tool called Vercel. Can someone point me to an example tutorial/setup/example Github Repository that accomplishes this task
As I know, you can't deploy the Flask back-end on Vercel. I'm not familiar with Flusk, but I checked right now and you can deploy your Flusk back-end server on railway.app. Then hit from your front-end that you can deploy on Vercel.
It took me a while to figure this out as well, even though Flask usage is technically "documented" in the official docs. You need something like this:
your_app_root/
└── api/
├── function1/
│ └── index.py
├── function2/
│ └── index.py
└── index.py
#!index.py
from flask import Flask, Response
app = Flask(__name__)
#app.route("/", defaults={"path": ""})
#app.route("/<path:path>")
def catch_all(path):
# Everything above this line should look the same for each
# index.py. Modify lines below this to have different logic
# for different routes.
return Response(
"<h1>Flask</h1><p>You visited: /%s</p>" % (path), mimetype="text/html"
)
Basically, each function is going to be a separate Flask app. So you cannot do any routes within the Flask api with #app.route. It needs to all be folder based because Vercel is doing the routing.

How do I add cache-control response headers to index.html and static JS bundles created by Webpack in Springboot application?

Basically, I have springboot application serving my index.html and other static JS files which includes(runtime, vendor, main) chunks created during the production build by Webpack. How do I set cache-control settings for index.html and chunks separately so that index.html won't be cached and chunks will be cached on the client-side? Currently, I have my resources under static folder like the following:
├── static
│ ├── index.html
| |-- bundles
│ │ ├── main.js
│ │ ├── vendors.js
│ │ ├── runtime.js
`
Basically, I am aiming for long-term caching of static assets on the client-side.
I interpret your question as asking how you can control this in Spring.
I think the better way to achieve what you want is to let Webpack output the different chunk-names so that they are cached for a long time (or until you deploy a new version of a chunk), not by specifically setting cache related headers for each filename.
The Webpack caching documentation recommends outputting the different chunk filenames to also include the contenthash.
output: {
path: path.join(__dirname, "build"),
filename: "bundle.[contenthash].js",
}
This will name your current bundle.js to something like bundle.7b4c86b268840bec8c4d.js. The first time a browser visits your site it will cache that chunk for a long time, typically a year but it depends on your configuration.
When you make changes to whatever code goes into bundle.[contenthash].js, the value of contenthash will change and the browser will cache that new version of your site/bundle since the filename doesn't match the cached bundle filename any more.
For more information, please refer to the aforementioned Webpack caching documentation

Moving HTML files to their own directory in Google App Engine (Using Jinja2 Templates) - Error 13

This seems like its probably something simple and n00bish, but I can't move my .html files to their own directory without the site coming to a screaming halt. They work file if left in the root folder.
Here's what I tried to do
<root>
|_ app.yaml
|_ main.py
|_ ...etc
|_<layout>
|_ base.html
|_ home.html
|_ ...etc
I added the following to my app.yaml file:
- url: /layout
static_dir: layout
I figured that would do it, and since nothing else uses that directory I assume the order in HANDLERS doesn't matter. Here is my complete handlers section in case someone spots something obvious I missed (I admit to not having a great understanding of this, despite having trolled through documentation and other problems here relating to static files and directories):
handlers:
- url: /favicon.ico
static_files: favicon.ico
upload: favicon.ico
- url: /layout
static_dir: layout
- url: /stylesheets
static_dir: stylesheets
- url: .*
script: main.app
I've tried mixing up the order of the handlers, but the error is always the same:
IOError: [Errno 13] file not accessible: 'E:\\Users\\Steve\\Documents\\test_gae\\test\\layout\\home.html'
Any suggestions would be greatly appreciated, Cheers
ANSWER, as per the answer from voscausa: these HTML files are templates, not static pages. Removing the static handler for 'layout' completely solved the problem.
If you use Jinja2, you do not need to put the /layout folder in your app.yaml, because you do not serve the templates static, but you render the templates with jinja and write the response HTML.
So the problem must be in your code. Look at the template path.
The order of handler matters. The url patterns are matched from top to bottom. This means
- url: /.*
script: main.app
is always the last handler!!

GAE: How to upload files to be accessed by the application?

Update: I found the problem. My static rule for HTML files still matched the templates even though they were in a subdirectory. After changing the rule to not match them anymore, the files could be accessed by the application.
I'm creating a Google AppEngine application. I'm using the Go language but I'm not sure that's relevant. I want to use a template with a separate template file. So the application must read the template file. Locally this works but after uploading the app to GAE, I get "no such file or directory" when calling template.ParseFiles().
So I'm thinking that somehow I must indicate that the template files are application files so that they get uploaded in the right way. I thought maybe my template files were uploaded as static files because of this in my app.yaml
- url: /(.*\.html)
static_files: \1
upload: .*\.html
So I moved them to their own directory. But that didn't make a difference. I tried adding an upload directive for my script rule in app.yaml like this:
- url: /.*
script: _go_app
upload: templates/.*
But that didn't seem to be allowed. So can anyone tell me how do I access the template files (or any data files) from my GAE application?
Thanks!
All files in your project directory are automatically uploaded.
If your app needs to access them (this is your case as you are working with templates) you can't mark them as static. This is why the first solution fails.
The second attempt, does not work either as upload is not a member of an url description.
In your case, just deploy your app and the files will be automatically uploaded and available to your app (you may need to get the basepath of your project to construct the full path to the template).
The files are automatically uploaded, assuming they're not in a static_dir or static_files directory. See the Skipping Files section in the App Engine documentation. App Engine treats such directories and files as static resources, and static resources are served separately from the application.
Static resources are not normally accessible from application code. If you must put your templates in the same directory as your other static resources, you can use the application_readable setting to make such resources accessible to your app as well.
But as you note, you can put your templates in a place within your app that isn't mapped to a static resource path; that's probably the right thing to do.
Check the different options for the app.yaml at [1]. You can check the static_dir and static_files options. I’m sharing a sample that is able to download static files. These files are in the static folder adn test folder. I share my app.yaml:
runtime: python27
api_version: 1
threadsafe: yes
handlers:
- url: .*
script: main.app
- url: /test
static_dir: test
application_readable: true
- url: /(.*\.(gif|png|jpg))$
static_files: static/\1
upload: static/.*\.(gif|png|jpg)$
application_readable: true
And the main.py:
…
import webapp2
...
class Download(webapp2.RequestHandler):
def get(self):
imageName = self.request.get('img-name')
self.response.headers['Content-Disposition'] = str('attachment; filename=' + imageName)
f = None
try:
f = open('static/' + imageName, 'r')
self.response.out.write(f.read())
except:
self.response.out.write('Jon Wayne')
class Test(webapp2.RequestHandler):
def get(self):
imageName = self.request.get('tst-name')
self.response.headers['Content-Disposition'] = str('attachment; filename=' + imageName)
f = None
try:
f = open('test/' + imageName, 'r')
self.response.out.write(f.read())
except:
self.response.out.write('Jon Test')
app = webapp2.WSGIApplication([
('/download', Download),
('/tst', Test)
], debug=True)
I have two images: fib2.png and fib1.jpeg
Then in the Test folder I have two files fib2.tst and fib1.tst.
Web is the domain name.
https://web.com/download?img-name=fib2.png
https://web.com/download?img-name=fib1.jpeg
https://web.com/tst?tst-name=fib2.tst
https://web.com/tst?tst-name=fib1.tst
Hope this helps!
[1] https://cloud.google.com/appengine/docs/standard/go/config/appref#handlers_element

Resources