How to you prevent an attribute that you would like to remain hidden from begin returned? Put another way, how do you hide or filter out a db.model attribute?
There is not currently a way to filter fields (built in), although there is currently an enhancement request (with a patch) for such a feature, see Issue 22.
I'm using Angular.js and Angular expects to get back models without the outer hashmap containing the model name. For example, for the url /rest/Country/12345 Angular would expect {"countryName": "Russian Federation"} rather than the wrapped {"Country": {"countryName": "Russian Federation"}} that appengine-rest-server returns.
Is there a switch somewhere to return json without the outer hashmap wrapper containing the model name?
There are no switches to directly modify the returned data, however, you can specify a callback javascript wrapper method of your choice (see the JSON support section on the main page). this wrapper could, for instance, modify the data to fit your desired format.
Thanks. The only JSON documentation that I see on the main page refers to how to add a callback from the client side ("?callback=my_method"). Where in the appengine-rest-server code is the best place to try and strip off the outer hashmap to just return the actual entity details?
thats exactly the documentation to which i am referring. you could wrap your returned json object with a javascript method which removes the outer hashmap and just returns the details. the doc_to_output() method would be the most logical place to modify the rest server code.
Thanks. Taking out the outer hashmap in doc_to_output() was simple enough.
Next question, when I post back to update a model, I currently need to add the outer hashmap wrapper. Where would you recommend removing this requirement? For example: this code works well enough to update a model attribute.
well, considering you just modified the place where xml_to_json() was called, the reverse transformation would probably make sense where json_to_xml() is called...
Is there a recommended approach for adding the ability to call functions via this REST API? For instance, one approach would be to just treat methods on a model as you treat attributes. Then on the server side, if the fetch is for a method rather than an attribute, you call the method and return the result as json or xml.
well, the obvious first answer is that REST is "object" based, not "function" based. the second issue is that since these methods could return arbitrary data, the object->xml/json serialization code would have to be much more sophisticated. currently, the serialization code is based on the metadata available as part of the app engine Model API. third, you would have a similar problem with the function arguments (some layer of code would need to handle the string->type coercion), again without the benefit of any existing metadata. other than that, there's nothing stopping you from implementing something like that.
I am beginning to teach university students with appengine-rest-server. It is a simple and elegant approach that enables students to quickly prototype rest-based applications. I also like the way that access permissions can be incrementally added as the final application starts to come in to focus.
The recurring design problem that I’m beginning to see is how to consistently filter out or obfuscate attributes that should not be publicly viewable. These are usually attributes such as passwords and email addresses.
The first straightforward step is to replace the text for the attributes by overriding the Authorizer.filter_models() method. This approach is easy to add an also works for single entity fetches where ?key=<key>.
def filter_models(self, models):
for model in models:
if hasattr(model, 'email'):
model.email = 'PRIVATE'
return models
The next issue is that any obfuscated attributes will still be visible when a GET is done for a specific entity (/rest/MyModel?/12345). The simplest approach would be to just prevent reads for any models where all attributes for the model should not be visible, but this results is certain models no longer functioning consistently on the REST interface just because they have one attribute that needs to be hidden.
How can you obfuscate or remove specific attributes during reads by overriding Authorizer methods?
Controlling access to specific properties is an existing (much requested) feature request, see Issue 22. That issue contains a patch which adds some minimal support, although it is not a complete solution as i mentioned in the comments. unfortunately, i haven't hit on a good solution yet, which is why it isn't yet implemented.
Thanks. It is good to know that I'm hitting a common issue rather than missing something obvious. My initial approaches have not been as elegant as the rest of the design. Let me know if you have any interesting ideas and I will help to investigate.
It seems like the elegant approach would enable developers to simply add a parameter to exclude a property as each model is added. This exclude parameter would then prevent all reads and writes related to the listed properties. If the design gracefully ignores cases where the property does not exist on the model, then developers could exclude properties like password and email by default on all models and they would automatically be excluded when added to the model in the future.
Or, borrowing from the filtering approach used in queries (feq_property, fne_property), exclusions could just be added to the list of supported commands. This would be easy to teach, add, and read. #Example
When fetching the entities for a model, an array is returned as long as there are 2 or more entities for the model. If there are 0 or 1 entity, the rest interface returns a naked hashmap (dictionary). What is the best way to alter this behavior so that an array is always returned even if there are none or only one entity for the model?
Another question. Has any thought been given to how to format errors sent back to the client when a fetch or a put fails for some reason? If the errors were well formatted in JSON for example, the GUI or other calling client could better handle the common failures and provide additional feedback. Any recommendations on where to catch errors and return well-formatted error messages?
For what it's worth, we wrote a little sample showing how to run this API utilizing all the commands (GET/POST/PUT/DELETE) along with a little sample step by step exercise.
How do I get the response in JSON. A light example will be great... Thanks
What's missing from the description on the main project page?
How to you prevent an attribute that you would like to remain hidden from begin returned? Put another way, how do you hide or filter out a db.model attribute?
There is not currently a way to filter fields (built in), although there is currently an enhancement request (with a patch) for such a feature, see Issue 22.
I'm using Angular.js and Angular expects to get back models without the outer hashmap containing the model name. For example, for the url /rest/Country/12345 Angular would expect {"countryName": "Russian Federation"} rather than the wrapped {"Country": {"countryName": "Russian Federation"}} that appengine-rest-server returns.
Is there a switch somewhere to return json without the outer hashmap wrapper containing the model name?
There are no switches to directly modify the returned data, however, you can specify a callback javascript wrapper method of your choice (see the JSON support section on the main page). this wrapper could, for instance, modify the data to fit your desired format.
Thanks. The only JSON documentation that I see on the main page refers to how to add a callback from the client side ("?callback=my_method"). Where in the appengine-rest-server code is the best place to try and strip off the outer hashmap to just return the actual entity details?
thats exactly the documentation to which i am referring. you could wrap your returned json object with a javascript method which removes the outer hashmap and just returns the details. the doc_to_output() method would be the most logical place to modify the rest server code.
Thanks. Taking out the outer hashmap in doc_to_output() was simple enough.
Next question, when I post back to update a model, I currently need to add the outer hashmap wrapper. Where would you recommend removing this requirement? For example: this code works well enough to update a model attribute.
>>> url = 'http://127.0.0.1:8080/rest/App/agRkZWxpcgoLEgNBcHAY6QcM' >>> data = json.dumps({"App": {"name":"Chris"}}) >>> print urllib2.urlopen(urllib2.Request(url, data, {'Content-Type': 'application/json'})).read() agRkZWxpcgoLEgNBcHAY6QcM
But Angular will expect to be able to just post back data={"name":"Chris"}. So I need to remove the other hashmap expectations for posts.
well, considering you just modified the place where xml_to_json() was called, the reverse transformation would probably make sense where json_to_xml() is called...
Is there a recommended approach for adding the ability to call functions via this REST API? For instance, one approach would be to just treat methods on a model as you treat attributes. Then on the server side, if the fetch is for a method rather than an attribute, you call the method and return the result as json or xml.
#For example: /rest/Country/aghzaW5ncGF0aHIPCxIHQ291bnRyeRjHsjMM/get_ranking?maxRank=100¶m2=true
Would appreciate hearing any ideas or recommendations that you might have.
well, the obvious first answer is that REST is "object" based, not "function" based. the second issue is that since these methods could return arbitrary data, the object->xml/json serialization code would have to be much more sophisticated. currently, the serialization code is based on the metadata available as part of the app engine Model API. third, you would have a similar problem with the function arguments (some layer of code would need to handle the string->type coercion), again without the benefit of any existing metadata. other than that, there's nothing stopping you from implementing something like that.
I am beginning to teach university students with appengine-rest-server. It is a simple and elegant approach that enables students to quickly prototype rest-based applications. I also like the way that access permissions can be incrementally added as the final application starts to come in to focus.
The recurring design problem that I’m beginning to see is how to consistently filter out or obfuscate attributes that should not be publicly viewable. These are usually attributes such as passwords and email addresses.
The first straightforward step is to replace the text for the attributes by overriding the Authorizer.filter_models() method. This approach is easy to add an also works for single entity fetches where ?key=<key>.
The next issue is that any obfuscated attributes will still be visible when a GET is done for a specific entity (/rest/MyModel?/12345). The simplest approach would be to just prevent reads for any models where all attributes for the model should not be visible, but this results is certain models no longer functioning consistently on the REST interface just because they have one attribute that needs to be hidden.
How can you obfuscate or remove specific attributes during reads by overriding Authorizer methods?
Controlling access to specific properties is an existing (much requested) feature request, see Issue 22. That issue contains a patch which adds some minimal support, although it is not a complete solution as i mentioned in the comments. unfortunately, i haven't hit on a good solution yet, which is why it isn't yet implemented.
Thanks. It is good to know that I'm hitting a common issue rather than missing something obvious. My initial approaches have not been as elegant as the rest of the design. Let me know if you have any interesting ideas and I will help to investigate.
It seems like the elegant approach would enable developers to simply add a parameter to exclude a property as each model is added. This exclude parameter would then prevent all reads and writes related to the listed properties. If the design gracefully ignores cases where the property does not exist on the model, then developers could exclude properties like password and email by default on all models and they would automatically be excluded when added to the model in the future.
#Example rest.Dispatcher.add_models({
})Or, borrowing from the filtering approach used in queries (feq_property, fne_property), exclusions could just be added to the list of supported commands. This would be easy to teach, add, and read. #Example
When fetching the entities for a model, an array is returned as long as there are 2 or more entities for the model. If there are 0 or 1 entity, the rest interface returns a naked hashmap (dictionary). What is the best way to alter this behavior so that an array is always returned even if there are none or only one entity for the model?
https://code.google.com/p/appengine-rest-server/source/browse/trunk/src/main/python/rest/__init__.py#355
Thanks for the pointer to the code. Perfect.
Another question. Has any thought been given to how to format errors sent back to the client when a fetch or a put fails for some reason? If the errors were well formatted in JSON for example, the GUI or other calling client could better handle the common failures and provide additional feedback. Any recommendations on where to catch errors and return well-formatted error messages?
Would it be possible to see the source for the Boomi Demo? I'm a Python beginner, and seeing that project would really help me out:)
For what it's worth, we wrote a little sample showing how to run this API utilizing all the commands (GET/POST/PUT/DELETE) along with a little sample step by step exercise.
http://semi-legitimate.com/blog/item/restharness-the-rest-service-test-sandbox