Defining a static directory into app.yaml make app crash - google-app-engine

I have a weird issue on GAE standard (running node), more precisely with my app.yaml below.
runtime: nodejs8
# Environment variables
env_variables:
GOOGLE_CLOUD_PROJECT: '...'
# Static directories and files
handlers:
- url: /static
static_dir: public
Without the handlers part, everything works like a charm: my app is deployed and works. Note that the size is 4.8 MB (version 1-0-43).
However, with the handlers part, my app doesn't work anymore: 4xx error and an app size of 324 KB (version 1-0-43).
The sole purpose of the handlers part is to define a directory to serve static assets (CSS, JS, images...).
Any clue? Thanks.

When you add your static_dir handler definition the entire content of your public subdirectory is no longer (by default) uploaded together with your app code (most likely explaining the app size difference). Instead it's uploaded to a different location to be served directly by the GAE infra, see How to serve static files in AppEngine Standard and nodejs
It sounds that your app may need some of those files as well. In such case the easiest solution would be to add the application_readable flag to the static definition, causing that directory to be uploaded both in the static content location and together with your app code, see GAE: file_get_contents() and static files.
To speedup your deployments could also try to separate the static content in 2: one portion not needed by your app code, deployed without application_readable (thus not also uploaded with your app code, deployed faster) and one with the flag. If it's not too much trouble.

Could you try changing static_dir from 'public' to 'static'. Because the url and static_dir are usually located at the same place. Please try it and let me know. Cheers!
# Static directories and files
handlers:
- url: /static
static_dir: static

Related

Google App Engine URL Routing with App.Yaml for Static resource and Script

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.

serving static file not from /static in webpy

Is there a way of serving static files (images) not from the /static folder in webpy? What I would like to do is show images that are scattered in various directories, and moving all of them to /static is really not an option. If it is not feasible in webpy, are there any other python web frameworks that would do this?
Thanks,
v923z
You can easily do it when deploying your web.app under different webserver. But if you want to set static path in web.py development server then you'll have to patch webpy's static middleware or write your own. Please check my answer to the same question here: Changing the static directory path in webpy

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

Mixing static and dynamic endpoints in app.yaml file

I'm trying to describe endpoints in my App Engine app and am having difficulty for directory structures that mix static and dynamic content. But my yaml rules are conflicting with one another. Before I change my directory structure, does anyone have a recommendation?
The goal is to create a directory that contains both documentation (static html files) and implementations.
/api
- /v1
- getitdone.py
- doc.html
- index.html
What I think I should be doing with my application yaml...
- url: /api/v1/getitdone
script: api/v1/getitdone.py
- url: /api/
static_files: api/index.html
upload: api/index.html
- url: /api
static_dir: api
But this causes the dynamic endpoints to fail. I'm assuming the static_dir reference is breaking it. How can I do this without describing every script and static file reference (I have many more than are listed here)?
The cause of this is that you're marking /api/ as a static directory, so your scripts are getting uploaded as static files, which makes them inaccessible to the App Engine runtime.
The easiest solution would be to put your dynamic code and your static resources in different parts of your app's directory heirarchy, and use app.yaml to map them into the desired URL structure.

Uploading images along with Google App Engine

I'm working on a Google App Engine project.
My app is working and looking correct locally, but when I try to upload images in an image directory, they're not being displayed at appspot.
As a little troubleshoot, I put a HTML page in "/images/page2.html" and I can load that page at the appspot, but my pages don't display my images. So, it's not a problem with my path.
As another sanity check, I'm also uploading a style sheet directory with .css code in it, and that's being read properly.
I have a suspicion that the problem lies in my app.yaml file.
Any ideas?
I don't want to paste all the code here, but here are some of the key lines. The first two work fine. The third does not work:
<link type="text/css" rel="stylesheet" href="/stylesheets/style.css" />
Page 2
<img src="/images/img.gif">
This is my app.yaml file
application: myApp
version: 1
runtime: python
api_version: 1
handlers:
- url: /stylesheets
static_dir: stylesheets
- url: /images
static_dir: images
- url: /.*
script: helloworld.py
You have to configure app.yaml for static content such as images and css files
Example:
url: /(.*\.(gif|png|jpg))
static_files: static/\1
upload: static/(.*\.(gif|png|jpg))
For more info check out:
http://code.google.com/appengine/docs/configuringanapp.html
I'll bet your problem is that you're using Windows.
If that's the case, I believe you need a preceding slash for your static_dir value.
I am using the Java version of App engine, and I faced a similar issues with the server not able to serve static images.
What worked ultimately was to change the AppEngine config file "appengine-web.xml" in my case to contain
<static-files>
<include path="**.*"/>
<include path="/images/**.*" />
</static-files>
My images are in the /images directory and HTML and CSS are in . directory which is at the WEB-INF level
#jamtoday The preceding slash didn't make a difference, but it did get me started figuring out what each app needs to be told what about my directory structure.
So, I have nothing very conclusive to add, but I wanted to follow up, because I got it working, but I didn't explore all the issues after I got it working.
One change that helped was to stop working from a HwlloWorld/src/ directory and start working in the HelloWorld/ directory. It seems like the dev_appserver picked up all the dependencies, but the remote server didn't. Essentially, the relative path of my local links didn't match the relative path of the links after uploading.
I also realized that the dev-appserver relies on the .yaml file, as well as the appcfg script. That is. . .if you add a directory to your project, and then try to link to files in that directory, you need to add the directory to the .yaml file, and then restart the dev-appserver to pick up on this.
So, there are probably ways to handle what I was originally trying to do if you give the .yaml file the right info, but changing to a different directory structure locally handled it for me.
<img src="/images/img.gif">
this line can't show you the image.
Try this one:
1-Create a class to handle "image request"
class GetImage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'image/jpg'
self.response.out.write(image_object)
2-In your page.html:
<img src="/image"
3-At the main function in your code.py:
application = webapp.WSGIApplication(('/image', GetImage), debug=True)
have fun

Resources