SkillAgentSearch skills...

Tailbone

Automatic RESTful backend for AppEngine

Install / Use

/learn @dataarts/Tailbone
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Tailbone Tailbone - Restful AppEngine

TL;DR

Install helper and dependencies

brew install google-app-engine go
go get github.com/doug/tailbone-generator/tailbone

Your new project

mkdir myproject
cd myproject
git init
tailbone init
tailbone serve
open localhost:8080
# <Ctrl-C> to stop local server
tailbone deploy master

Alternatives

A lot of the use cases I originally used tailbone for, a simple javascript based datastore, now have some great alternatives available. Wanted to give people information about https://www.firebase.com/ which is great and takes care of a lot of the things tailbone originally had to do.

Posting an alternative created some confusion, I'm still supporting Tailbone, but honestly at this point I don't really know how and if this library is being used. If you have used it and have stories of it being helpful even for something like prototyping an idea, please send them to tailbone.stories@gmail.com. That would really help me understand how this project is being used in the wild. Thanks!

Preamble

App Engine is cheap, fast, and awesome. Using it for the first time is sometimes…well…different. There are tons of frameworks like Django or others out there that work with App Engine, but these days we write almost all our applications in JavaScript with AngularJS or Backbone.js, we just need a simple backend to do its part. The App Engine server side APIs are great and for more complex things we recommend you learn them and use them. All this hopes to do is ease that barrier of use and get people writing their apps faster without worrying about their backend code. That said, writing more code on your backend is great if you are up to it, we can’t recommend Go enough for doing that, it's a wonderful language.

Anyway, this was written in spare time to fill a need and hopefully others find it useful too. It provides a simple RESTful backend setup for App Engine so you can write your apps in JavaScript via frameworks like AngularJS, Backbone, etc. and not have to touch any App Engine code. Or just using plain JavaScript and your own xhr calls. All your static resources are automatically served from client/app. App Engine is great at static serving and if you turn on PageSpeed on App Engine you get automatic optimization of your images and scripts, as well as other goodies all for free. It even supports large file uploads and serving via the Google Blobstore.

Guiding Principles

  • Do as little as possible server side, if it can be done on the client do it there.
  • Be as modular as possible so people can mix and match how they choose.
  • Only need to edit the app.yaml and appengine_config.py.
  • Should work out of the box how most people plan to use it.
  • Start with loose security, but be able to harden as you approach launch.
  • Be backend implementation agnostic, whether it is Go or Python or something else have a unified javascript interface.

Style Guide

Status

This is a side project made out of past experiences. That being said there are a few rough edges. Also working on a Go branch with the same api. If you want to contribute please add a test for any fix or feature before you file a pull request.

Getting Started

Tailbone utility helper:

  • Install tailbone

      brew install google-app-engine go
      go get github.com/doug/tailbone-generator/tailbone
    
  • Initialize a new tailbone project

      mkdir myproject
      cd myproject
      git init
      tailbone init
    
  • Start the dev server

      tailbone serve
      open localhost:8080
    
  • Deploy to app engine {version} is your own version name, e.g. 'master'

      tailbone deploy {version}
    

Manual steps to get started:

  • First, make sure you have the Google Cloud SDK for Python. Note, tailbone uses the Python 2.7 version so make sure your default python is at least 2.7.

  • Second, create a folder and git repo for your new project

      mkdir myproject
      cd myproject
      git init 
    
  • Third, add tailbone as a submodule to your project

      git submodule add https://github.com/dataarts/tailbone
      git submodule update --init --recursive
    
  • Third, create your app in any js framework or static html you want. As well as copy the app.yaml from the tailbone template.

      cp tailbone/app.template.yaml app.yaml
      mkdir app
      echo "<html><body>hello world</body></html>" > app/index.html
    
  • Lastly, start the server like a normal app engine app, but remember to do so from the tailbone directory.

      dev_appserver.py tailbone
      open http://localhost:8080
    

N.B: For you javascript development we recommend two things yeoman for bootstrapping and installing js libraries and angularjs for your MVC javascript application framework.

Modules

restful

Resources:

POST /api/{modelname}/
  Creates an object.

PUT or POST /api/{modelname}/{id}
  Updates an object, does a complete overwrite of the properites. This does not do a partial patch.

GET /api/{modelname}/{id}
  Get a specific object.

GET /api/{modelname}/?filter={propertyname==somevalue}&order={propertyname}&projection={propertyname1,propertyname2}
  Query a type.

Any GET request can take an optional list of properties to return, the query will use those to make a projection query which will only return those properties from the model. The format of the projection is a comma seperated list of properties: projection=propertyname1,propertyname2,propertyname3

Extending restful

In appengine_config.py in your root directory copied from tailbone/appengine_config.template.py

from google.appengine.ext import ndb
from tailbone.restful import ScopedModel
class MyModel(ScopedModel):
  stuff = ndb.FloatProperty()

tailbone_restful_DEFINED_MODELS = {"mymodel": MyModel}

This will restrict it so that only /api/mymodel will work.

If you want some user defined models plus everything else to work with whatever you give it you can also specify.

tailbone_restful_RESTRICT_TO_DEFINED_MODELS = False

N.B:

  • non indexed properties (such as large text or binary fields cannot be given as a projected property).
  • if owners is not listed as one of the projected properties then only public properties will be returned, because owners is needed to check ownership.

All restful models have three special properties:

  • Id: a public id for the model
  • owners: a private list of user ids which represent the owners for this model. By default this includes the user who created it.
  • viewers: a private list of user ids which represent the viewers for this model. By default this includes no one.

Special types include:

  • Geolocations: this occurs when you serialize your json data as {"lat": NUMBER, "lon": NUMBER}
  • Timestamps: this is in ISO 8601 DateTime format, this is the same style JSON supports when given a new Date() in ECMAScript 5.

To extend the loading of a date strings into native javascript Date format try something like:

var reISO = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/;

JSON._parse = JSON.parse;
JSON.parse = function(json) {
  return JSON._parse(json, function(key, value) {
    if (typeof value === 'string') {
      if (reISO.exec(value)) {
        return new Date(value);
      }
    }
    return value;
  });
};

Note: By including /tailbone.js this is automatically added.

Access Control:

Public private exposure of properties on a model is controlled by capitalization of the first letter, similar to Go. All models except for users have a private owners list which is just a list of user ids that can access and change the private variables of a model. This is prepopulated with the person who first creates this model. Only the signed in user can edit information on their users model. We thought about owners vs. editors to grant access rights like many other systems, but thought it out of scope for this first pass. This is about rapid prototyping. Also, if you need to make something only modifable by an admin prefix the property with admin or Admin.

$.ajax({
  url: "/api/todos/",
  method: "POST",
  data: {
    Text: "some public text",
    secret: "some secret that only owners can see",
    adminSecret: "only editable by a user who is an admin."
  }
})

Validation:

While you have to be authenticated, at the time of this writing you can still write anything to the datastore. This is fantastic for rapid development and changing schemas. However, you might want to be more strict once you deploy your application. In order to help, Tailbone does simple [regex validation](https://github.com/dataarts/tailbon

View on GitHub
GitHub Stars379
CategoryDevelopment
Updated7mo ago
Forks49

Languages

JavaScript

Security Score

87/100

Audited on Aug 23, 2025

No findings