def test_my_avatar(self): self.login(self.profile1.username) my_avatar = MyAvatar(self.profile1, self.request) data = my_avatar() self.assertTrue(IStreamIterator.providedBy(data)) profile_data = my_avatar.avatar_profile() self.assertTrue(IStreamIterator.providedBy(profile_data)) no_avatar = MyAvatar(self.profile2, self.request) data = no_avatar() self.assertIsNone(data)
def test_my_avatar(self): self.login(self.profile1.username) my_avatar = MyAvatar(self.profile1, self.request) data = my_avatar() self.assertTrue(IStreamIterator.providedBy(data)) profile_data = my_avatar.avatar_profile() self.assertTrue(IStreamIterator.providedBy(profile_data)) avatar = MyAvatar(self.profile2, self.request) self.assertEqual(avatar(), self.default_avatar)
def manage_FTPget(self, REQUEST=None, RESPONSE=None): """Return the body of the content item in an FTP or WebDAV response. This adapts self to IRawReadFile(), which is then returned as an iterator. The adapter should provide IStreamIterator. """ reader = IRawReadFile(self, None) if reader is None: return '' request = REQUEST is not None and REQUEST or self.REQUEST response = RESPONSE is not None and RESPONSE or request.response mimeType = reader.mimeType encoding = reader.encoding if mimeType is not None: if encoding is not None: response.setHeader('Content-Type', '%s; charset="%s"' % (mimeType, encoding,)) else: response.setHeader('Content-Type', mimeType) size = reader.size() if size is not None: response.setHeader('Content-Length', str(size)) # if the reader is an iterator that the publisher can handle, return # it as-is. Otherwise, read the full contents if ((IInterface.providedBy(IStreamIterator) and IStreamIterator.providedBy(reader)) or (not IInterface.providedBy(IStreamIterator) and IStreamIterator.isImplementedBy(reader)) ): return reader else: return reader.read()
def test_defaultreadfile_verify_iface(self): dummy = DefaultReadFile(ItemDummy()) self.assertTrue(IStreamIterator.providedBy(dummy)) self.assertTrue(verifyObject(IStreamIterator, dummy)) self.assertEqual(b"".join(dummy), b"Portal-Type: foo\n\n") self.assertEqual(len(dummy), 18)
def setBody(self, body, title='', is_error=False, lock=None): # allow locking of the body in the same way as the status if self._locked_body: return if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super().setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super().setBody(b'', title, is_error) else: super().setBody(body, title, is_error) # Have to apply the lock at the end in case the super class setBody # is called, which will observe the lock and do nothing if lock: self._locked_body = 1
def setBody(self, body, title='', is_error=False, lock=None): # allow locking of the body in the same way as the status if self._locked_body: return if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super(WSGIResponse, self).setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super(WSGIResponse, self).setBody(b'', title, is_error) else: super(WSGIResponse, self).setBody(body, title, is_error) # Have to apply the lock at the end in case the super class setBody # is called, which will observe the lock and do nothing if lock: self._locked_body = 1
def setBody(self, body, *args, **kw): if IInterface.providedBy(IStreamIterator): # is this zope 2.12? stream = IStreamIterator.providedBy(body) else: stream = IStreamIterator.isImplementedBy(body) if stream: body = ''.join(body) # read from iterator return original_setBody(self, body, *args, **kw)
def setBody(self, body, *args, **kw): if IInterface.providedBy(IStreamIterator): # is this zope 2.12? stream = IStreamIterator.providedBy(body) else: stream = IStreamIterator.isImplementedBy(body) if stream: body = ''.join(body) # read from iterator return self._original_setBody(body, *args, **kw)
def setBody(self, body, title='', is_error=0): if isinstance(body, file) or IStreamIterator.providedBy(body): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body else: HTTPResponse.setBody(self, body, title, is_error)
def setBody(self, body, title='', is_error=0, **kw): """ Accept either a stream iterator or a string as the body """ if IStreamIterator.providedBy(body): assert('content-length' in self.headers) # wrap the iterator up in a producer that medusa can understand self._bodyproducer = iterator_producer(body) HTTPResponse.setBody(self, '', title, is_error, **kw) return self else: HTTPResponse.setBody(self, body, title, is_error, **kw)
def setBody(self, body, title='', is_error=0, **kw): """ Accept either a stream iterator or a string as the body """ if IStreamIterator.providedBy(body): assert (self.headers.has_key('content-length')) # wrap the iterator up in a producer that medusa can understand self._bodyproducer = iterator_producer(body) HTTPResponse.setBody(self, '', title, is_error, **kw) return self else: HTTPResponse.setBody(self, body, title, is_error, **kw)
def test_avatars_view(self): self.login(self.profile1.username) avatars_view = AvatarsView(self.portal, self.request) avatars_view.publishTraverse(self.request, self.profile1.username) data = avatars_view() self.assertTrue(IStreamIterator.providedBy(data)) avatars_view.publishTraverse(self.request, self.profile2.username) self.assertEqual(avatars_view(), self.default_avatar) avatars_view.publishTraverse(self.request, 'not-a-username') self.assertEqual(avatars_view(), self.default_avatar)
def getWSGIResponse(self): # This return a tuple (data_sent, data_to_send_to_WSGI) result = self.body if result is not None: # If we have an iterator, we say that data have been sent # in order not to commit the transaction finish consuming # the iterator. if IStreamIterator.providedBy(result): return (True, StreamIteratorIterator(result)) elif IResult.providedBy(result): return (True, result) if not isinstance(result, str): log_invalid_response_data(result, self.__environ) return (self.__started, [result,]) return (self.__started, [])
def test_avatars_view(self): self.login(self.profile1.username) avatars_view = AvatarsView(self.portal, self.request) avatars_view.publishTraverse(self.request, self.profile1.username) data = avatars_view() self.assertTrue(IStreamIterator.providedBy(data)) avatars_view.publishTraverse(self.request, self.profile2.username) data = avatars_view() self.assertIsNone(data) avatars_view.publishTraverse(self.request, "not-a-username") with self.assertRaises(NotFound): avatars_view()
def setBody(self, body, title='', is_error=False): if isinstance(body, IOBase): body.seek(0, 2) length = body.tell() body.seek(0) self.setHeader('Content-Length', '%d' % length) self.body = body elif IStreamIterator.providedBy(body): self.body = body super(WSGIResponse, self).setBody(b'', title, is_error) elif IUnboundStreamIterator.providedBy(body): self.body = body self._streaming = 1 super(WSGIResponse, self).setBody(b'', title, is_error) else: super(WSGIResponse, self).setBody(body, title, is_error)
def applyTransformOnSuccess(event): """Apply the transform after a successful request """ transformed = applyTransform(event.request) if transformed is None: return response = event.request.response if IStreamIterator.providedBy(transformed): response.setBody(transformed) # setBody() can deal with byte and unicode strings (and will encode as # necessary)... elif isinstance(transformed, six.string_types): response.setBody(transformed) # ... but not with iterables else: response.setBody(''.join(transformed))
def applyTransformOnSuccess(event): """Apply the transform after a successful request """ transformed = applyTransform(event.request) if transformed is None: return response = event.request.response if IStreamIterator.providedBy(transformed): response.setBody(transformed) # setBody() can deal with byte and unicode strings (and will encode as # necessary)... elif isinstance(transformed, basestring): response.setBody(transformed) # ... but not with iterables else: response.setBody(''.join(transformed))
def setBody(self, body, title='', is_error=0, **kw): """ Accept either a stream iterator or a string as the body """ if not IStreamIterator.providedBy(body): return HTTPResponse.setBody(self, body, title, is_error, **kw) assert not self._wrote if isinstance(body, BlobStreamIterator): body = body.blob # A BlobFile if hasattr(body, 'seek') and hasattr(body, 'read') and hasattr(body, 'close'): self.stdout = body self._wrote = 1 return try: while True: chunk = body.next() self.write(chunk) except StopIteration: pass
def applyTransformOnSuccess(event): """Apply the transform after a successful request """ transformed = applyTransform(event.request) if transformed is not None: response = event.request.response # horrid check to deal with Plone 3/Zope 2.10, where this is still an old-style interface if ((IInterface.providedBy(IStreamIterator) and IStreamIterator.providedBy(transformed)) or (not IInterface.providedBy(IStreamIterator) and IStreamIterator.isImplementedBy(transformed)) ): response.setBody(transformed) # setBody() can deal with byte and unicode strings (and will encode as necessary)... elif isinstance(transformed, basestring): response.setBody(transformed) # ... but not with iterables else: response.setBody(''.join(transformed))
def manage_FTPget(self, REQUEST=None, RESPONSE=None): """Get the raw content for this object (also used for the WebDAV source) """ if REQUEST is None: REQUEST = self.REQUEST if RESPONSE is None: RESPONSE = REQUEST.RESPONSE if not self.Schema().hasLayer('marshall'): RESPONSE.setStatus(501) # Not implemented return RESPONSE self.dav__init(REQUEST, RESPONSE) collection_check(self) marshaller = self.Schema().getLayerImpl('marshall') ddata = marshaller.marshall(self, REQUEST=REQUEST, RESPONSE=RESPONSE) if (shasattr(self, 'marshall_hook') and self.marshall_hook): ddata = self.marshall_hook(ddata) content_type, length, data = ddata RESPONSE.setHeader('Content-Type', content_type) # Only set Content-Length header length is not None. If we want to # support 'chunked' Transfer-Encoding we shouldn't set # this. However ExternalEditor *expects* it to be set if we return # a StreamIterator, so until that gets fixed we must set it. if length is not None: RESPONSE.setHeader('Content-Length', length) if type(data) is type(''): return data # We assume 'data' is a 'Pdata chain' as used by OFS.File and # return a StreamIterator. assert length is not None, 'Could not figure out length of Pdata chain' if (issubclass(IStreamIterator, Interface) and IStreamIterator.providedBy(data) or not issubclass(IStreamIterator, Interface) and IStreamIterator.IsImplementedBy(data)): return data return PdataStreamIterator(data, length)
def setBody(self, body, title='', is_error=0, **kw): """ Accept either a stream iterator or a string as the body """ if not IStreamIterator.providedBy(body): return HTTPResponse.setBody(self, body, title, is_error, **kw) assert not self._wrote if isinstance(body, BlobStreamIterator): body = body.blob # A BlobFile if hasattr(body, 'seek') \ and hasattr(body, 'read') and \ hasattr(body, 'close'): self.stdout = body self._wrote = 1 return try: while True: chunk = body.next() self.write(chunk) except StopIteration: pass
def applyTransformOnSuccess(event): """Apply the transform after a successful request """ transformed = applyTransform(event.request) if transformed is not None: response = event.request.response # horrid check to deal with Plone 3/Zope 2.10, where this is still an old-style interface if ((IInterface.providedBy(IStreamIterator) and IStreamIterator.providedBy(transformed)) or (not IInterface.providedBy(IStreamIterator) and IStreamIterator.isImplementedBy(transformed))): response.setBody(transformed) # setBody() can deal with byte and unicode strings (and will encode as necessary)... elif isinstance(transformed, basestring): response.setBody(transformed) # ... but not with iterables else: response.setBody(''.join(transformed))
def manage_FTPget(self, REQUEST=None, RESPONSE=None): """Return the body of the content item in an FTP or WebDAV response. This adapts self to IRawReadFile(), which is then returned as an iterator. The adapter should provide IStreamIterator. """ reader = IRawReadFile(self, None) if reader is None: return '' request = REQUEST is not None and REQUEST or self.REQUEST response = RESPONSE is not None and RESPONSE or request.response mimeType = reader.mimeType encoding = reader.encoding if mimeType is not None: if encoding is not None: response.setHeader('Content-Type', '%s; charset="%s"' % ( mimeType, encoding, )) else: response.setHeader('Content-Type', mimeType) size = reader.size() if size is not None: response.setHeader('Content-Length', str(size)) # if the reader is an iterator that the publisher can handle, return # it as-is. Otherwise, read the full contents if ((IInterface.providedBy(IStreamIterator) and IStreamIterator.providedBy(reader)) or (not IInterface.providedBy(IStreamIterator) and IStreamIterator.isImplementedBy(reader))): return reader else: return reader.read()
def applyTransformOnSuccess(event): """Apply the transform after a successful request """ transformed = applyTransform(event.request) if transformed is None: return response = event.request.response if IStreamIterator.providedBy(transformed): response.setBody(transformed) # setBody() can deal with byte and unicode strings (and will encode as # necessary)... elif isinstance(transformed, six.string_types)\ or isinstance(transformed, six.binary_type): response.setBody(transformed) # ... but not with iterables else: transformed = map( lambda it: it.decode('utf-8') if isinstance(it, six.binary_type) else it, transformed ) response.setBody(''.join(transformed))
def testDownloadReturnsIterator(self): result=self.view() self.failUnless(IStreamIterator.providedBy(result))
def getResourceContent(self, item, context, original=False, theme=None): """Fetch resource content for delivery.""" if theme is None: theme = self.getCurrentSkinName() ids = self.concatenatedResourcesByTheme.get(theme, {}).get(item, None) resources = self.getResourcesDict() if ids is not None: ids = ids[:] output = u"" if len(ids) > 1: output = output + self.merged_output_prefix portal = getToolByName(context, 'portal_url').getPortalObject() if context == self and portal is not None: context = portal default_charset = 'utf-8' for id in ids: try: if portal is not None: obj = context.restrictedTraverse(id) else: #Can't do anything other than attempt a getattr obj = getattr(context, id) except (AttributeError, KeyError): output += u"\n/* XXX ERROR -- could not find '%s'*/\n" % id content = u'' obj = None except Unauthorized: #If we're just returning a single resource, raise an Unauthorized, #otherwise we're merging resources in which case just log an error if len(ids) > 1: #Object probably isn't published yet output += u"\n/* XXX ERROR -- access to '%s' not authorized */\n" % id content = u'' obj = None else: raise if obj is not None: if isinstance(obj, z3_Resource): # z3 resources # XXX this is a temporary solution, we wrap the five resources # into our mechanism, where it should be the other way around. # # First thing we must be aware of: resources give a complete # response so first we must save the headers. # Especially, we must delete the If-Modified-Since, because # otherwise we might get a 30x response status in some cases. original_headers, if_modified = self._removeCachingHeaders() # Now, get the content. try: method = obj.__browser_default__(self.REQUEST)[1][0] except AttributeError: # zope.app.publisher.browser.fileresource try: method = obj.browserDefault(self.REQUEST)[1][0] except (AttributeError, IndexError): try: method = obj.browserDefault(self.REQUEST)[0].__name__ except AttributeError: # The above can all fail if request.method is # POST. We can still at least try to use the # GET method, as we prefer that anyway. method = getattr(obj, 'GET').__name__ method = method in ('HEAD','POST') and 'GET' or method content = getattr(obj, method)() if not isinstance(content, unicode): contenttype = self.REQUEST.RESPONSE.headers.get('content-type', '') contenttype = getCharsetFromContentType(contenttype, default_charset) content = unicode(content, contenttype) self._restoreCachingHeaders(original_headers, if_modified) elif hasattr(aq_base(obj),'meta_type') and obj.meta_type in ['DTML Method', 'Filesystem DTML Method']: content = obj(client=self.aq_parent, REQUEST=self.REQUEST, RESPONSE=self.REQUEST.RESPONSE) contenttype = self.REQUEST.RESPONSE.headers.get('content-type', '') contenttype = getCharsetFromContentType(contenttype, default_charset) content = unicode(content, contenttype) elif hasattr(aq_base(obj),'meta_type') and obj.meta_type == 'Filesystem File': obj._updateFromFS() content = obj._readFile(0) contenttype = getCharsetFromContentType(obj.content_type, default_charset) content = unicode(content, contenttype) elif hasattr(aq_base(obj),'meta_type') and obj.meta_type in ('ATFile', 'ATBlob'): f = obj.getFile() contenttype = getCharsetFromContentType(f.getContentType(), default_charset) content = unicode(str(f), contenttype) # We should add more explicit type-matching checks elif hasattr(aq_base(obj), 'index_html') and callable(obj.index_html): original_headers, if_modified = self._removeCachingHeaders() # "index_html" may use "RESPONSE.write" (e.g. for OFS.Image.Pdata) tmp = StringIO() response_write = self.REQUEST.RESPONSE.write self.REQUEST.RESPONSE.write = tmp.write try: content = obj.index_html(self.REQUEST, self.REQUEST.RESPONSE) finally: self.REQUEST.RESPONSE.write = response_write content = tmp.getvalue() or content if not isinstance(content, unicode): content = unicode(content, default_charset) self._restoreCachingHeaders(original_headers, if_modified) elif callable(obj): try: content = obj(self.REQUEST, self.REQUEST.RESPONSE) except TypeError: # Could be a view or browser resource content = obj() if IStreamIterator.providedBy(content): content = content.read() if not isinstance(content, unicode): content = unicode(content, default_charset) else: content = str(obj) content = unicode(content, default_charset) # Add start/end notes to the resource for better # understanding and debugging if content: output += u'\n/* - %s - */\n' % (id,) if original: output += content else: output += self.finalizeContent(resources[id], content) output += u'\n' return output
def getResourceContent(self, item, context, original=False, theme=None): """Fetch resource content for delivery.""" if theme is None: theme = self.getCurrentSkinName() ids = self.concatenatedResourcesByTheme.get(theme, {}).get(item, None) resources = self.getResourcesDict() if ids is not None: ids = ids[:] output = u"" if len(ids) > 1: output = output + self.merged_output_prefix portal = getToolByName(context, 'portal_url').getPortalObject() if context == self and portal is not None: context = portal default_charset = 'utf-8' for id in ids: try: if portal is not None: obj = context.restrictedTraverse(id) else: #Can't do anything other than attempt a getattr obj = getattr(context, id) except (AttributeError, KeyError): output += u"\n/* XXX ERROR -- could not find '%s'*/\n" % id content = u'' obj = None except Unauthorized: #If we're just returning a single resource, raise an Unauthorized, #otherwise we're merging resources in which case just log an error if len(ids) > 1: #Object probably isn't published yet output += u"\n/* XXX ERROR -- access to '%s' not authorized */\n" % id content = u'' obj = None else: raise if obj is not None: if isinstance(obj, z3_Resource): # z3 resources # XXX this is a temporary solution, we wrap the five resources # into our mechanism, where it should be the other way around. # # First thing we must be aware of: resources give a complete # response so first we must save the headers. # Especially, we must delete the If-Modified-Since, because # otherwise we might get a 30x response status in some cases. original_headers, if_modified = self._removeCachingHeaders( ) # Now, get the content. try: method = obj.__browser_default__(self.REQUEST)[1][0] except AttributeError: # zope.app.publisher.browser.fileresource try: method = obj.browserDefault(self.REQUEST)[1][0] except (AttributeError, IndexError): try: method = obj.browserDefault( self.REQUEST)[0].__name__ except AttributeError: # The above can all fail if request.method is # POST. We can still at least try to use the # GET method, as we prefer that anyway. method = getattr(obj, 'GET').__name__ method = method in ('HEAD', 'POST') and 'GET' or method content = getattr(obj, method)() if not isinstance(content, unicode): contenttype = self.REQUEST.RESPONSE.headers.get( 'content-type', '') contenttype = getCharsetFromContentType( contenttype, default_charset) content = unicode(content, contenttype) self._restoreCachingHeaders(original_headers, if_modified) elif hasattr(aq_base(obj), 'meta_type') and obj.meta_type in [ 'DTML Method', 'Filesystem DTML Method' ]: content = obj(client=self.aq_parent, REQUEST=self.REQUEST, RESPONSE=self.REQUEST.RESPONSE) contenttype = self.REQUEST.RESPONSE.headers.get( 'content-type', '') contenttype = getCharsetFromContentType( contenttype, default_charset) content = unicode(content, contenttype) elif hasattr( aq_base(obj), 'meta_type') and obj.meta_type == 'Filesystem File': obj._updateFromFS() content = obj._readFile(0) contenttype = getCharsetFromContentType( obj.content_type, default_charset) content = unicode(content, contenttype) elif hasattr( aq_base(obj), 'meta_type') and obj.meta_type in ('ATFile', 'ATBlob'): f = obj.getFile() contenttype = getCharsetFromContentType( f.getContentType(), default_charset) content = unicode(str(f), contenttype) # We should add more explicit type-matching checks elif hasattr(aq_base(obj), 'index_html') and callable( obj.index_html): original_headers, if_modified = self._removeCachingHeaders( ) # "index_html" may use "RESPONSE.write" (e.g. for OFS.Image.Pdata) tmp = StringIO() response_write = self.REQUEST.RESPONSE.write self.REQUEST.RESPONSE.write = tmp.write try: content = obj.index_html(self.REQUEST, self.REQUEST.RESPONSE) finally: self.REQUEST.RESPONSE.write = response_write content = tmp.getvalue() or content if not isinstance(content, unicode): content = unicode(content, default_charset) self._restoreCachingHeaders(original_headers, if_modified) elif callable(obj): try: content = obj(self.REQUEST, self.REQUEST.RESPONSE) except TypeError: # Could be a view or browser resource content = obj() if IStreamIterator.providedBy(content): content = content.read() if not isinstance(content, unicode): content = unicode(content, default_charset) else: content = str(obj) content = unicode(content, default_charset) # Add start/end notes to the resource for better # understanding and debugging if content: output += u'\n/* - %s - */\n' % (id, ) if original: output += content else: output += self.finalizeContent(resources[id], content) output += u'\n' return output
setDefaultSkin(request) try: response = _publish(request, 'Zope2') except Unauthorized, v: response._unauthorized() except Redirect, v: response.redirect(v) # Start the WSGI server response status, headers = response.finalize() start_response(status, headers) body = response.body if isinstance(body, file) or IStreamIterator.providedBy(body): result = body else: # If somebody used response.write, that data will be in the # stdout StringIO, so we put that before the body. # XXX This still needs verification that it really works. result = (stdout.getvalue(), response.body) if 'repoze.tm.active' not in environ: request.close() # this aborts the transation! stdout.close() for callable in response.after_list: callable()
def startWSGIResponse(self, stream=False): if self.__started: return self.__write self.__started = True # If the body is an IResult, it is a case of streaming where # we don't fix headers. if IResult.providedBy(self.body): stream = True if not stream: # If we are not streaming, we try to set Content-Length, # Content-Type and adapt status if there is no content. content_length = None content_type = None # Inspect content-length if self.headers.has_key('Content-Length'): content_length = self.headers['Content-Length'] else: if (isinstance(self.body, basestring) or IStreamIterator.providedBy(self.body)): body_length = len(self.body) if body_length: content_length = str(body_length) # Inspect content-type if self.headers.has_key('Content-Type'): content_type = self.headers['Content-Type'] # Modify them if content_length is None: if content_type is None and self.status == 200: # No content length and content-type switch to 204. self.status = 204 if self.status not in (100, 100, 101, 102, 204, 304): content_length = '0' if content_length is not None: # If there is Content and no Content-Type, set HTML if content_type is None and content_length != '0': content_type = 'text/html;charset={0}'.format( self.default_charset) # Update content_length and content_type if content_length is not None: self.headers['Content-Length'] = content_length if content_type is not None: self.headers['Content-Type'] = content_type else: # Fire event before streaming notify(PublicationBeforeStreaming(self)) # Fix default Content-Type if not self.headers.has_key('Content-Type'): self.headers['Content-Type'] = 'text/html;charset=%s' % ( self.default_charset,) formatted_status = "%d %s" % ( self.status, status_reasons.get(self.status, 'OK')) formatted_headers = self.headers.items() + format_cookies(self.cookies) self.__write = self.__start_response( formatted_status, formatted_headers) return self.__write
def getResourceContent(item, context=None, request=None): """Fetch resource content for delivery.""" id = item output = u"" portal = getSite() if context is None: context = portal if request is None: request = getRequest() default_charset = 'utf-8' id = item # skip external resources that look like //netdna.bootstrapcdn.com/etc... if id[0:2] == '//': return output # original_request = getRequest() # import pdb; pdb.set_trace() # if original_request != request: # setRequest(request) try: if portal is not None: obj = context.restrictedTraverse(id) else: # Can't do anything other than attempt a getattr obj = getattr(context, id) except (AttributeError, KeyError): output += u"\n/* XXX ERROR -- could not find '%s'*/\n" % id content = u'' obj = None except Unauthorized: # If we're just returning a single resource, raise an Unauthorized, # otherwise we're merging resources in which case just log an error raise if obj is not None: if isinstance(obj, z3_Resource): # z3 resources # XXX this is a temporary solution, we wrap the five resources # into our mechanism, where it should be the other way around. # # First thing we must be aware of: resources give a complete # response so first we must save the headers. # Especially, we must delete the If-Modified-Since, because # otherwise we might get a 30x response status in some cases. original_headers, if_modified = _removeCachingHeaders(request) # Now, get the content. try: method = obj.__browser_default__(request)[1][0] except AttributeError: # zope.app.publisher.browser.fileresource try: method = obj.browserDefault(request)[1][0] except (AttributeError, IndexError): try: method = obj.browserDefault(request)[0].__name__ except AttributeError: # The above can all fail if request.method is # POST. We can still at least try to use the # GET method, as we prefer that anyway. method = getattr(obj, 'GET').__name__ method = method in ('HEAD', 'POST') and 'GET' or method content = getattr(obj, method)() import pdb; pdb.set_trace() if not isinstance(content, unicode): contenttype = request.RESPONSE.headers.get('content-type', '') contenttype = getCharsetFromContentType(contenttype, default_charset) content = unicode(content, contenttype) _restoreCachingHeaders(request, original_headers, if_modified) elif hasattr(aq_base(obj), 'meta_type') and obj.meta_type in ['DTML Method', 'Filesystem DTML Method']: content = obj(client=context, REQUEST=request, RESPONSE=request.RESPONSE) contenttype = request.RESPONSE.headers.get('content-type', '') contenttype = getCharsetFromContentType(contenttype, default_charset) content = unicode(content, contenttype) elif hasattr(aq_base(obj), 'meta_type') and obj.meta_type == 'Filesystem File': obj._updateFromFS() content = obj._readFile(0) contenttype = getCharsetFromContentType(obj.content_type, default_charset) content = unicode(content, contenttype) elif hasattr(aq_base(obj), 'meta_type') and obj.meta_type in ('ATFile', 'ATBlob'): f = obj.getFile() contenttype = getCharsetFromContentType(f.getContentType(), default_charset) content = unicode(str(f), contenttype) # We should add more explicit type-matching checks elif hasattr(aq_base(obj), 'index_html') and callable(obj.index_html): original_headers, if_modified = _removeCachingHeaders(request) # "index_html" may use "RESPONSE.write" (e.g. for OFS.Image.Pdata) tmp = StringIO() response_write = request.RESPONSE.write request.RESPONSE.write = tmp.write try: content = obj.index_html(request, request.RESPONSE) finally: request.RESPONSE.write = response_write content = tmp.getvalue() or content if not isinstance(content, unicode): content = unicode(content, default_charset) _restoreCachingHeaders(request, original_headers, if_modified) elif callable(obj): try: content = obj(request, request.RESPONSE) except TypeError: # Could be a view or browser resource content = obj() if IStreamIterator.providedBy(content): content = content.read() if not isinstance(content, unicode): content = unicode(content, default_charset) else: content = str(obj) content = unicode(content, default_charset) # Add start/end notes to the resource for better # understanding and debugging if content: output += u'\n/* - %s - */\n' % (id,) output += content output += u'\n' # if original_request != request: # setRequest(original_request) return output
def index_html(self, REQUEST, RESPONSE, path=None): """Publish the object to the external editor helper app""" security = getSecurityManager() if path is None: parent = self.aq_parent try: ob = parent[REQUEST['target']] # Try getitem except KeyError: ob = getattr(parent, REQUEST['target']) # Try getattr except AttributeError: # Handle objects that are methods in ZClasses ob = parent.propertysheets.methods[REQUEST['target']] else: ob = self.restrictedTraverse(path) r = [] r.append('url:%s' % ob.absolute_url()) r.append('meta_type:%s' % ob.meta_type) title = getattr(aq_base(ob), 'title', None) if title is not None: if callable(title): title = title() if isinstance(title, types.UnicodeType): title = unicode.encode(title, 'utf-8') r.append('title:%s' % title) if hasattr(aq_base(ob), 'content_type'): if callable(ob.content_type): r.append('content_type:%s' % ob.content_type()) else: r.append('content_type:%s' % ob.content_type) if REQUEST._auth: if REQUEST._auth[-1] == '\n': auth = REQUEST._auth[:-1] else: auth = REQUEST._auth r.append('auth:%s' % auth) r.append('cookie:%s' % REQUEST.environ.get('HTTP_COOKIE', '')) if wl_isLocked(ob): # Object is locked, send down the lock token # owned by this user (if any) user_id = security.getUser().getId() for lock in ob.wl_lockValues(): if not lock.isValid(): continue # Skip invalid/expired locks creator = lock.getCreator() if creator and creator[1] == user_id: # Found a lock for this user, so send it r.append('lock-token:%s' % lock.getLockToken()) if REQUEST.get('borrow_lock'): r.append('borrow_lock:1') break # Apply any extra callbacks that might have been registered. applyCallbacks(ob, r, REQUEST, RESPONSE) # Finish metadata with an empty line. r.append('') metadata = join(r, '\n') metadata_len = len(metadata) # Check if we should send the file's data down the response. if REQUEST.get('skip_data'): # We've been requested to send only the metadata. The # client will presumably fetch the data itself. self._write_metadata(RESPONSE, metadata, metadata_len) return '' ob_data = getattr(aq_base(ob), 'data', None) if (ob_data is not None and isinstance(ob_data, Image.Pdata)): # We have a File instance with chunked data, lets stream it. # # Note we are setting the content-length header here. This # is a simplification. Read comment below. # # We assume that ob.get_size() will return the exact size # of the PData chain. If that assumption is broken we # might have problems. This is mainly an optimization. If # we read the whole PData chain just to compute the # correct size that could cause the whole file to be read # into memory. RESPONSE.setHeader('Content-Length', ob.get_size()) # It is safe to use this PDataStreamIterator here because # it is consumed right below. This is only used to # simplify the code below so it only has to deal with # stream iterators or plain strings. body = PDataStreamIterator(ob.data) elif hasattr(ob, 'manage_FTPget'): # Calling manage_FTPget *might* have side-effects. For # example, in Archetypes it does set the 'content-type' # response header, which would end up overriding our own # content-type header because we've set it 'too # early'. We've moved setting the content-type header to # the '_write_metadata' method since, and any manipulation # of response headers should happen there, if possible. try: body = ob.manage_FTPget() except TypeError: # some need the R/R pair! body = ob.manage_FTPget(REQUEST, RESPONSE) elif hasattr(ob, 'EditableBody'): body = ob.EditableBody() elif hasattr(ob, 'document_src'): body = ob.document_src(REQUEST, RESPONSE) elif hasattr(ob, 'read'): body = ob.read() else: # can't read it! raise 'BadRequest', 'Object does not support external editing' if (HAVE_Z3_IFACE and IStreamIterator.providedBy(body) or (not HAVE_Z3_IFACE) and IStreamIterator.isImplementedBy(body)): # We need to manage our content-length because we're streaming. # The content-length should have been set in the response by # the method that returns the iterator, but we need to fix it up # here because we insert metadata before the body. clen = RESPONSE.headers.get('content-length', None) assert clen is not None self._write_metadata(RESPONSE, metadata, metadata_len + int(clen)) for data in body: RESPONSE.write(data) return '' # If we reached this point, body *must* be a string. We *must* # set the headers ourselves since _write_metadata won't get # called. self._set_headers(RESPONSE) return join((metadata, body), '\n')
def setBody(self, body, title='', is_error=0, **kw): if IStreamIterator.providedBy(body): body = ''.join(body) Response.setBody(self, body, title, is_error, **kw)
def __init__(self, stream): assert IStreamIterator.providedBy(stream) self.__stream = stream
def __call__(self): self.request.response.setHeader("Content-Type", "application/json") result = self.render() if IStreamIterator.providedBy(result): return result return json.dumps(result, indent=2, sort_keys=True)
def Service__call__(self): self.request.response.setHeader("Content-Type", "application/json") result = self.render() if IStreamIterator.providedBy(result): return result return json.dumps(result, indent=2, sort_keys=True)