Why can't api method names contain underscores? - google-app-engine

My method names get translated from some_method to apiname.resource.somemethod and gapi.client.apiname.resource.somemethod. Example:
#endpoints.method(messages.VoidMessage, messages.VoidMessage,
name='resource.some_method', path='resource/some_method' )
def resource_some_method(self, request):
pass
I've also tested by naming a method with a few underscores in between.
Can this be stopped?

No. Google's API Infrastructure has strict naming guidelines and these are "enforced" by the SDK code. When deploying your application, your API definition is translated into an API configuration file which is sent of to Google's API Infrastructure to spin up a Discovery-based API of your very own.
Before creating this API config, these names are parsed by the endpoints.message_parser library (called from endpoints.api_config) to make sure your names adhere to the specification. In particular:
split_name = re.split(r'[^0-9a-zA-Z]', name)
normalized = ''.join(
part[0].upper() + part[1:] for part in split_name if part)
You are free to circumvent this code and generate your own API configuration, but the API deployment will fail as those names will be rejected by Google's API Infrastructure when you deploy.

Related

Are there environment variables available to an Alexa Hosted Skill?

I have written an Alexa hosted skill, which I would like to open source as a friend would like to join me in working on it. It uses Googles Geocoding Api, which relies on an API key. Currently, this API key sits In my python source code:
...
import logging
GOOGLE_API_KEY = "KEY"
GOOGLE_GEOCODE_API_PATH = "https://maps.googleapis.com/maps/api/geocode/json?"
def get_lat_lon(address):
...
I want to upload my source code to GitHub (preferably public), whilst still hosting the application (ultimately a lambda function) using Alexa Hosting, which is eases up a lot of the infrastructure. Is there any way to define environment variables for an Alexa hosted application, so that my private API key is hidden?
This is a suggestion. Store your API key on dynamoDB and fetch whenever required. You will need to write an extra piece of code that reads from dynamoDB using boto3 library and then store the key on your variable.
import logging
GOOGLE_API_KEY = get_apikey_db()
GOOGLE_GEOCODE_API_PATH = "https://maps.googleapis.com/maps/api/geocode/json?"
def get_apikey_db():
#read from db here
def get_lat_lon(address):
...
I hope this solves your problem.

How to use external api access tokens without exposing them to the user?

Sorry if this might be a bit of a trivial question, but I wanna be sure and couldn't exactly find a definitive answer online.
I am writing a small app that uses Mapbox, and I am using react-map-gl for it. They require the access token on the client side, so they suggest using an environment variable. My question is would it be okay to simply create a .env file in the front-end folder and put the variable there?
Thanks!
You can't get away from revealing API keys on the front end. If someone wants to dig around in your source code, they will find them.
However, you should always configure any API key that is visible on the Internet to be restricted to specific referrers, i.e. the domain of your website.
Usually this is done during creation of an API key through your provider's dashboard.
For Mapbox, you can read the documentation on restricting API tokens here. It states:
You can make your access tokens for web maps more secure by adding URL restrictions. When you add a URL restriction to a token, that token will only work for requests that originate from the URLs you specify. Tokens without restrictions will work for requests originating from any URL.
(emphasis my own)
They require the access token on the client side, so they suggest using an environment variable. My question is would it be okay to simply create a .env file in the front-end folder and put the variable there?
There are two reasons one uses environment variables in front-end development:
As a convenience, to keep environment-specific configuration removed from source code.
To keep sensitive information out of source code. You shouldn't commit API tokens or other similarly sensitive details to your version control.
Using environment variables in front-end code will not to keep their values secret from the end user. Whatever the value of an environment variable is at build time will be visible in the compiled output.

Cloud Endpoints and App Engine

