Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
C
corepost
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Commits
Open sidebar
nexlab
corepost
Commits
89864450
Commit
89864450
authored
Mar 02, 2012
by
Jacek Furmankiewicz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
major change to enable custom routing to REST services from a single parent Resource
parent
39d43ed7
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
246 additions
and
88 deletions
+246
-88
__init__.py
corepost/__init__.py
+19
-0
routing.py
corepost/routing.py
+78
-43
arguments.py
corepost/test/arguments.py
+3
-3
filter_resource.py
corepost/test/filter_resource.py
+8
-7
home_resource.py
corepost/test/home_resource.py
+3
-5
multi_resource.py
corepost/test/multi_resource.py
+11
-16
rest_resource.py
corepost/test/rest_resource.py
+100
-0
utils.py
corepost/utils.py
+8
-0
web.py
corepost/web.py
+16
-14
No files found.
corepost/__init__.py
View file @
89864450
...
...
@@ -2,6 +2,25 @@
Common classes
'''
from
zope.interface
import
Interface
,
Attribute
#########################################################
#
# INTERFACES
#
#########################################################
class
IRestServiceContainer
(
Interface
):
"""An interface for all REST services that can be added within a root CorePost resource"""
services
=
Attribute
(
"All the REST services contained in this resource"
)
#########################################################
#
# CLASSES
#
#########################################################
class
Response
:
"""
Custom response object, can be returned instead of raw string response
...
...
corepost/routing.py
View file @
89864450
...
...
@@ -5,13 +5,13 @@ Created on 2011-10-03
Common routing classes, regardless of whether used in HTTP or multiprocess context
'''
from
collections
import
defaultdict
from
corepost
import
Response
from
corepost.enums
import
Http
,
HttpHeader
from
corepost.utils
import
getMandatoryArgumentNames
,
convertToJson
from
corepost.convert
import
convertForSerialization
,
generateXml
from
corepost.filters
import
IRequestFilter
,
IResponseFilter
from
corepost
import
Response
from
enums
import
MediaType
from
formencode
import
FancyValidator
,
Invalid
from
twisted.internet
import
reactor
,
defer
from
twisted.web.http
import
parse_qs
from
twisted.web.resource
import
Resource
...
...
@@ -19,6 +19,7 @@ from twisted.web.server import Site, NOT_DONE_YET
import
re
,
copy
,
exceptions
,
json
,
yaml
from
xml.etree
import
ElementTree
from
xml.etree.ElementTree
import
Element
from
zope.interface.verify
import
verifyObject
class
UrlRouter
:
''' Common class for containing info related to routing a request to a function '''
...
...
@@ -28,20 +29,21 @@ class UrlRouter:
__typeConverters
=
{
"int"
:
int
,
"float"
:
float
}
def
__init__
(
self
,
f
,
url
,
methods
,
accepts
,
produces
,
cache
):
self
.
__f
=
f
self
.
__url
=
url
self
.
__methods
=
methods
if
isinstance
(
methods
,
tuple
)
else
(
methods
,)
self
.
__accepts
=
accepts
if
isinstance
(
accepts
,
tuple
)
else
(
accepts
,)
self
.
__produces
=
produces
self
.
__cache
=
cache
self
.
__f
=
f
self
.
__argConverters
=
{}
# dict of arg names -> group index
self
.
__validators
=
{}
self
.
__mandatory
=
getMandatoryArgumentNames
(
f
)[
2
:]
def
compileMatcherForFullUrl
(
self
):
"""Compiles the regex matches once the URL has been updated to include the full path from the parent class"""
#parse URL into regex used for matching
m
=
UrlRouter
.
__urlMatcher
.
findall
(
url
)
self
.
__matchUrl
=
"^
%
s$"
%
url
m
=
UrlRouter
.
__urlMatcher
.
findall
(
self
.
url
)
self
.
__matchUrl
=
"^
%
s$"
%
self
.
url
for
match
in
m
:
if
len
(
match
[
0
])
==
0
:
# string
...
...
@@ -56,6 +58,7 @@ class UrlRouter:
self
.
__matcher
=
re
.
compile
(
self
.
__matchUrl
)
@
property
def
cache
(
self
):
'''Indicates if this URL should be cached or not'''
...
...
@@ -101,19 +104,31 @@ class UrlRouter:
if
arg
not
in
kwargs
:
raise
TypeError
(
"Missing mandatory argument '
%
s'"
%
arg
)
return
self
.
__f
(
instance
,
request
,
**
kwargs
)
def
__str__
(
self
):
return
"
%
s
%
s"
%
(
self
.
url
,
self
.
methods
)
class
UrlRouterInstance
():
"""Combines a UrlRouter with a class instance it should be executed against"""
def
__init__
(
self
,
clazz
,
urlRouter
):
self
.
clazz
=
clazz
self
.
urlRouter
=
urlRouter
def
__str__
(
self
):
return
self
.
urlRouter
.
url
class
CachedUrl
:
'''
Used for caching URLs that have been already routed once before. Avoids the overhead
of regex processing on every incoming call for commonly accessed REST URLs
'''
def
__init__
(
self
,
router
,
args
):
self
.
__
router
=
router
def
__init__
(
self
,
urlRouterInstance
,
args
):
self
.
__
urlRouterInstance
=
urlRouterInstance
self
.
__args
=
args
@
property
def
router
(
self
):
return
self
.
__
router
def
urlRouterInstance
(
self
):
return
self
.
__
urlRouterInstance
@
property
def
args
(
self
):
...
...
@@ -124,16 +139,16 @@ class RequestRouter:
Class that handles request->method routing functionality to any type of resource
'''
def
__init__
(
self
,
url
Container
,
schema
=
None
,
filters
=
()):
def
__init__
(
self
,
restService
Container
,
schema
=
None
,
filters
=
()):
'''
Constructor
'''
self
.
__urls
=
{
Http
.
GET
:
defaultdict
(
dict
),
Http
.
POST
:
defaultdict
(
dict
),
Http
.
PUT
:
defaultdict
(
dict
),
Http
.
DELETE
:
defaultdict
(
dict
)}
self
.
__cachedUrls
=
{
Http
.
GET
:
defaultdict
(
dict
),
Http
.
POST
:
defaultdict
(
dict
),
Http
.
PUT
:
defaultdict
(
dict
),
Http
.
DELETE
:
defaultdict
(
dict
)}
self
.
__
router
s
=
{}
self
.
__
urlRouterInstance
s
=
{}
self
.
__schema
=
schema
self
.
__registerRouters
(
url
Container
)
self
.
__urlContainer
=
url
Container
self
.
__registerRouters
(
restService
Container
)
self
.
__urlContainer
=
restService
Container
self
.
__requestFilters
=
[]
self
.
__responseFilters
=
[]
...
...
@@ -155,61 +170,80 @@ class RequestRouter:
def
path
(
self
):
return
self
.
__path
def
__registerRouters
(
self
,
url
Container
):
def
__registerRouters
(
self
,
restService
Container
):
"""Main method responsible for registering routers"""
from
types
import
FunctionType
for
_
,
func
in
urlContainer
.
__class__
.
__dict__
.
iteritems
():
if
type
(
func
)
==
FunctionType
and
hasattr
(
func
,
'corepostRequestRouter'
):
rq
=
func
.
corepostRequestRouter
for
method
in
rq
.
methods
:
for
accepts
in
rq
.
accepts
:
self
.
__urls
[
method
][
rq
.
url
][
accepts
]
=
rq
self
.
__routers
[
func
]
=
rq
# needed so that we cdan lookup the router for a specific function
def
route
(
self
,
url
,
methods
=
(
Http
.
GET
,),
accepts
=
MediaType
.
WILDCARD
,
produces
=
None
,
cache
=
True
):
'''Obsolete'''
raise
RuntimeError
(
"Do not @app.route() any more, as of 0.0.6 API has been re-designed around class methods, see docs and examples"
)
for
service
in
restServiceContainer
.
services
:
# check if the service has a root path defined, which is optional
rootPath
=
service
.
__class__
.
path
if
"path"
in
service
.
__class__
.
__dict__
else
""
for
key
in
service
.
__class__
.
__dict__
:
func
=
service
.
__class__
.
__dict__
[
key
]
# handle REST resources directly on the CorePost resource
if
type
(
func
)
==
FunctionType
and
hasattr
(
func
,
'corepostRequestRouter'
):
# if specified, add class path to each function's path
rq
=
func
.
corepostRequestRouter
rq
.
url
=
"
%
s
%
s"
%
(
rootPath
,
rq
.
url
)
# remove trailing '/' to standardize URLs
if
rq
.
url
!=
"/"
and
rq
.
url
[
-
1
]
==
"/"
:
rq
.
url
=
rq
.
url
[:
-
1
]
# now that the full URL is set, compile the matcher for it
rq
.
compileMatcherForFullUrl
()
for
method
in
rq
.
methods
:
for
accepts
in
rq
.
accepts
:
urlRouterInstance
=
UrlRouterInstance
(
service
,
rq
)
self
.
__urls
[
method
][
rq
.
url
][
accepts
]
=
urlRouterInstance
self
.
__urlRouterInstances
[
func
]
=
urlRouterInstance
# needed so that we can lookup the urlRouterInstance for a specific function
def
getResponse
(
self
,
request
):
"""Finds the appropriate
router
and dispatches the request to the registered function. Returns the appropriate Response object"""
"""Finds the appropriate
instance
and dispatches the request to the registered function. Returns the appropriate Response object"""
# see if already cached
response
=
None
try
:
if
len
(
self
.
__requestFilters
)
>
0
:
self
.
__filterRequests
(
request
)
# standardize URL and remove trailing "/" if necessary
standardized_postpath
=
request
.
postpath
if
(
request
.
postpath
[
-
1
]
!=
''
or
request
.
postpath
==
[
''
])
else
request
.
postpath
[:
-
1
]
path
=
'/'
+
'/'
.
join
(
standardized_postpath
)
path
=
'/'
+
'/'
.
join
(
request
.
postpath
)
contentType
=
MediaType
.
WILDCARD
if
HttpHeader
.
CONTENT_TYPE
not
in
request
.
received_headers
else
request
.
received_headers
[
HttpHeader
.
CONTENT_TYPE
]
url
router
,
pathargs
=
None
,
None
url
RouterInstance
,
pathargs
=
None
,
None
# fetch URL arguments <-> function from cache if hit at least once before
if
contentType
in
self
.
__cachedUrls
[
request
.
method
][
path
]:
cachedUrl
=
self
.
__cachedUrls
[
request
.
method
][
path
][
contentType
]
url
router
,
pathargs
=
cachedUrl
.
router
,
cachedUrl
.
args
url
RouterInstance
,
pathargs
=
cachedUrl
.
urlRouterInstance
,
cachedUrl
.
args
else
:
# first time this URL is called
router
=
None
instance
=
None
for
contentTypeFunctions
in
self
.
__urls
[
request
.
method
]
.
values
():
# go through all the URLs, pick up the ones matching by content type
# and then validate which ones match by path/argument to a particular UrlRouterInstance
for
contentTypeInstances
in
self
.
__urls
[
request
.
method
]
.
values
():
if
contentType
in
contentType
Function
s
:
if
contentType
in
contentType
Instance
s
:
# there is an exact function for this incoming content type
router
=
contentTypeFunction
s
[
contentType
]
elif
MediaType
.
WILDCARD
in
contentType
Function
s
:
instance
=
contentTypeInstance
s
[
contentType
]
elif
MediaType
.
WILDCARD
in
contentType
Instance
s
:
# fall back to any wildcard method
router
=
contentTypeFunction
s
[
MediaType
.
WILDCARD
]
instance
=
contentTypeInstance
s
[
MediaType
.
WILDCARD
]
if
router
!=
None
:
if
instance
!=
None
:
# see if the path arguments match up against any function @route definition
args
=
r
outer
.
getArguments
(
path
)
args
=
instance
.
urlR
outer
.
getArguments
(
path
)
if
args
!=
None
:
if
r
outer
.
cache
:
self
.
__cachedUrls
[
request
.
method
][
path
][
contentType
]
=
CachedUrl
(
router
,
args
)
url
router
,
pathargs
=
router
,
args
if
instance
.
urlR
outer
.
cache
:
self
.
__cachedUrls
[
request
.
method
][
path
][
contentType
]
=
CachedUrl
(
instance
,
args
)
url
RouterInstance
,
pathargs
=
instance
,
args
break
#actual call
if
url
router
!=
None
and
pathargs
!=
None
:
if
url
RouterInstance
!=
None
and
pathargs
!=
None
:
allargs
=
copy
.
deepcopy
(
pathargs
)
# handler for weird Twisted logic where PUT does not get form params
# see: http://twistedmatrix.com/pipermail/twisted-web/2007-March/003338.html
...
...
@@ -227,7 +261,8 @@ class RequestRouter:
try
:
# if POST/PUT, check if we need to automatically parse JSON
self
.
__parseRequestData
(
request
)
val
=
urlrouter
.
call
(
self
.
__urlContainer
,
request
,
**
allargs
)
urlRouter
=
urlRouterInstance
.
urlRouter
val
=
urlRouter
.
call
(
urlRouterInstance
.
clazz
,
request
,
**
allargs
)
#handle Deferreds natively
if
isinstance
(
val
,
defer
.
Deferred
):
...
...
corepost/test/arguments.py
View file @
89864450
...
...
@@ -3,7 +3,7 @@ Argument extraction tests
@author: jacekf
'''
from
corepost.web
import
CorePost
,
validate
,
route
from
corepost.web
import
RestServiceContainer
,
validate
,
route
from
corepost.enums
import
Http
from
formencode
import
Schema
,
validators
...
...
@@ -11,7 +11,7 @@ class TestSchema(Schema):
allow_extra_fields
=
True
childId
=
validators
.
Regex
(
regex
=
"^jacekf|test$"
)
class
ArgumentApp
(
CorePost
):
class
ArgumentApp
():
@
route
(
"/int/<int:intarg>/float/<float:floatarg>/string/<stringarg>"
,
Http
.
GET
)
def
test
(
self
,
request
,
intarg
,
floatarg
,
stringarg
,
**
kwargs
):
...
...
@@ -29,5 +29,5 @@ class ArgumentApp(CorePost):
return
"
%
s -
%
s -
%
s"
%
(
rootId
,
childId
,
kwargs
)
def
run_app_arguments
():
app
=
ArgumentApp
(
)
app
=
RestServiceContainer
((
ArgumentApp
(),)
)
app
.
run
(
8082
)
\ No newline at end of file
corepost/test/filter_resource.py
View file @
89864450
...
...
@@ -3,21 +3,21 @@ Server tests
@author: jacekf
'''
from
corepost.web
import
CorePost
,
route
from
corepost.web
import
RestServiceContainer
,
route
from
corepost.enums
import
Http
from
corepost.filters
import
IRequestFilter
,
IResponseFilter
import
zope.interface
from
zope.interface
import
implements
class
AddCustomHeaderFilter
():
"""Implements just a request filter"""
zope
.
interface
.
implements
(
IRequestFilter
)
implements
(
IRequestFilter
)
def
filterRequest
(
self
,
request
):
request
.
received_headers
[
"Custom-Header"
]
=
"Custom Header Value"
class
Change404to503Filter
():
"""Implements just a response filter that changes 404 to 503 statuses"""
zope
.
interface
.
implements
(
IResponseFilter
)
implements
(
IResponseFilter
)
def
filterResponse
(
self
,
request
,
response
):
if
response
.
code
==
404
:
...
...
@@ -25,7 +25,7 @@ class Change404to503Filter():
class
WrapAroundFilter
():
"""Implements both types of filters in one class"""
zope
.
interface
.
implements
(
IRequestFilter
,
IResponseFilter
)
implements
(
IRequestFilter
,
IResponseFilter
)
def
filterRequest
(
self
,
request
):
request
.
received_headers
[
"X-Wrap-Input"
]
=
"Input"
...
...
@@ -33,14 +33,15 @@ class WrapAroundFilter():
def
filterResponse
(
self
,
request
,
response
):
response
.
headers
[
"X-Wrap-Output"
]
=
"Output"
class
FilterApp
(
CorePost
):
class
FilterService
():
path
=
"/"
@
route
(
"/"
,
Http
.
GET
)
def
root
(
self
,
request
,
**
kwargs
):
return
request
.
received_headers
def
run_filter_app
():
app
=
FilterApp
(
filters
=
(
Change404to503Filter
(),
AddCustomHeaderFilter
(),
WrapAroundFilter
(),))
app
=
RestServiceContainer
(
services
=
(
FilterService
(),),
filters
=
(
Change404to503Filter
(),
AddCustomHeaderFilter
(),
WrapAroundFilter
(),))
app
.
run
(
8083
)
if
__name__
==
"__main__"
:
...
...
corepost/test/home_resource.py
View file @
89864450
...
...
@@ -3,17 +3,15 @@ Server tests
@author: jacekf
'''
from
corepost.web
import
CorePost
,
route
from
corepost.web
import
RestServiceContainer
,
route
from
corepost.enums
import
Http
,
MediaType
,
HttpHeader
from
twisted.internet
import
defer
from
xml.etree
import
ElementTree
from
UserDict
import
UserDict
import
json
,
yaml
class
HomeApp
(
CorePost
):
class
HomeApp
():
def
__init__
(
self
,
*
args
,
**
kwargs
):
CorePost
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
issue1
=
"issue 1"
@
route
(
"/"
,
Http
.
GET
)
...
...
@@ -117,7 +115,7 @@ class HomeApp(CorePost):
return
self
.
issue1
def
run_app_home
():
app
=
HomeApp
(
)
app
=
RestServiceContainer
((
HomeApp
(),)
)
app
.
run
()
if
__name__
==
"__main__"
:
...
...
corepost/test/multi_resource.py
View file @
89864450
'''
A
CorePost module1 that can be merged into the main CorePost
Resource
A
RestServiceContainer module1 that can be merged into the main RestServiceContainer
Resource
'''
from
corepost.web
import
CorePost
,
route
from
corepost.web
import
RestServiceContainer
,
route
from
corepost.enums
import
Http
from
twisted.web.resource
import
Resource
from
twisted.internet
import
reactor
from
twisted.web.server
import
Site
class
HomeApp
(
CorePost
):
class
HomeApp
():
@
route
(
"/"
)
def
home_root
(
self
,
request
,
**
kwargs
):
return
"HOME
%
s"
%
kwargs
class
Module1
(
CorePost
):
class
Module1
():
path
=
"/module1"
@
route
(
"/"
,
Http
.
GET
)
def
module1_get
(
self
,
request
,
**
kwargs
):
...
...
@@ -24,7 +22,8 @@ class Module1(CorePost):
def
module1e_sub
(
self
,
request
,
**
kwargs
):
return
request
.
path
class
Module2
(
CorePost
):
class
Module2
():
path
=
"/module2"
@
route
(
"/"
,
Http
.
GET
)
def
module2_get
(
self
,
request
,
**
kwargs
):
...
...
@@ -35,12 +34,8 @@ class Module2(CorePost):
return
request
.
path
def
run_app_multi
():
app
=
Resource
()
app
.
putChild
(
''
,
HomeApp
())
app
.
putChild
(
'module1'
,
Module1
())
app
.
putChild
(
'module2'
,
Module2
())
factory
=
Site
(
app
)
reactor
.
listenTCP
(
8081
,
factory
)
#@UndefinedVariable
reactor
.
run
()
#@UndefinedVariable
app
=
RestServiceContainer
((
HomeApp
(),
Module1
(),
Module2
()))
app
.
run
(
8081
)
if
__name__
==
"__main__"
:
run_app_multi
()
\ No newline at end of file
corepost/test/rest_resource.py
0 → 100644
View file @
89864450
'''
Server tests
@author: jacekf
'''
from
corepost
import
Response
from
corepost.web
import
RestServiceContainer
class
DB
():
"""Fake in-memory DB for testing"""
customers
=
{}
class
Customer
():
"""Represents customer entity"""
def
__init__
(
self
,
customerId
,
firstName
,
lastName
):
(
self
.
customerId
,
self
.
firstName
,
self
.
lastName
)
=
(
customerId
,
firstName
,
lastName
)
self
.
addresses
=
{}
class
CustomerAddress
():
"""Represents customer address entity"""
def
__init__
(
self
,
customer
,
streetNumber
,
streetName
,
stateCode
,
countryCode
):
(
self
.
customer
,
self
.
streetNumber
,
self
.
streetName
.
self
.
stateCode
,
self
.
countryCode
)
=
(
customer
,
streetNumber
,
streetName
,
stateCode
,
countryCode
)
class
CustomerRestService
():
path
=
"/customer"
def
getAll
(
self
,
request
):
return
DB
.
customers
def
get
(
self
,
request
,
customerId
):
return
DB
.
customers
[
customerId
]
if
customerId
in
DB
.
customers
else
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
post
(
self
,
request
,
customerId
,
firstName
,
lastName
):
if
customerId
in
DB
.
customers
:
return
Response
(
409
,
"Customer
%
s already exists"
%
customerId
)
else
:
DB
.
customers
[
customerId
]
=
Customer
(
customerId
,
firstName
,
lastName
)
return
Response
(
201
)
def
put
(
self
,
request
,
customerId
,
firstName
,
lastName
):
if
customerId
in
DB
.
customers
:
DB
.
customers
[
customerId
]
.
firstName
=
firstName
DB
.
customers
[
customerId
]
.
lastName
=
lastName
return
Response
(
200
)
else
:
return
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
delete
(
self
,
request
,
customerId
):
if
customerId
in
DB
.
customers
:
del
(
DB
.
customers
[
customerId
])
return
Response
(
200
)
else
:
return
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
deleteAll
(
self
,
request
):
DB
.
customers
.
clear
()
return
Response
(
200
)
class
CustomerAddressRestService
():
path
=
"/customer/<customerId>/address"
def
getAll
(
self
,
request
,
customerId
):
return
DB
.
customers
def
get
(
self
,
request
,
customerId
):
return
DB
.
customers
[
customerId
]
if
customerId
in
DB
.
customers
else
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
post
(
self
,
request
,
customerId
,
firstName
,
lastName
):
if
customerId
in
DB
.
customers
:
return
Response
(
409
,
"Customer
%
s already exists"
%
customerId
)
else
:
DB
.
customers
[
customerId
]
=
Customer
(
customerId
,
firstName
,
lastName
)
return
Response
(
201
)
def
put
(
self
,
request
,
customerId
,
firstName
,
lastName
):
if
customerId
in
DB
.
customers
:
DB
.
customers
[
customerId
]
.
firstName
=
firstName
DB
.
customers
[
customerId
]
.
lastName
=
lastName
return
Response
(
200
)
else
:
return
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
delete
(
self
,
request
,
customerId
):
if
customerId
in
DB
.
customers
:
del
(
DB
.
customers
[
customerId
])
return
Response
(
200
)
else
:
return
Response
(
404
,
"Customer
%
s not found"
%
customerId
)
def
deleteAll
(
self
,
request
):
DB
.
customers
.
clear
()
return
Response
(
200
)
def
run_rest_app
():
app
=
RestServiceContainer
(
restServices
=
(
CustomerRestService
(),))
app
.
run
(
8085
)
if
__name__
==
"__main__"
:
run_rest_app
()
\ No newline at end of file
corepost/utils.py
View file @
89864450
...
...
@@ -22,3 +22,11 @@ def convertToJson(obj):
return
json
.
dumps
(
obj
)
except
Exception
as
ex
:
raise
RuntimeError
(
str
(
ex
))
def
checkExpectedInterfaces
(
objects
,
expectedInterface
):
"""Verifies that all the objects implement the expected interface"""
for
obj
in
objects
:
if
not
expectedInterface
.
providedBy
(
obj
):
raise
RuntimeError
(
"Object
%
s does not implement
%
s interface"
%
(
obj
,
expectedInterface
))
\ No newline at end of file
corepost/web.py
View file @
89864450
...
...
@@ -3,32 +3,35 @@ Main server classes
@author: jacekf
'''
from
collections
import
defaultdict
from
corepost
import
Response
from
corepost.enums
import
Http
,
HttpHeader
from
corepost.utils
import
getMandatoryArgumentNames
,
convertToJson
from
corepost.routing
import
UrlRouter
,
CachedUrl
,
RequestRouter
from
corepost
import
Response
,
IRestServiceContainer
from
corepost.enums
import
Http
from
corepost.routing
import
UrlRouter
,
RequestRouter
from
enums
import
MediaType
from
formencode
import
FancyValidator
,
Invalid
from
twisted.internet
import
reactor
,
defer
from
twisted.
web.http
import
parse_qs
from
twisted.internet
import
reactor
from
twisted.
internet.defer
import
Deferred
from
twisted.web.resource
import
Resource
from
twisted.web.server
import
Site
,
NOT_DONE_YET
import
re
,
copy
,
exceptions
,
json
,
yaml
from
xml.etree
import
ElementTree
from
xml.etree.ElementTree
import
Element
from
twisted.internet.defer
import
Deferred
from
zope.interface
import
implements
#########################################################
#
# CLASSES
#
#########################################################
class
CorePost
(
Resource
):
class
RestServiceContainer
(
Resource
):
'''
Main resource responsible for routing REST requests to the implementing methods
'''
isLeaf
=
True
implements
(
IRestServiceContainer
)
def
__init__
(
self
,
schema
=
None
,
filters
=
()):
def
__init__
(
self
,
s
ervices
=
(),
s
chema
=
None
,
filters
=
()):
'''
Constructor
'''
self
.
services
=
services
self
.
__router
=
RequestRouter
(
self
,
schema
,
filters
)
Resource
.
__init__
(
self
)
...
...
@@ -82,7 +85,6 @@ class CorePost(Resource):
factory
=
Site
(
self
)
reactor
.
listenTCP
(
port
,
factory
)
#@UndefinedVariable
reactor
.
run
()
#@UndefinedVariable
##################################################################################################
#
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment