Change endpoint for OpenFaaS function - openfaas

By default, functions deployed to OpenFaaS are available at one of the following endpoints:
http://$IP:8080/function/[function_name]
http://$IP:8080/async-function/[function_name]
How can I create an endpoint like the following?
http://[my_domain]/api/v1/[function_name]

How are you running OpenFaas? Assuming you are running in Kubernetes, you'll need an Ingress for your functions (so that they can be accessible outside your cluster).
There are a bunch of Ingress options:
Follow Alex's example here, this is end-to-end, which I found very helpful.
Use the openfaas ingress operator. More detail here.
Use an API Gateway like Kong, which is what I do. Kong is super flexible. This sample shows you how to use HMAC, but also has links to configuring JWT.
Use another supported OpenFaas Ingress; I have not tried these.
If you are not running in Kubernetes, let me know, and I'll see what I can do.

Related

AppEnginge dispatch.yaml url

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.

Can I point a domain at a google app engine service?

I have two very simple services set up (in python) on google app engine. I have a site which has been up for a while as the defualt service of my example project, and I just deployed another service, lets call it foo. I have dns forwarding working for the default service, so I can go to example.com (which I own in this hypothetical scenario) and see my default service. I can also go to foo.example.appspot.com and see my foo service, which works at the url.
I have also registered another domain, let's call it foo.com. What I want is for foo.com to use my foo.example.appspot.com service. To make matters trickier, foo.com has a bunch of sub-domains of it's own, so I need x.foo.com to go to my foo service as well (and even x.y.foo.com would be ideal, but if that is hard I can work around that one easily enough by just substituting out another character so it would be x-y.foo.com or something along those lines).
I'm pretty new to web dev (which is honestly a generous description for this simple project), but Iv'e spent a while reading and googling and haven't found a solution to this, so any advice would be helpful. My last resort would be to un-service-ify (if you will) the two services, and just bundle it all up into one big main.py which routes differently depending on the domain, and then point both domains at the default service. The big downside to this is that I already have everything working with services (which seems like a better approach).
I expect to get very few users so scaling isn't really an issue (though it's always interesting to learn about).
EDIT:
attempted to create a dispatch.yaml file to solve this as follows:
dispatch:
- url: "foo.com"
module: foo
- url: "*.foo.com"
module: foo
but when I run appcfg.py -A <project_id_here> update_dispatch . it says
Error parsing yaml file:
Unable to assign value 'foo.com' to attribute 'url':
invalid url 'foo.com'
in "./dispatch.yaml", line 3, column 10
Yes, it should be possible. I didn't actually use 2 different top-level domains, but the development console appears to be ready to accept a second one (I can't actually check as I don't own a 2nd domain). Follow the Adding a custom domain for your application procedure.
Pay special attention to the Wildcard mappings section - since your foo.com domain already has sub-domains in use you can't use wildcards at/above those sub-domains, you'll have to specify the desired subdomains.
The procedure only maps (sub)domains to the app as a whole, not to individual services/modules. You'll also have to use a dispatch file, to route the specific subdomains to the corresponding modules/services. You can find examples here: https://stackoverflow.com/a/32103486/4495081 and https://stackoverflow.com/a/34111170/4495081 (the last one has rules to allow the module to work on the custom domain, on appspot.com and on the local development server).
I got it to work following The links in the answer. My dispatch file wound up looking like this:
dispatch:
- url: "foo.com/*"
module: foo
- url: "*.foo.com/*"
module: foo

why i couldn't see any text in "http://crawlservice.appspot.com/?key=123456&url=http://mydomain.com#!article"?

Ok, i found this link https://code.google.com/p/gwt-platform/wiki/CrawlerSupport#Using_gwtp-crawler-service that explain how you can make your GWTP app crawlable.
I got some GWTP experience, but i know nothing about AppEngine.
Google said its "crawlservice.appspot.com" can parse any Ajax page. Now I have a page "http://mydomain.com#!article" that has an artice that was pulled from Database. Say that page has the text "this is my article". Now I open this link:
crawlservice.appspot.com/?key=123456&url=http://mydomain.com#!article, then i can see all javascript but I couldn't find the text "this is my article".
Why?
Now let check with a real life example
open this link https://groups.google.com/forum/#!topic/google-web-toolkit/Syi04ArKl4k & you will see the text "If i open that url in IE"
Now you open http://crawlservice.appspot.com/?key=123456&url=https://groups.google.com/forum/#!topic/google-web-toolkit/Syi04ArKl4k you can see all javascript but there is no text "If i open that url in IE",
Why is it?
SO if i use http://crawlservice.appspot.com/?key=123456&url=mydomain#!article then Can google crawler be able to see the text in mydomain#!article?
also why the key=123456, it means everyone can use this service? do we have our own key? does google limit the number of calls to their service?
Could you explain all these things?
Extra Info:
Christopher suggested me to use this example
https://github.com/ArcBees/GWTP-Samples/tree/master/gwtp-samples/gwtp-sample-crawler-service
However, I ran into other problem. My app is a pure GWTP, it doesn't have appengine-web.xml in WEB-INF. I have no idea what is appengine or GAE mean or what is Maven.
DO i need to register AppEngine?
My Appp may have a lot of traffic. Also I am using Godaddy VPS. I don't want to register App Engine since I have to pay for Google for extra traffic.
Everything in my GWTP App is ok right now except Crawler Function.
So if I don't use Google App Engine, then how can i build Crawler Function for GWTP?
I tried to use HTMLUnit for my app, but HTMLUnit doesn't work for GWTP (See details in here Why HTMLUnit always shows the HostPage no matter what url I type in (Crawlable GWT APP)? )
I believe you are not allowed to crawl Google Groups. Probably they are actively trying to prevent this, so you do not see the expected content.
There's a couple points I wish to elaborate on:
The Google Code documentation is no longer maintained. You should look on Github instead: https://github.com/ArcBees/GWTP/wiki/Crawler-Support
You shouldn't use http://crawlservice.appspot.com. This isn't a Google service, it's out of date and we may decide to delete it down the road. This only serves as a public example. You should create your own application on App Engine (https://appengine.google.com/)
There is a sample here (https://github.com/ArcBees/GWTP-Samples/tree/master/gwtp-samples/gwtp-sample-crawler-service) using GWTP's Crawler Service. You can basically copy-paste it. Just make sure you update the <application> tag in appengine-web.xml to the name of your application and use your own service key in CrawlerModule.
Finally, if your client uses GWTP and you followed the documentation, it will work. If you want to try it manually, you must encode the Query Parameters.
For example http://crawlservice.appspot.com/?key=123456&url=http://www.arcbees.com#!service will not work because the hash (everything including and after #) is not sent to the server.
On the other hand http://crawlservice.appspot.com/?key=123456&url=http%3A%2F%2Fwww.arcbees.com%2F%23!service will work.

How to work with authentication in local Google App Engine tests written in Go?

I'm building a webapp in Go that requires authentication. I'd like to run local tests using appengine/aetest that validate the authentication behavior. However, I do not see any way to create an aetest.Context with a dummy user. Am I missing something?
I had a similar issue with Python sdk. The gist of the solution is to bypass authentication when tests run locally.
You should have access to the [web] app object at the the test setup time - create a user object and save it into the app (or wherever your get_current_user() method will check).
This will let you unit test all application functions except authentication itself. For the later part you can deploy your latest changes as unpublished google app version, then test authentication and if all works - publish the version.
I've discovered some header values that seem to do the trick. appengine/user/user_dev.go has the following:
X-AppEngine-Internal-User-Email
X-AppEngine-Internal-User-Federated-Identity
X-AppEngine-Internal-User-Federated-Provider
X-AppEngine-Internal-User-Id
X-AppEngine-Internal-User-Is-Admin
If I set those headers on the Context's Request when doing in-process tests, things seem to work as expected. If I set the headers on a request that I create separately, things are less successful, since the 'user.Current()' call consults the Context's Request.
These headers might work in a Python environment as well.

How do I get an instance Id of app engine front server?

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

Resources