lazr-users team mailing list archive
-
lazr-users team
-
Mailing list archive
-
Message #00036
Re: Using lazr.restful with a zope3 app
2010/6/22 Gary Poster <gary.poster@xxxxxxxxxxxxx>
>
> On Jun 22, 2010, at 10:15 AM, Gustavo Rahal wrote:
>
> > 2010/6/21 Gary Poster <gary.poster@xxxxxxxxxxxxx>
> >
> > On Jun 21, 2010, at 2:42 PM, Gustavo Rahal wrote:
> >
> > > The problem was really the __repr__ of z3c.form. I fixed it and things
> worked fine. Will contact z3c.form owner for a permanent fix
> >
> > Great.
> >
> > > Now zope.app.publication and z3c.form need fixes...
> > >
> > > So, one step closer but still not there. At least now it seems i'm
> really on lazr.restful space. I'm having problems with the following:
> > >
> > > lazr/restful/_resource.py(1887)toDataForJSON()
> > > 1886 for link_name, publication in publications.items():
> > > -> 1887 data_for_json[link_name] = absoluteURL(publication,
> > > 1888
> self.request)
> > >
> > > absoluteURL call fails with TypeError: There isn't enough context to
> get URL information
> > > Here is what the various objects look like:
> > >
> > > ipdb> publications
> > > Out[0]: {'systems_collection_link':
> <tp4.portal.restful.resources.SystemSet object at 0xaf14d6c>}
> > > ipdb> publication
> > > Out[0]: <tp4.portal.restful.resources.SystemSet object at 0xaf14d6c>
> > > ipdb> self.request
> > > Out[0]: <lazr.restful.simple.Request instance URL=
> http://localhost:8080/api/1.0>
> > >
> > > My RootResource is:
> > >
> > > class WebServiceRootResource(RootResource):
> > > """The root resource for a web service."""
> > >
> > > def _build_top_level_objects(self):
> > > systemset = SystemSet()
> > > systemset.systems = [
> > > System(systemset, "foo", "bar"),
> > > System(systemset, "1", "2")
> > > ]
> > > collections = dict(systems=(ISystem, systemset))
> > > return collections, {}
> > >
> > > Configuration:
> > >
> > > class WebServiceConfiguration(BaseWebServiceConfiguration):
> > > code_revision = '1'
> > > active_versions = ['1.0',]
> > > use_https = False
> > > last_version_with_mutator_named_operations = None
> > > view_permission = 'zope.Public'
> > > service_root_uri_prefix = "api/"
> > > hostname = "localhost"
> > > port = "8080"
> > >
> > >
> > > Thoughts?
> >
> > It sounds like you need to define your own IAbsoluteURL implementation
> for the root object.
> >
> > It might be sufficient to add this to your zcml:
> >
> > <adapter factory="lazr.restful.simple.RootResourceAbsoluteURL" />
> >
> > If you are curious what is going on here, see
> lazr/restful/docs/absoluteurl.txt
> >
> >
> > This is already done
> >
> > Look what happens in lazr/restful/_resource.py(1887)toDataForJSON() :
> >
> > ipdb> self.request
> > Out[0]: <lazr.restful.simple.Request instance URL=
> http://localhost:8080/api/1.0>
> > ipdb> publication
> > Out[0]: <tp4.portal.restful.resources.SystemSet object at 0xb0db04c>
> > ipdb> getMultiAdapter((publication, self.request), IAbsoluteURL)
> > Out[0]: <tp4.portal.restful.root.BelowRootAbsoluteURL object at
> 0xac00b6c>
> > ipdb> self
> > Out[0]: <tp4.portal.restful.root.WebServiceRootResource object at
> 0xe324b0c>
> > ipdb> getMultiAdapter((self, self.request), IAbsoluteURL)
> > Out[0]: <tp4.portal.restful.root.RootAbsoluteURL object at 0xb44d50c>
> >
> > This works fine:
> > ipdb> adapter_root = getMultiAdapter((self, self.request), IAbsoluteURL)
> > ipdb> adapter_root()
> > Out[0]: 'http://localhost:8080/api/1.0/'
> >
> > But then:
> >
> > ipdb> adapter = getMultiAdapter((publication, self.request),
> IAbsoluteURL)
> > ipdb> adapter()
> > *** TypeError: There isn't enough context to get URL information. This is
> probably due to a bug in setting up location information.
>
> More guessing:
>
> - Does SystemSet declare that it implements
> zope.location.interfaces.ILocation, either by a direct declaration or by
> ISystemSet inherting from ILocation?
> - Does SystemSet actually implement ILocation?
>
> See PairSet at the bottom of lazr/restful/example/wsgi/resources.py for an
> example.
>
> Gary
>
>
ipdb> ILocation.providedBy(publication)
Out[0]: True
ipdb> publication.__parent__
Out[0]: <tp4.portal.restful.root.WebServiceRootResource object at 0xe773c0c>
ipdb> publication.__name__
Out[0]: 'systems'
I tested WSGI example setting "service_root_uri_prefix = "api/"" to the WSGI
WebServiceConfiguration and it also worked fine. This was mostly the only
difference compared to what I have.
I have not shown what I did to customize the request. Just to double check:
from lazr.restful.directives import publication_class, request_class
class TP4WSFactory:
implements(IRequestPublicationFactory)
def canHandle(self, environment):
ws_config = getUtility(IWebServiceConfiguration)
if environment["REQUEST_URI"].startswith("/" +
ws_config.path_override):
return True
else:
return False
def __call__(self):
return request_class.default, publication_class.default
ZCML:
<publisher
name="LAZRWS"
factory=".root.TP4WSFactory"
methods="GET POST HEAD DELETE"
mimetypes="*"
priority="5"
/>
Follow ups
References