And is there a way to send a request directly to that server?
Actually there is a way and it can be useful for pushing new data out to all instances of an application.
from google.appengine.api import modules
instance_id = modules.get_current_instance_id()
ref: GAE Modules Docs
For what purpose?
If you want to test different versions, you can use traffic splitting https://developers.google.com/appengine/docs/adminconsole/trafficsplitting
That is different versions though, and not a specific instance.
No there isn't.
Usually when someone asks something like this, they're headed in the wrong direction on app engine. Frontend servers get started and shutdown all the time. If you are designing anything that relies on a particular instance, you're doing it wrong. You need to design requests that work no matter what instance they hit.
Consider using backends if you must do that.
I use Python and a datetime stamp to identify an instance. This instance id is set by appengine_config.py. To signal other instances I use a flag in memcache, which is checked by the __init__ of my webapp2 request handler.
I use signals to other instances to flush the jinja environment and reload dynamic python code, because I could not find another way.
Here is an example of a memcache flag; signalling to reload all dynamic modules, which had been set by instance id: '2012-12-26 16:39:50.072000'
{ u'_all': { u'dyn_reloads_dt': datetime.datetime(2012, 12, 26, 16, 39, 59, 120000),
u'setter_instance': '2012-12-26 16:39:50.072000'}}
And I starred the feature request from : Ibrahim Arief
With the advent of Modules, you can get the current instance id in a more elegant way:
ModulesServiceFactory.getModulesService().getCurrentInstanceId()
Also, according to this doc, you can route requests specifically to a particular instance by using a URL like
http://instance.version.module.app-id.appspot.com
Note that you need to replace the dot with -dot- to suppress the SSL certificate warning your web client may be complaining about:
http://instance-dot-version-dot-module-dot-app-id.appspot.com
Related
My GAE app publishes some APIs in GCP and uses the following structure:
# Replace the following lines with client IDs obtained from the APIs
# Console or Cloud Console.
WEB_CLIENT_ID = '????????????.apps.googleusercontent.com'
ALLOWED_CLIENT_IDS = [WEB_CLIENT_ID, endpoints.API_EXPLORER_CLIENT_ID]
SCOPES = [endpoints.EMAIL_SCOPE]
#endpoints.api(name=API_NAME,
version=API_VERSION,
description='An API to manage languages',
allowed_client_ids=ALLOWED_CLIENT_IDS,
scopes=SCOPES)
My doubt is if someone picks this source code from my machine or GitHub project. He or she can access the APIs using the discovered web client id.
What’s the best practice in this case?
I acknowledge that the client can expose the ID and someone have access to it. But I believe that is another matter.
There are many ways you can do this. One way is to always check in a default value for the client ID, so that when people check out your code, they have to modify it to deploy it. You can also move the client ID to its own module and not check it in at all, and make the expectation that they create their own module with their own client ID. This avoids having a modified state for a checked in file all of the time.
The client ID itself is not sufficient information to generate a valid token. The cryptography involved will prevent such a person from accessing your API.
In my case we work with other companies which would consume our APIs along with our internal javascript client. I think we need to create a web client id for javascript client. But when exposing APIs externally, is it correct to generate new web client id per company? If so do we have to update clientid each time and redeploy application?
I'm following this documentation and in their example client ids are hardcoded, if I need to give access to new 3rd party users, then I need to generate new client id for them but I'd expect to not redeploy application.
Update: I've created a feature request as per #Alex's suggestion below.
Unfortunately the docs at https://cloud.google.com/appengine/docs/python/endpoints/auth very specifically say, and I quote,
Because the allowed_client_ids must be specified at build time, you
must rebuild and redeploy your API backend after adding or changing
any client IDs in the authorized list of allowed_client_ids or
audiences
so it appears that your perfectly-reasonable use case is very explicitly not covered at this time.
I recommend you visit said page and enter a feature request via the "Write Feedback" link (around the upper right corner of the page) as well as entering a feature request on the Endpoints component of the App Engine feature tracker, https://code.google.com/p/googleappengine/issues/list?can=2&q=component=Endpoints&colspec=ID%20Type%20Component%20Status%20Stars%20Summary%20Language%20Priority%20Owner%20Log -- we monitor both, but with different processes, so trying both is best.
Sorry to be a bearer of bad news. For now, it seems the only workaround is to distribute to the other companies one of a bunch of client ids generated in advance (you can only change the valid bunch when you re-deploy, sigh) and perhaps add some extra, app-layer authorization check of your own -- exactly the kind of work endpoints should be doing on your behalf:-(.
You can use an asterisk as the client ID, that will allow any client to call it without redeploying your API backend. Not sure if this is a documented feature or not, but it works (at least) with both Python and Java.
#Api(name = "myapi",
version = "v1",
scopes = {"https://www.googleapis.com/auth/userinfo.email"},
description = "My flashy API",
clientIds = {"*"})
public class MyAPI { ... }
I am calling a third party web service from app engine. This particular service is picky. I ran into an issue where calls would work fine for a while, then stop working, then start working again. I realized that if I manually stopped all instances in the admin console, that the calls would work again.
I setup a proxy to route the calls through that so I could see the headers and all detail. I think I have tracked the issue down to the following. After an instance has been up for a while (the app usually just needs 1 to 3 instances right now) app engine will start using the IP address of the destination as the value for the host header instead of the hostname. Well the service doesn't like that. Whether it should care is another matter.
So my question is, why does app engine use the ip address for the host header eventually instead of the hostname? And, of course, is there anything I can do about it? I know that I cannot set the host header, but maybe there is something else that can be done.
Thanks for any insight.
First, thank you for finding this behavior. We have had intermittent issues with urlfetch for a long time, and will try to detect if this is the issue.
One thing you could try is to target a specific instance/module:
http://instance.version.module.app-id.appspot.com
and cycle through the instances. If you just target the module, it will kill the instance after some inactivity. So, perhaps that would not trigger the GAE DNS shortcut.
Another trick would be to add a fake, random, query string after your url: ?foo=D7hfka67h. Perhaps that would prevent GAE from recognizing the repeat url, and trying to shortcut the DNS.
I have a model called "Category" in my app in GAE.
This model simply contains a name and it's parent category, and this won't be changed frequently after the website go online.
I'd like to know what is a better way to put these model instances in the beginning?
I now only know to execute (category.put()) in a webapp.RequestHandler by issuing a http request. But I suspect there is a proper way to do this.
Thanks!
You can use the remote API to connect to your datastore in a shell and add data as required.
Or, if it's a huge amount, you could think about using the bulk loader - but I suspect that the remote API will be more suitable.
I use httplib.HTTPConnection within my app. Do I really need to provide host parameter in httplib.HTTPConnection constructor? If so, why? (I mean, I know that it's a mandatory parameter, but I wonder if I could specify None or empty string) And is there any global constant in Google AppEngine and in development server which I can use within my app in order to omit explicitly defined host.
If you leave it out of the constructor, how will the other methods know where to send their messages?
The address/name of the server you're connecting to is the parameter for the HTTPConnection, the URI on that server is what goes into request.
From the python documentation (which is the basis for AppEngine)
h1 = httplib.HTTPConnection(host[, port[, strict[, timeout[, source_address]]]])
h1.request(method, url[, body[, headers]])
[edit]
Remember, it may not always be you who is responsible for this code. Also, why complicate things by including so much more information in the URI when you're (for example) making calls to numerous URI's on the same website?
[/edit]