-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRestfulHandler.py
executable file
·183 lines (137 loc) · 6.65 KB
/
RestfulHandler.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import webapp2
from google.appengine.ext import db
from decorators import httpCode_loginRequired
from git_submodules.gae_json_model_converter.jsonUtil import modelListToJson
from HTTPExceptions import HTTP400, HTTP403, HTTP404, HTTP415
import logging
def noValidation(object): return True
def generateHandler(Model, createValidator = noValidation, updateValidator = noValidation):
class GenericHandler(webapp2.RequestHandler):
@httpCode_loginRequired
def get(self, key=None):
gql = self.request.get("filter")
try:
if key:
self.response.out.write(Model.get(key).toJson())
else:
if gql:
instances = Model.gql(gql)
else:
instances = Model.all()
self.response.out.write(modelListToJson(instances))
self.response.headers['Content-Type'] = 'application/json'
except KeyError as e:
raise HTTP404(e)
@httpCode_loginRequired
def put(self, key): #update
if not key:
raise HTTP404("You can't update an instance if you don't put the identifier in the URL! Use POST for creating!")
onlyAllowJson(self.request)
try:
instance = Model.fromJson(self.request.body)
except KeyError as e:
raise HTTP404(e)
if not instance.is_saved():
raise HTTP400("You tried to update a object that has no identifier in the object, if this is a new object use POST!")
if unicode(instance.key()) != key:
raise HTTP403("JSON identifier in the object don't match the one in the URL!")
updateValidator(instance)
instance.put()
self.response.out.write(instance.toJson())
self.response.headers['Content-Type'] = 'application/json'
@httpCode_loginRequired
def post(self, key=None): # create
if key:
raise HTTP404("You can't create a new instance on an existing instance url! Use PUT for updating!")
onlyAllowJson(self.request)
instance = Model.fromJson(self.request.body)
createValidator(instance)
instance.put()
self.response.out.write(instance.toJson())
self.response.headers['Content-Type'] = 'application/json'
@httpCode_loginRequired
def delete(self, key):
if not key:
raise HTTP404("You need to supply the key you want to delete in the url!")
try:
instance = Model.get(key)
except KeyError as e:
raise HTTP404(e)
try:
instance.delete()
self.response.out.write('Deleted "%s"!' % instance.key())
except Exception, e:
errorMsg = 'There was a problem deleting %s' % key
logging.error(errorMsg)
raise Exception(e, errorMsg)
return GenericHandler
def generateChildHandler(Model, createValidator = noValidation, updateValidator = noValidation):
class GenericChildHandler(webapp2.RequestHandler):
@httpCode_loginRequired
def get(self, parentKey, childKey=None):
if not existInDB(parentKey):
raise HTTP404('Could not find the parentKey from the URL in the database')
try:
if childKey:
self.response.out.write(Model.get(childKey).toJson())
else:
childInstances = Model.allByParentReference(parentKey)
self.response.out.write(modelListToJson(childInstances))
self.response.headers['Content-Type'] = 'application/json'
except KeyError as e:
raise HTTP404(e)
@httpCode_loginRequired
def put(self, parentKey, childKey): #update
if not existInDB(parentKey):
raise HTTP404('Could not find the parentKey from the URL in the database')
if not childKey:
raise HTTP404("You can't update an instance if you don't put the identifier in the URL! Use POST for creating!")
onlyAllowJson(self.request)
try:
instance = Model.fromJson(self.request.body)
except KeyError as e:
raise HTTP404(e)
if not instance.is_saved():
raise HTTP400("You tried to update a object that has no identifier in the object, if this is a new object use POST!")
if unicode(instance.key()) != childKey:
raise HTTP403("JSON identifier in the object don't match the one in the URL!")
updateValidator(instance)
instance.put()
self.response.out.write(instance.toJson())
self.response.headers['Content-Type'] = 'application/json'
@httpCode_loginRequired
def post(self, parentKey, childKey=None): # create
if not existInDB(parentKey):
raise HTTP404('Could not find the parentKey from the URL in the database')
if childKey:
raise HTTP404("You can't create a new instance on an existing instance url! Use PUT for updating!")
onlyAllowJson(self.request)
instance = Model.fromJson(self.request.body)
instance.setParentReference(db.Key(parentKey))
createValidator(instance)
instance.put()
self.response.out.write(instance.toJson())
self.response.headers['Content-Type'] = 'application/json'
@httpCode_loginRequired
def delete(self, parentKey, childKey):
if not existInDB(parentKey):
raise HTTP404('Could not find the parentKey from the URL in the database')
if not childKey:
raise HTTP404("You need to supply the childKey you want to delete in the url!")
try:
instance = Model.get(childKey)
except KeyError as e:
raise HTTP404(e)
try:
instance.delete()
self.response.out.write('Deleted "%s"!' % instance.key())
except Exception, e:
errorMsg = 'There was a problem deleting %s' % childKey
logging.error(errorMsg)
raise Exception(e, errorMsg)
return GenericChildHandler
def existInDB(keyString):
return db.Query().filter('__key__ =', db.Key(keyString)).fetch(1) != None
def onlyAllowJson(request):
if 'application/json' not in request.headers['Content-Type'].lower():
raise HTTP415('Only Content-Type allowed is application/json!')