Is it possible to make a cron request to a URL via Google App Engine using method=post. I could not find anything in the documentation allowing different methods other than get.
https://developers.google.com/appengine/docs/python/config/cron#Python_app_yaml_Cron_support_in_the_development_server
the simple answer is no. from the docs it is clearly stated that cron jobs use HTTP GET. the best thing is to change your method to GET and restrict direct access to the url in your app.yaml.
like this:
handlers:
- url: /report/weekly
script: reports.app
login: admin
It's not possible. The requests will have a header 'X-AppEngine-Cron' that you can check for, that might help if you want to prevent accidental running from a browser.
Related
Is it possible to group certain requests togeather based on their url ensuring that similar requests go to the same instance?
E.g.
There are multiple instances for my app engine
myurl.com?foo=abc // Multiple people putting in this url will all go to the same instance
myurl.com // I don't care which one this goes
I don't think you can control which instance handles a url pattern.
If you want to send certain urls to a certain service, what you want is a dispatch.yaml, which does exactly that. You can use regex to tailor how you want. With some strategy, you could match urls with (groups of) instances, though they would be in separate services. If your site doesn't get a lot of traffic, you could essentially have one instance per service, and accomplish what you want.
dispatch:
# don't forget: gcloud app deploy dispatch.yaml after changes !!!
- url: "*/some/high/memory/urls/*"
service: my_high_memory_service
- url: "*/some/fast/cpu/url"
service: my_fast_cpu_service
- url: "*/.*"
service: default
More at: https://cloud.google.com/appengine/docs/standard/python/reference/dispatch-yaml
I'm trying to write a VSCode extension where users could log into Google AppEngine with a google account, and I need to get their SACSID cookie to make appengine requests.
So I'm opening a browser window at
https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttp://localhost:3000/
(generated by google.appengine.api.users.create_login_url)
The user logs in and is redirected to my local webserver at
localhost:3000/_ah/conflogin/?state={state}
Now I try to forward the request to my AppEngine app (since it knows how to decode the state parameter), so I do a request to
https://my-app.appspot.com/_ah/conflogin/?state={state}
basically just replacing localhost with the actual app.
but it doesn't work, presumably because the domain is different. I assume this is on purpose, for security.
Is there any way I can make this work ?
Not ideal, but the only solution I've found is to have an endpoint on my GAE instance that does the redirection. Then I can set that as the continue url, when I'm starting the authentication process
https://accounts.google.com/ServiceLogin?service=ah&passive=true&continue=https://appengine.google.com/_ah/conflogin%3Fcontinue%3Dhttps://my-app.appspot.com/redirect?to=http://localhost:3000
I think you should center the attention on the protocols you are using, since it’s known that the cookie name is based on the http protocol (HTTP : ACSID, HTTPS:SACSID), and that’s the security perspective till this point for me.
Having the error you are facing now would be helpful to understand the problem better. Also, how are you performing the call to the API and the code you are using would be helpful too.
I have this:
- url: "awesome.com/*"
service: awesome
- url: "www.awesome.com/*"
service: awesome
Is possible to do this? to achieve same as above?
- url: "*.awesome.com/*"
service: awesome
No, what that last option you mentioned would do is map all subdomains of awesome.com to the service awesome, as you can see in this example corresponding to mapping subdomains in the documentation.
Here you have more information about mapping custom domains.
Yes, it's possible to do that. But it won't be equivalent with what you have now:
it won't match your top-level domain awesome.com which is matched by your current 1st rule
it'll match any <blah>.awesome.com subdomain, your current set of rules only matches the www.awesome.com subdomain
If indeed you want to send requests for both the full domain as well as all its subdomains to the awesome service you can achieve that simply by the custom domain mapping/config itself (which you need to do explicitly for the domain and each subdomain anyways), no need for a dispatch file.
Note that you'd still need to deploy a default service, see Why do I need to deploy a "default" app before I can deploy multiple services in GAE?. Might as well just let the awesome service be the default one in this case, less confusing and less room for trouble IMHO.
I have taken the basic python 3 tutorial website on flask from this google cloud tutorial and I am able to set this up and the website works just fine.
In addition , I also wanted to run a python script which runs everyday to collect some data, but the cron job just doesn't work. I also added login: admin to restrict anyone to directly use that url
cron.yaml
cron:
- description: test dispatch vs target
url: /cronapp
schedule: every 5 hours
app.yaml
runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app
runtime_config:
python_version: 3
handlers:
- url: /cronapp
script: cronapp.py
login: admin
I am calling this as http://myproject.appspot.com/cronapp also doesn't work and returns a 404.
what am I doing wrong ? any help is appreciated
Your app.yaml file is mixing up the standard environment Handlers element into a flexible environment configuration, so it is probably ignored. You can probably see the cron requests in the app's logs in the developer console (likely with errors, though).
You need to add a handler for /cronapp inside your app code, not in app.yaml. Not entirely sure how you do that (I'm still using only standard environment), it depends on your app and/or its framework. Take a look at the Hello World code review for a flask example.
Update:
I may not be entirely correct, I based my answer on documentation but I just noticed some inconsistencies (I sent some documentation feedback to Google for it).
The flexible environment Securing URLs for cron (which appears mostly copied from the standard environment equivalent) mentions a couple of solutions:
one indeed based on the login: admin option to handler:
You can restrict a URL by adding login: admin to the handler
configuration section in app.yaml. For more information see
Securing URLs
But handler is not mentioned in the Configuring your App with app.yaml and the Securing URLs is pointing to an inexistent tag. So I'm not sure if this is indeed working or not.
the second one is based on the X-Appengine-Cron header (same as in the standard environment):
Requests from the Cron Service will also contain a HTTP header:
X-Appengine-Cron: true
The X-Appengine-Cron header is set internally by Google App Engine.
If your request handler finds this header it can trust that the
request is a cron request. If the header is present in an external
user request to your app, it is stripped, except for requests from
logged in administrators of the application, who are allowed to set
the header for testing purposes.
But in Removed headers it is mentioned that:
In addition, some selected headers that match the following pattern
are removed from the request:
X-Appengine-*
It's unclear if this extends to X-Appengine-Cron or not. It's worth a try. This is my check in the (standard env, webapp2-based) cron handler code:
if self.request.headers.get('X-AppEngine-Cron') is None:
self.abort(403) # HTTPForbidden
I am trying to get a custom domain to work with Google App Engine 1.9.7 without SSL
I have done all the prerequisites;
Domain is verified with the proper TXT records.
Domain is configured in the GAE Cloud Console with the proper subdomain www.
Application is deployed the appspot.com domain and works.
But when I try to got to http://www.customdomain.com it immediately redirects to https://www.customdomain.com and I get the following error:
net::ERR_SSL_PROTOCOL_ERROR
I know that for SSL I need to set up a certificate.
I don't have any of my webapp modules configured to be secure.
I don't want SSL right now, I don't need it right now.
I found this little nugget after reading the instructions again and again:
It's okay for multiple domains and subdomains to point to the same
application. You can design your app to treat them all the same or
handle each one in a different way.
This is exactly what I want to do but I can't find any information on how to actually do this?
How do I get it to stop redirecting to the http to https?
I ran into the same problem. You say "I don't have any of my webapp modules configured to be secure." If that's the case, sorry, can't help you.
Otherwise the most likely cause for your problem would be: A "secure: always" flag for the respective handler in your app.yaml in the handlers section. Like so:
handlers:
- url: /*
secure: always
Remove the line with the "secure: always". Details in the official Google docs here (table item "secure").
How to run into this problem? I ran into it, because I copied the app.yaml from one of my other apps that didn't need to run on a custom domain, yet needed the SSL always.
For a Django/Python GAE app, by the way, the same problem is caused like this:
handlers:
- url: /.*
script: google.appengine.ext.django.main.app
secure: always
Same answer here: Remove or change the "secure" line. Python version just tested as described. Always works on the appspot.com domain, only without secure flag on a custom domain.
Just pointing out the above, as other people might run into this problem and come to this threat for help.
What I had to do was to shut down all instances and remove all versions, then do a fresh deployment from scratch, then I stopped having this problem.