I have deployed my react app to GCP's App engine. It successfully deploys and the landing page is accessible. However none of the routes work. All the routes are giving '404' error.
I am pretty sure its the app.yaml configuration that has issue. Help please!
app.yaml
runtime: nodejs10
handlers:
- url: /
static_files: build/index.html
upload: build/index.html
- url: /
static_dir: build
The issue is that you are using both static_files and static_dir to your / url.
You need to either use static_files or static_dir.
From the description of your question it looks like you want to use static_dir to match everything that is inside the directory after the url: /.
As stated in the documentation:
static_dir: The path to the directory containing the static files, from the application root directory. Everything after the end of the matched url pattern is appended to static_dir to form the full path to the requested file.
static_files: A static file pattern handler associates a URL pattern with paths to static files uploaded with the application. The URL pattern regular expression can define regular expression groupings to be used in the construction of the file path. You can use this instead of static_dir to map to specific files in a directory structure without mapping the entire directory.
Related
I followed this tutorial: https://cloud.google.com/storage/docs/hosting-static-website to host my React webapp. Here is what I have so far:
// app.yaml
runtime: nodejs10
handlers:
- url: /static
static_dir: build/static
- url: /(.*\.(json|ico|js))$
static_files: build/\1
upload: build/.*\.(json|ico|js)$
- url: /.*
static_files: build/index.html
upload: build/index.html
(I've tried MANY configurations here)
I run npm run build and put the build directory in GCP Cloud Storage along with app.yaml. When I go to my website I get this:
This happens when I hit the root url.
It looks like it is looking at the static directory which should then look at build/static according to my app.yaml.
If I go directly to the webpage such as https://www.drinkingbuddy.io/build/static/js/main.39aaab31.js, the browser displays the file as expected. So it is there being hosted but something is messed up with pathing? I'm not sure.
Testing locally, everything works. Even when serving the build files.
Any guidance would be greatly appreciated! Thank you.
EDIT:
Another thing is that when I go to the base url, it just shows the document tree.
EDIT 2:
When accessing the files directly from the bucket such as https://www.storage.googleapis.com/drinkingbuddy-static/build/index.html, I then get this error:
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>UserProjectAccountProblem</Code>
<Message>User project billing account not in good standing.</Message>
<Details>The billing account for the owning project is disabled in state absent</Details>
</Error>
But looking through my account I don't see any billing issues.
EDIT 3:
Now I am able to get to .../build/index.html and it displays my site. but the root / is still throwing errors saying it can't find main.js. I added homepage: "." to my package.json.
I was able to get it to work by doing homepage:"/build". Now I can access the root url and get expected behavior.
I have the following app.yaml + file structure:
css files keep giving me 404:
I have tried different file structures and both static_dir and static_files in the app.yaml, nothing works...
ideas?
Based on the current file structure and your app.yaml config, your css files will have to be referenced in html relative to the url handler you defined: like /css/static.css.
With that covered, the static_dir has to be defined properly and relative to the location of your app.yaml, should be code/public/css and not /code/public/css. Note the leading slash you put there
handlers:
- url: /css
static_dir: code/public/css
If you want the full path though in your html, your config file will have to be tweaked slightly:
handlers:
- url: /code/public/css
static_dir: code/public/css
Is there a way to only serve existing files in a static directory? For example in my app.yaml file I have
- url: /img
static_dir: img
Which works fine if you go to /img/exists.jpg. However if you go to /img/doesnt-exist.jpg you get an ugly Error: Not Found message. Is there a way to make it skip this file and go to this script so that I can add a custom 404 message?
- url: /.*
script: index.php
According to the current documentation, you can configure a custom error response.
I am busy migrating a app into the GAE. I used to utilize timthumb.php to resize images on demand from within a static img folder. From the same folder I used to serve static images aswel.
eg: example.com/img/image_name.jpg
example.com/img/timbthumb.php?src=example.com/img/image_name.jpg&w=50&h=50
etc.
I am not using timbthump.php anymore, I have re-written it to serve images via CloudStorageTools.php api, and I do not want to go through all code to rewrite the image paths.
Now, on my local environment the google app engine is serving both versions of images, static and dynamic via timbthumb.php.
On the live environment GAE only serves static or dynamic, I cannot build URL handlers to serve both.
The timbthumb.php images are throwing a 404 error with both handlers.
My app.yaml
application: my-app
version: 1
runtime: php55
api_version: 1
threadsafe: yes
handlers:
- url: /favicon\.ico
static_files: favicon.ico
upload: favicon\.ico
- url: /css
static_dir: dir/css
#timbthumb.php images
- url: /img/(.+\.php)$
script: dir/img/timbthumb.php
#static images
- url: /img
static_dir: dir/img
#all other php files
- url: /.*
script: dir/index.php
My Question, how can I make GAE route static images via example.com/img/ and the timthumb.php script located at example.com/img/timbthumb.php in my app.yaml?
Thanks
According to the documentation you can't serve a script from a static directory:
A static directory handler makes it easy to serve the entire contents
of a directory as static files. Each file is served using the MIME
type that corresponds with its filename extension unless overridden by
the directory's mime_type setting. All of the files in the given
directory are uploaded as static files, and none of them can be run
as scripts.
The fact that it appears to be running in the development server is just another reflection of the fact that the development server is just an approximation of GAE, but not really GAE.
If your image paths naming allows it you could use static_files routing rules instead of a static_dir one:
A static file pattern handler associates a URL pattern with paths to
static files uploaded with the application. The URL pattern regular
expression can define regular expression groupings to be used in the
construction of the file path. You can use this instead of
static_dir to map to specific files in a directory structure without
mapping the entire directory.
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