I've just started on Google Cloud and I'm creating an iOS app to interact with Google Cloud services via a mobile backend. I'm using Python to write the backend for App Engine. I've gone through the tutorials in creating an API based on endpoints - but I have a question.
Do I have to create a Cloud Endpoints API, and then an app on App Engine? Basically, I want to be able to register accounts on my iOS app, call an API which then makes use of Google Datastore to store the account details. From looking at the tutorials (both the cloud endpoints one and then the guestbook one), am I meant to expose Google Datastore, cloud storage etc. within the endpoints api? Or does that link into another app where that is all done?
Sorry if this sounds a bit silly, but I just want to make sure!
Thanks in advance.
In a nutshell, your Cloud Endpoints API is your application. Some of the documentation regarding Cloud Endpoints can be a bit confusing (or vague), but on the server side it's essentially a bunch of Python decorators or Java annotations that allow you to expose your application logic as a REST API.
I find the Java implementation of Cloud Endpoints more intuitive than the Python one, which requires a bit more work to (de-)serialise your objects. You could look at endpoints_proto_datastore.ndb.EndpointsModel which might take some of the boilerplate stuff out of the equation (defining messages).
Essentially, when you write your API, each endpoint maps to a python function. Inside that function you can do what you like, but typically it will be either:
Deserialise your POSTed JSON, validate it, and write some entities to Datastore (or Cloud SQL, BigTable, wherever).
Read one or more entities from Datastore and serialize them to JSON and return them to the client.
For example, you might define your API (the whole collection of endpoint functions) as
#endpoints.api(name='cafeApi', version='v1', description='Cafe API', audiences=[endpoints.API_EXPLORER_CLIENT_ID])
class CafeApi(remote.Service):
# endpoints here
For example, you might have an endpoint to get nearby cafes:
#endpoints.method(GEO_RESOURCE, CafeListResponse, path='cafes/nearby', http_method='GET', name='cafes.nearby')
def get_nearby_cafes(self, request):
"""Get cafes close to specified lat,long"""
cafes = list()
for c in search.get_nearby_cafes(request.lat, request.lon):
cafes.append(c.response_message())
return CafeListResponse(cafes=cafes)
A couple of things to highlight here. With the Python Endpoints implementation, you need to define your resource and message classes - these are used to encapsulate request data and response bodies.
So, in the above example, GEO_RESOURCE encapsulates the fields required to make a GeoPoint (so we can search by location using Search API, but you might just search Datastore for Cafes with a 5-star rating):
GEO_RESOURCE = endpoints.ResourceContainer(
message_types.VoidMessage,
lat=messages.FloatField(1, required=True),
lon=messages.FloatField(2, required=True)
)
and the CafeListResponse would just encapsulate a list of CafeResponse objects (with Cloud Endpoints you return a single object):
class CafeListResponse(messages.Message):
locations = messages.MessageField(CafeResponse, 1, required=False, repeated=True)
where the CafeResponse is the message that defines how you want your objects (typically Datastore entities) serialised by your API. e.g.,
class LocationResponse(messages.Message):
id = messages.StringField(1, required=False)
coordinates = messages.MessageField(GeoMessage, 3, required=True)
name = messages.StringField(4, required=False)
With that endpoint signature, you can access it via an HTTP GET at /cafeApi/v1/cafes/nearby?lat=...&lon=... or via, say, the Javascript API client with `cafeApi.cafes.nearby(...).
Personally, I found Flask a bit more flexible with working with Python to create a REST API.

Apex only for force.com hosted apps?

Is Apex only permitted on “native” applications that are hosted on force.com?
Or is Apex also available for external applications to hit the “Open APIs” such as REST API and Bulk API?
I think part of my confusion lies in how the term “Rest API” is used in various documents. In other parts of the software world, REST is usually means an HTTP based protocol to exchange data across different domains (and with certain formats, etc ). However, I think Rest API in sales force might SOMETIMES refer to an optional means for native apps to retrieve salesforce data from within force.com. Is that correct?
Not sure I understand your question...
Apex can be used "internally" in:
database triggers,
classes
Visualforce controllers that follow MVC pattern,
logic that parses incoming emails and for example makes Case or Lead records out of them,
asynchronous jobs that can be scheduled to recalculate some important stuff every night
and you can have utility classes for code reuse across these
A "kind of internal" would be to use the "Execute Anonymous" mechanism that lets you fire one-off code snippets against environment. Useful for prototyping of new classes, data fixes etc. You can do it for example in Eclipse IDE or the Developer Console (upper right corner next to your name).
And last but not least - "external" usage.
Apex code can be exposed as webservice and called by PHP, .NET, Java, even JavaScript applications. It's a good choice when:
you want to reuse same piece of logic for example on your own Visualforce page as well as in some mobile application that would be passing couple strings around or a simple JSON object
beats having to reimplement the logic in every new app and maintaining that afterwards
imagine insertion of Account and Contact in one go - your mobile device would have to implement some transaction control and delete the Acc if the Contact failed to load. Messy. And would waste more API calls (insert acc, insert con, ooops, delete acc). With a method exposed as webservice you could accept both parameters into your Apex code, do your magic and well, if it fails - it's all in one transaction so SF will roll it back for you.
There are 2 main methods:
SOAP API primarily uses global methods marked with webservice keyword. Easiest way for other applications to start calling these is to extract from SF and "consume" so-called "enterprise WSDL" file. It's a giant XML file that can be parsed in your .NET app to generate code that will help you write code you're familiar with. These generated classes will construct the XML message for you, send it, process the response (throw your own exceptions if SF has sent an error message) and so on.
Very simple example:
global class MyWebService {
webService static Id makeContact(String lastName, Account a) {
Contact c = new Contact(lastName = 'Weissman', AccountId = a.Id);
insert c;
return c.id;
}
}
REST API allows you to do similar things but you need to use correct HTTP verbs ("PUT" is best for inserts, "PATCH" for updates", "DELETE" and so on).
You can read more about them in the REST API guide: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#CSHID=apex_rest_methods.htm|StartTopic=Content%2Fapex_rest_methods.htm|SkinName=webhelp

GWT: Where (how) to define POJOs to make em available for client and server? (and to use datastore on serverside)

I try to get an application running which should interact with a server via RPC (JDO in Google DataStore). So I defined a persistent POJO on the server-side to get it put in the datastore via the PersistenceManager (as shown in the gwt rpc tuts). Everything works fine. But I am not able to receive the callback POJO on the client side because the POJO is only defined on server-side. How can I realize it, that the client knows that kind of object??
(sry for my bad english)
Lars
Put your POJOs in a separate package/directory (e.g. com.example.common) and then add source declaration to your GWT module descriptor (xyz.gwt.xml):
<source path="common"/> //relative to your xyz.gwt.xml location
GWT compiler will then also compile POJOs and they will be seen by your other GWT code.
Edited:
#Lars - now I understand your problem. As I see it you have several options:
If possible use Objectify instead of JDO. Objectify uses pure POJOs and they play nicely with GWT. I use this in my projects. One nice thing that Objectify gives you is #PostLoad & # PrePersist on methods to run some code before/after POJOs are loaded/saved to datastore. I use this to handle serialization of GeoPoint for instance.
Use JDO and make copies of your domain classes. This is a pain but it would work. Use 'transient' java keyword in your server JDO classes to exclude fields you do not want to RPC.
Edit #2: There is a third option that you might prefer:
Create "fake" JDO annotation classes using super-sourcing. This is a common technique to replace classes with a GWT version. Described here: http://fredsa.allen-sauer.com/2009/04/1st-look-at-app-engine-using-jdo.html
You can use DTO(stackoverflow, moar) for transferring data to client.
Basic sample here (method getTenLatestEntries() in your case).
Or you can use some third-party libraries like objectify and stop worry about making DTO`s.

Resources