Esempio n. 1
0
    def deferred_render_GET(self, request):
        # TODO: usages should be cached locally; lookup is expensive.
        usage = registry.findUsage(httpTagCategoryName, 'GET', TagsResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        args = {
            returnDescriptionArg:
            util.getBooleanArg(request, returnDescriptionArg,
                               usage.arguments[returnDescriptionArg].default),
        }

        ttag = yield self.facadeClient.getTag(
            self.session,
            sep.join(request.postpath),
            returnDescription=args[returnDescriptionArg])

        responseDict = {
            'id': ttag.objectId,
            'indexed': ttag.indexed,
        }
        if args[returnDescriptionArg]:
            responseDict['description'] = ttag.description

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 2
0
 def deferred_render_DELETE(self, request):
     usage = registry.findUsage(httpNamespaceCategoryName, 'DELETE',
                                NamespacesResource)
     registry.checkRequest(usage, request)
     yield self.facadeClient.deleteNamespace(self.session,
                                             sep.join(request.postpath))
     request.setResponseCode(usage.successCode)
Esempio n. 3
0
    def deferred_render_GET(self, request):
        usage = registry.findUsage(httpObjectCategoryName, 'GET',
                                   ObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        showAbout = util.getBooleanArg(
            request, showAboutArg,
            usage.arguments[showAboutArg].default)

        objectInfo = yield self.facadeClient.getObject(
            self.session, self.objectId, showAbout)

        responseDict = {
            tagPathsArg: objectInfo.tagPaths,
        }
        if showAbout:
            if objectInfo.about:
                responseDict[aboutArg] = objectInfo.about.decode('utf-8')
            else:
                responseDict[aboutArg] = None

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 4
0
    def deferred_render_GET(self, request):
        """
        Return information about the object whose about value is given in the
        URI.

        @param request: The HTTP request.
        @return: A C{Deferred} that fires with the body of the response.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'GET',
                                   AboutObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        # Note: we need to escape any double quotes in the about value so
        # that the query parser doesn't raise a syntax error.  See
        # https://bugs.edge.launchpad.net/fluiddb/+bug/802783
        query = '%s = "%s"' % (_aboutPath, self.about.replace('"', r'\"'))
        objectIds = yield self.facadeClient.resolveQuery(self.session, query)
        if objectIds:
            objectId = objectIds.pop()
        else:
            raise error.NoSuchObject()
        objectInfo = yield self.facadeClient.getObject(self.session,
                                                       objectId,
                                                       showAbout=False)
        responseDict = {
            _tagPathsArg: objectInfo.tagPaths,
            'id': objectId,
        }
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 5
0
    def deferred_render_GET(self, request):
        """
        Return information about the object whose about value is given in the
        URI.

        @param request: The HTTP request.
        @return: A C{Deferred} that fires with the body of the response.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'GET',
                                   AboutObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        # Note: we need to escape any double quotes in the about value so
        # that the query parser doesn't raise a syntax error.  See
        # https://bugs.edge.launchpad.net/fluiddb/+bug/802783
        query = '%s = "%s"' % (_aboutPath, self.about.replace('"', r'\"'))
        objectIds = yield self.facadeClient.resolveQuery(self.session, query)
        if objectIds:
            objectId = objectIds.pop()
        else:
            raise error.NoSuchObject()
        objectInfo = yield self.facadeClient.getObject(
            self.session, objectId, showAbout=False)
        responseDict = {
            _tagPathsArg: objectInfo.tagPaths,
            'id': objectId,
        }
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 6
0
 def deferred_render_DELETE(self, request):
     usage = registry.findUsage(httpNamespaceCategoryName, 'DELETE',
                                NamespacesResource)
     registry.checkRequest(usage, request)
     yield self.facadeClient.deleteNamespace(self.session,
                                             sep.join(request.postpath))
     request.setResponseCode(usage.successCode)
Esempio n. 7
0
    def deferred_render_GET(self, request):
        """
        Handle a GET request for /values with a query and a list
        of wanted tags.

        @param request: The incoming C{twisted.web.server.Request} request.
        @return: A C{Deferred} which will fire with the body of the
            response.  The deferred may errback for a variety of reasons,
            for example an invalid query, the mention of a non-existent tag
            or a tag that the caller does not have READ permission for.
        """
        usage = registry.findUsage(httpValueCategoryName, 'GET',
                                   ValuesResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        query = request.args[queryArg][0]
        tags = request.args[tagArg]
        # FIXME An HTTP 500 will occur if a user passes '*' with some other
        # tags, like 'tag=foo&tag=*'. -jkakar
        if tags == ['*']:
            tags = None
        body = yield self.facadeClient.getValuesForQuery(
            self.session, query, tags)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 8
0
    def deferred_render_GET(self, request):
        usage = registry.findUsage(httpObjectCategoryName, 'GET',
                                   ObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        showAbout = util.getBooleanArg(request, showAboutArg,
                                       usage.arguments[showAboutArg].default)

        objectInfo = yield self.facadeClient.getObject(self.session,
                                                       self.objectId,
                                                       showAbout)

        responseDict = {
            tagPathsArg: objectInfo.tagPaths,
        }
        if showAbout:
            if objectInfo.about:
                responseDict[aboutArg] = objectInfo.about.decode('utf-8')
            else:
                responseDict[aboutArg] = None

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 9
0
    def deferred_render_GET(self, request):
        """
        Handle a GET request for /values with a query and a list
        of wanted tags.

        @param request: The incoming C{twisted.web.server.Request} request.
        @return: A C{Deferred} which will fire with the body of the
            response.  The deferred may errback for a variety of reasons,
            for example an invalid query, the mention of a non-existent tag
            or a tag that the caller does not have READ permission for.
        """
        usage = registry.findUsage(httpValueCategoryName, 'GET',
                                   ValuesResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        query = request.args[queryArg][0]
        tags = request.args[tagArg]
        # FIXME An HTTP 500 will occur if a user passes '*' with some other
        # tags, like 'tag=foo&tag=*'. -jkakar
        if tags == ['*']:
            tags = None
        body = yield self.facadeClient.getValuesForQuery(
            self.session, query, tags)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 10
0
    def deferred_render_GET(self, request):
        # TODO: usages should be cached locally; lookup is expensive.
        usage = registry.findUsage(httpTagCategoryName, 'GET', TagsResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        args = {
            returnDescriptionArg: util.getBooleanArg(
                request, returnDescriptionArg,
                usage.arguments[returnDescriptionArg].default),
        }

        ttag = yield self.facadeClient.getTag(
            self.session,
            sep.join(request.postpath),
            returnDescription=args[returnDescriptionArg])

        responseDict = {
            'id': ttag.objectId,
            'indexed': ttag.indexed,
        }
        if args[returnDescriptionArg]:
            responseDict['description'] = ttag.description

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 11
0
 def deferred_render_DELETE(self, request):
     """
     The following code is reproduced almost verbatim in
     deferred_render_DELETE in about.py. So if you change this code,
     you'll likely need to change that, and vice versa.
     """
     usage = registry.findUsage(httpObjectCategoryName, 'DELETE',
                                TagInstanceResource)
     registry.checkRequest(usage, request)
     yield self.facadeClient.deleteTagInstance(
         self.session, self.path, self.objectId)
     request.setResponseCode(usage.successCode)
     defer.returnValue(None)
Esempio n. 12
0
 def deferred_render_DELETE(self, request):
     """
     The following code is reproduced almost verbatim in
     deferred_render_DELETE in about.py. So if you change this code,
     you'll likely need to change that, and vice versa.
     """
     usage = registry.findUsage(httpObjectCategoryName, 'DELETE',
                                TagInstanceResource)
     registry.checkRequest(usage, request)
     yield self.facadeClient.deleteTagInstance(self.session, self.path,
                                               self.objectId)
     request.setResponseCode(usage.successCode)
     defer.returnValue(None)
Esempio n. 13
0
 def deferred_render_GET(self, request):
     usage = registry.findUsage(httpObjectCategoryName, 'GET',
                                ObjectsResource)
     registry.checkRequest(usage, request)
     responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
     query = request.args['query'][0]
     results = yield self.facadeClient.resolveQuery(self.session, query)
     responseDict = {'ids': list(results)}
     registry.checkResponse(responseType, responseDict, usage, request)
     body = payloads.buildPayload(responseType, responseDict)
     request.setHeader('Content-length', str(len(body)))
     request.setHeader('Content-type', responseType)
     request.setResponseCode(usage.successCode)
     defer.returnValue(body)
Esempio n. 14
0
 def deferred_render_GET(self, request):
     usage = registry.findUsage(httpObjectCategoryName, 'GET',
                                ObjectsResource)
     registry.checkRequest(usage, request)
     responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
     query = request.args['query'][0]
     results = yield self.facadeClient.resolveQuery(self.session, query)
     responseDict = {'ids': list(results)}
     registry.checkResponse(responseType, responseDict, usage, request)
     body = payloads.buildPayload(responseType, responseDict)
     request.setHeader('Content-length', str(len(body)))
     request.setHeader('Content-type', responseType)
     request.setResponseCode(usage.successCode)
     defer.returnValue(body)
Esempio n. 15
0
    def _GET_HEAD_common(self, request, verb):
        """
        The following code is reproduced almost verbatim in
        deferred_render_DELETE in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, verb,
                                   TagInstanceResource)

        registry.checkRequest(usage, request)

        # This will raise TNoInstanceOnObject if there's no instance,
        # and that will return a 404 (see util.py).
        tvalue, tagValue = yield self.facadeClient.getTagInstance(
            self.session, self.path, self.objectId)
        value = guessValue(tvalue)
        accept = request.getHeader('accept') or '*/*'

        if tvalue.valueType == ThriftValueType.BINARY_TYPE:
            contentType = tvalue.binaryKeyMimeType
            if mimeparse.best_match([contentType], accept) == '':
                raise error.NotAcceptable()
            body = value
            # Mark this value as unwrappable for JSON
            request._fluiddb_jsonp_unwrappable = None
        else:
            contentType = mimeparse.best_match(contentTypesForPrimitiveValue,
                                               accept)
            if contentType == '':
                raise error.NotAcceptable()
            try:
                serializer = util.primitiveTypeSerializer[contentType]
            except KeyError:
                raise TInternalError('No serializer for %r.' % contentType)
            else:
                body = serializer(value)

            typeValue = self._getTypeHeader(tvalue.valueType)
            request.setHeader(util.buildHeader('Type'), typeValue)

        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', contentType)
        # setting the Last-Modified header for fluiddb/id makes no sense
        if tagValue and tagValue.creationTime:
            request.setHeader(
                'Last-modified',
                tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S'))
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 16
0
    def _GET_HEAD_common(self, request, verb):
        """
        The following code is reproduced almost verbatim in
        deferred_render_DELETE in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, verb,
                                   TagInstanceResource)

        registry.checkRequest(usage, request)

        # This will raise TNoInstanceOnObject if there's no instance,
        # and that will return a 404 (see util.py).
        tvalue, tagValue = yield self.facadeClient.getTagInstance(
            self.session, self.path, self.objectId)
        value = guessValue(tvalue)
        accept = request.getHeader('accept') or '*/*'

        if tvalue.valueType == ThriftValueType.BINARY_TYPE:
            contentType = tvalue.binaryKeyMimeType
            if mimeparse.best_match([contentType], accept) == '':
                raise error.NotAcceptable()
            body = value
            # Mark this value as unwrappable for JSON
            request._fluiddb_jsonp_unwrappable = None
        else:
            contentType = mimeparse.best_match(
                contentTypesForPrimitiveValue, accept)
            if contentType == '':
                raise error.NotAcceptable()
            try:
                serializer = util.primitiveTypeSerializer[contentType]
            except KeyError:
                raise TInternalError('No serializer for %r.' % contentType)
            else:
                body = serializer(value)

            typeValue = self._getTypeHeader(tvalue.valueType)
            request.setHeader(util.buildHeader('Type'), typeValue)

        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', contentType)
        # setting the Last-Modified header for fluiddb/id makes no sense
        if tagValue and tagValue.creationTime:
            request.setHeader(
                'Last-modified',
                tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S'))
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 17
0
    def deferred_render_POST(self, request):
        usage = registry.findUsage(httpObjectCategoryName, 'POST',
                                   ObjectsResource)
        dictionary = registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        about = dictionary.get(aboutArg, '')

        objectId = yield self.facadeClient.createObject(
            session=self.session, about=about.encode('utf-8'))

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        # Return the location of the new object by its id.
        location = '%s://%s/%s/%s' % (
            proto,
            hostname,
            httpObjectCategoryName,
            # This is probably overkill
            urllib.quote(objectId.encode('utf-8')))

        responseDict = {'id': objectId, 'URI': location}
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 18
0
    def deferred_render_POST(self, request):
        usage = registry.findUsage(httpObjectCategoryName, 'POST',
                                   ObjectsResource)
        dictionary = registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
        about = dictionary.get(aboutArg, '')

        objectId = yield self.facadeClient.createObject(
            session=self.session, about=about.encode('utf-8'))

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        # Return the location of the new object by its id.
        location = '%s://%s/%s/%s' % (
            proto, hostname, httpObjectCategoryName,
            # This is probably overkill
            urllib.quote(objectId.encode('utf-8')))

        responseDict = {'id': objectId, 'URI': location}
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 19
0
        def run():
            if not request.isSecure() and not getDevelopmentMode():
                raise TBadRequest(
                    '/users/<username>/verify requests must use HTTPS')
            dictionary = registry.checkRequest(usage, request)
            user = cachingGetUser(self.username.decode('utf-8'))
            if not user:
                raise TNoSuchUser(self.username)
            password = dictionary['password']

            if checkPassword(password, user.passwordHash):
                # FIXME Hard-coding the 'anon' consumer here isn't great,
                # but for now it means we don't have to change the public
                # API. -jkakar
                api = OAuthConsumerAPI()
                consumer = cachingGetUser(u'anon')
                accessToken = api.getAccessToken(consumer, user)
                renewalToken = api.getRenewalToken(consumer, user)
                return {'accessToken': accessToken.encrypt(),
                        'fullname': user.fullname,
                        'renewalToken': renewalToken.encrypt(),
                        'role': str(user.role),
                        'valid': True}
            else:
                return {'valid': False}
Esempio n. 20
0
 def deferred_render_GET(self, request):
     # TODO: usages should be cached locally; lookup is expensive.
     usage = registry.findUsage(httpUserCategoryName, 'GET',
                                ConcreteUserResource)
     registry.checkRequest(usage, request)
     responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
     tuser = yield self.facadeClient.getUser(self.session, self.username)
     responseDict = {
         'name': tuser.name,
         'role': tuser.role,
         'id': tuser.objectId,
     }
     registry.checkResponse(responseType, responseDict, usage, request)
     body = payloads.buildPayload(responseType, responseDict)
     request.setHeader('Content-length', str(len(body)))
     request.setHeader('Content-type', responseType)
     request.setResponseCode(usage.successCode)
     defer.returnValue(body)
Esempio n. 21
0
    def deferred_render_PUT(self, request):
        usage = registry.findUsage(httpTagCategoryName, 'PUT', TagsResource)
        dictionary = registry.checkRequest(usage, request)

        description = dictionary.get('description') or ''

        yield self.facadeClient.updateTag(self.session,
                                          sep.join(request.postpath),
                                          description.encode('utf-8'))
        request.setResponseCode(usage.successCode)
Esempio n. 22
0
 def deferred_render_GET(self, request):
     # TODO: usages should be cached locally; lookup is expensive.
     usage = registry.findUsage(httpPermissionCategoryName, 'GET',
                                self.__class__)
     registry.checkRequest(usage, request)
     responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
     action = request.args[actionArg][0].lower()
     result = yield self.facadeClient.getPermission(
         self.session, self.category, action, sep.join(request.postpath))
     responseDict = {
         'policy': result.policy,
         'exceptions': list(result.exceptions),
     }
     registry.checkResponse(responseType, responseDict, usage, request)
     body = payloads.buildPayload(responseType, responseDict)
     request.setHeader('Content-length', str(len(body)))
     request.setHeader('Content-type', responseType)
     request.setResponseCode(usage.successCode)
     defer.returnValue(body)
Esempio n. 23
0
    def deferred_render_PUT(self, request):
        usage = registry.findUsage(httpTagCategoryName, 'PUT', TagsResource)
        dictionary = registry.checkRequest(usage, request)

        description = dictionary.get('description') or ''

        yield self.facadeClient.updateTag(self.session,
                                          sep.join(request.postpath),
                                          description.encode('utf-8'))
        request.setResponseCode(usage.successCode)
Esempio n. 24
0
 def deferred_render_GET(self, request):
     # TODO: usages should be cached locally; lookup is expensive.
     usage = registry.findUsage(httpPermissionCategoryName, 'GET',
                                self.__class__)
     registry.checkRequest(usage, request)
     responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)
     action = request.args[actionArg][0].lower()
     result = yield self.facadeClient.getPermission(
         self.session, self.category, action, sep.join(request.postpath))
     responseDict = {
         'policy': result.policy,
         'exceptions': list(result.exceptions),
     }
     registry.checkResponse(responseType, responseDict, usage, request)
     body = payloads.buildPayload(responseType, responseDict)
     request.setHeader('Content-length', str(len(body)))
     request.setHeader('Content-type', responseType)
     request.setResponseCode(usage.successCode)
     defer.returnValue(body)
Esempio n. 25
0
    def deferred_render_GET(self, request):
        """Render a response to a C{GET} request to C{recent/objects}

        @param request: a C{twisted.web.server.Request} specifying
            meta-information about the request.
        @return: A C{deferred} which fires with a JSON payload with the
            information about recent activity for the given object.
        """
        usage = registry.findUsage('recent', 'GET',
                                   RecentObjectActivityResource)
        registry.checkRequest(usage, request)

        recentActivity = yield self.facadeClient.getRecentObjectActivity(
            self.session, self.objectID)

        body = buildPayload('application/json', recentActivity)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', 'application/json')
        request.setResponseCode(http.OK)
        returnValue(body)
Esempio n. 26
0
    def deferred_render_GET(self, request):
        """Render a response to a C{GET} request to C{recent/objects}

        @param request: a C{twisted.web.server.Request} specifying
            meta-information about the request.
        @return: A C{deferred} which fires with a JSON payload with the
            information about recent activity for the given object.
        """
        usage = registry.findUsage('recent', 'GET',
                                   RecentObjectActivityResource)
        registry.checkRequest(usage, request)

        recentActivity = yield self.facadeClient.getRecentObjectActivity(
            self.session, self.objectID)

        body = buildPayload('application/json', recentActivity)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', 'application/json')
        request.setResponseCode(http.OK)
        returnValue(body)
Esempio n. 27
0
    def deferred_render_DELETE(self, request):
        """
        Handle a DELETE request for /values with a query and a list of
        wanted tags.

        @param request: The incoming C{twisted.web.server.Request} request.
        @return: A C{Deferred} which will fire when the request has
            completed.  The deferred may errback for a variety of reasons,
            for example an invalid query, the mention of a non-existent tag
            or a tag that the caller does not have DELETE permission for.
        """
        usage = registry.findUsage(httpValueCategoryName, 'DELETE',
                                   ValuesResource)
        registry.checkRequest(usage, request)
        query = request.args[queryArg][0]
        tags = request.args[tagArg]
        if tags == ['*']:
            tags = None
        yield self.facadeClient.deleteValuesForQuery(self.session, query, tags)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 28
0
    def deferred_render_DELETE(self, request):
        """
        Handle a DELETE request for /values with a query and a list of
        wanted tags.

        @param request: The incoming C{twisted.web.server.Request} request.
        @return: A C{Deferred} which will fire when the request has
            completed.  The deferred may errback for a variety of reasons,
            for example an invalid query, the mention of a non-existent tag
            or a tag that the caller does not have DELETE permission for.
        """
        usage = registry.findUsage(httpValueCategoryName, 'DELETE',
                                   ValuesResource)
        registry.checkRequest(usage, request)
        query = request.args[queryArg][0]
        tags = request.args[tagArg]
        if tags == ['*']:
            tags = None
        yield self.facadeClient.deleteValuesForQuery(self.session, query, tags)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 29
0
    def deferred_render_POST(self, request):
        """
        Create an object whose about value is the one given in the URI
        and return information about its object id and location.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with the body of the response.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'POST',
                                   AboutObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        objectId = yield self.facadeClient.createObject(
            session=self.session, about=self.about)

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        # Return the location of the new object by its id.
        location = '%s://%s/%s/%s' % (
            proto, hostname, httpObjectCategoryName,
            urllib.quote(objectId.encode('utf-8')))

        responseDict = {
            'id': objectId,
            'URI': location,
        }

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 30
0
    def deferred_render_POST(self, request):
        """
        Create an object whose about value is the one given in the URI
        and return information about its object id and location.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with the body of the response.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'POST',
                                   AboutObjectResource)
        registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        objectId = yield self.facadeClient.createObject(session=self.session,
                                                        about=self.about)

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        # Return the location of the new object by its id.
        location = '%s://%s/%s/%s' % (proto, hostname, httpObjectCategoryName,
                                      urllib.quote(objectId.encode('utf-8')))

        responseDict = {
            'id': objectId,
            'URI': location,
        }

        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 31
0
 def deferred_render_PUT(self, request):
     # TODO: usages should be cached locally; lookup is expensive.
     usage = registry.findUsage(httpPermissionCategoryName, 'PUT',
                                self.__class__)
     dictionary = registry.checkRequest(usage, request)
     action = request.args[actionArg][0].lower()
     policyAndExceptions = TPolicyAndExceptions(
         policy=dictionary['policy'],
         exceptions=set(dictionary['exceptions']))
     yield self.facadeClient.updatePermission(
         self.session, self.category, action, sep.join(request.postpath),
         policyAndExceptions)
     request.setResponseCode(usage.successCode)
Esempio n. 32
0
    def deferred_render_DELETE(self, request):
        """
        Delete a tag from an object. Return a Deferred that fires with None
        once the facade has done the deletion.

        The following code, apart from the yield self._setObjectId(), is
        taken verbatim from deferred_render_DELETE in objects.py. So if
        you change this code, you'll likely need to change that, and vice
        versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'DELETE',
                                   AboutTagInstanceResource)
        registry.checkRequest(usage, request)
        yield self._setObjectId()
        yield self.facadeClient.deleteTagInstance(self.session, self.path,
                                                  self.objectId)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 33
0
 def deferred_render_PUT(self, request):
     # TODO: usages should be cached locally; lookup is expensive.
     usage = registry.findUsage(httpPermissionCategoryName, 'PUT',
                                self.__class__)
     dictionary = registry.checkRequest(usage, request)
     action = request.args[actionArg][0].lower()
     policyAndExceptions = TPolicyAndExceptions(
         policy=dictionary['policy'],
         exceptions=set(dictionary['exceptions']))
     yield self.facadeClient.updatePermission(self.session, self.category,
                                              action,
                                              sep.join(request.postpath),
                                              policyAndExceptions)
     request.setResponseCode(usage.successCode)
Esempio n. 34
0
    def deferred_render_DELETE(self, request):
        """
        Delete a tag from an object. Return a Deferred that fires with None
        once the facade has done the deletion.

        The following code, apart from the yield self._setObjectId(), is
        taken verbatim from deferred_render_DELETE in objects.py. So if
        you change this code, you'll likely need to change that, and vice
        versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'DELETE',
                                   AboutTagInstanceResource)
        registry.checkRequest(usage, request)
        yield self._setObjectId()
        yield self.facadeClient.deleteTagInstance(
            self.session, self.path, self.objectId)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 35
0
    def deferred_render_PUT(self, request):
        usage = registry.findUsage(httpUserCategoryName, 'PUT',
                                   ConcreteUserResource)
        dictionary = registry.checkRequest(usage, request)

        name = dictionary.get('name')
        email = dictionary.get('email')
        password = dictionary.get('password')
        role = dictionary.get('role')

        # All args are optional. Don't bother the facade if there's nothing
        # to do.
        if name or email or password or role:
            update = TUserUpdate(username=self.username, name=name,
                                 email=email, password=password, role=role)

            yield self.facadeClient.updateUser(self.session, update)

        request.setResponseCode(usage.successCode)
Esempio n. 36
0
    def deferred_render_POST(self, request):
        usage = registry.findUsage(httpTagCategoryName, 'POST', TagsResource)
        dictionary = registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        parentNamespace = sep.join(request.postpath)
        name = dictionary['name']
        description = dictionary['description'] or ''
        indexed = dictionary['indexed']

        path = sep.join([parentNamespace, name.encode('utf-8')])

        objectId = yield self.facadeClient.createTag(
            session=self.session,
            parentNamespace=parentNamespace,
            name=name.encode('utf-8'),
            description=description.encode('utf-8'),
            indexed=indexed,
            # Always request a normal range. We don't let apps do anything
            # else yet.
            rangeType=TagRangeType.NORMAL_TYPE)

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        location = '%s://%s/%s/%s' % (
            proto, hostname, httpTagCategoryName,
            urllib.quote(path))

        responseDict = {
            'id': objectId,
            'URI': location,
        }
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 37
0
    def deferred_render_POST(self, request):
        usage = registry.findUsage(httpTagCategoryName, 'POST', TagsResource)
        dictionary = registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        parentNamespace = sep.join(request.postpath)
        name = dictionary['name']
        description = dictionary['description'] or ''
        indexed = dictionary['indexed']

        path = sep.join([parentNamespace, name.encode('utf-8')])

        objectId = yield self.facadeClient.createTag(
            session=self.session,
            parentNamespace=parentNamespace,
            name=name.encode('utf-8'),
            description=description.encode('utf-8'),
            indexed=indexed,
            # Always request a normal range. We don't let apps do anything
            # else yet.
            rangeType=TagRangeType.NORMAL_TYPE)

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        location = '%s://%s/%s/%s' % (proto, hostname, httpTagCategoryName,
                                      urllib.quote(path))

        responseDict = {
            'id': objectId,
            'URI': location,
        }
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 38
0
    def createFromRequest(cls, request, usage):
        """
        Construct the objects from an HTTP request and a usage.

        @param request: The request object.
        @param usage: The L{Usage} object.
        @return: a L{ValuesQuerySchema} object for the given request.
        """
        payload = registry.checkRequest(usage, request)

        contentType = request.getHeader('content-type')
        if contentType is None:
            raise error.NoContentTypeHeader()

        try:
            contentTypeParts = parse_mime_type(contentType)
        except ValueError:
            raise error.UnknownContentType()

        if contentTypeParts[:2] != ('application', 'json'):
            raise error.UnknownContentType()

        if queryArg in request.args:
            try:
                # Decode to unicode from the UTF-8 in the URI.
                query = request.args[queryArg][0].decode('utf-8')
            except UnicodeDecodeError:
                raise error.InvalidUTF8Argument(queryArg)
        else:
            query = None

        payloadDict = cls._getPayloadDict(payload)

        if query is None:
            queryItems = cls._parseNewPayloadDict(payloadDict)
        else:
            tagsAndValues = cls._parseOldPayloadDict(payloadDict)
            queryItems = [(query, tagsAndValues)]

        return ValuesQuerySchema(queryItems)
Esempio n. 39
0
    def createFromRequest(cls, request, usage):
        """
        Construct the objects from an HTTP request and a usage.

        @param request: The request object.
        @param usage: The L{Usage} object.
        @return: a L{ValuesQuerySchema} object for the given request.
        """
        payload = registry.checkRequest(usage, request)

        contentType = request.getHeader('content-type')
        if contentType is None:
            raise error.NoContentTypeHeader()

        try:
            contentTypeParts = parse_mime_type(contentType)
        except ValueError:
            raise error.UnknownContentType()

        if contentTypeParts[:2] != ('application', 'json'):
            raise error.UnknownContentType()

        if queryArg in request.args:
            try:
                # Decode to unicode from the UTF-8 in the URI.
                query = request.args[queryArg][0].decode('utf-8')
            except UnicodeDecodeError:
                raise error.InvalidUTF8Argument(queryArg)
        else:
            query = None

        payloadDict = cls._getPayloadDict(payload)

        if query is None:
            queryItems = cls._parseNewPayloadDict(payloadDict)
        else:
            tagsAndValues = cls._parseOldPayloadDict(payloadDict)
            queryItems = [(query, tagsAndValues)]

        return ValuesQuerySchema(queryItems)
Esempio n. 40
0
    def deferred_render_POST(self, request):
        usage = registry.findUsage(httpUserCategoryName, 'POST', UsersResource)
        dictionary = registry.checkRequest(usage, request)
        responseType = usage.getResponsePayloadTypeFromAcceptHeader(request)

        username = dictionary['username']
        name = dictionary.get('name', username)
        password = dictionary['password']
        email = dictionary['email']

        objectId = yield self.facadeClient.createUserWithPassword(
            session=self.session,
            username=username.encode('utf-8'),
            password=password.encode('utf-8'),
            name=name.encode('utf-8'),
            email=email.encode('utf-8'))

        if request.isSecure():
            proto = "https"
        else:
            proto = "http"
        hostname = request.getRequestHostname()

        location = '%s://%s/%s/%s' % (
            proto, hostname, httpUserCategoryName,
            urllib.quote(username.encode('utf-8')))

        responseDict = {
            'id': objectId,
            'URI': location,
        }
        registry.checkResponse(responseType, responseDict, usage, request)
        body = payloads.buildPayload(responseType, responseDict)
        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', responseType)
        request.setHeader('Location', location)
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 41
0
    def deferred_render_PUT(self, request):
        """
        The following code is reproduced almost verbatim in
        deferred_render_PUT in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, 'PUT',
                                   TagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentTypeFirstComponent = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            # Get the lowercased first component of the content type, as
            # split by semicolon (the HTTP standard for separating the
            # content type from other tags, such as charset).
            #
            # Doing it this way allows us to ignore any other crud in the
            # content-type, for example a charset, when the content type is
            # our own contentTypeForPrimitiveJSON. See
            # https://oodl.es/trac/fluiddb/ticket/572 and the
            # testPrimitiveTypesWithCharsetAlsoInContentType test in
            # integration/wsfe/test_tagValues.py for more details
            #
            # We only need to rstrip the first component of the content
            # type as twisted.web does a strip on the whole header value
            # (so the left side is already stripped).
            contentTypeFirstComponent = \
                contentType.split(';')[0].lower().rstrip()

        if contentTypeFirstComponent == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        # log.msg("PUT: tvalue is %r" % tvalue)
        yield self.facadeClient.setTagInstance(self.session, self.path,
                                               self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 42
0
 def deferred_render_DELETE(self, request):
     usage = registry.findUsage(httpUserCategoryName, 'DELETE',
                                ConcreteUserResource)
     registry.checkRequest(usage, request)
     yield self.facadeClient.deleteUser(self.session, self.username)
     request.setResponseCode(usage.successCode)
Esempio n. 43
0
    def deferred_render_PUT(self, request):
        """
        The following code is reproduced almost verbatim in
        deferred_render_PUT in about.py. So if you change this code,
        you'll likely need to change that, and vice versa.
        """
        usage = registry.findUsage(httpObjectCategoryName, 'PUT',
                                   TagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentTypeFirstComponent = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            # Get the lowercased first component of the content type, as
            # split by semicolon (the HTTP standard for separating the
            # content type from other tags, such as charset).
            #
            # Doing it this way allows us to ignore any other crud in the
            # content-type, for example a charset, when the content type is
            # our own contentTypeForPrimitiveJSON. See
            # https://oodl.es/trac/fluiddb/ticket/572 and the
            # testPrimitiveTypesWithCharsetAlsoInContentType test in
            # integration/wsfe/test_tagValues.py for more details
            #
            # We only need to rstrip the first component of the content
            # type as twisted.web does a strip on the whole header value
            # (so the left side is already stripped).
            contentTypeFirstComponent = \
                contentType.split(';')[0].lower().rstrip()

        if contentTypeFirstComponent == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        # log.msg("PUT: tvalue is %r" % tvalue)
        yield self.facadeClient.setTagInstance(
            self.session, self.path, self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 44
0
    def deferred_render_PUT(self, request):
        """
        PUT a tag value onto an object. Return a Deferred that fires with
        None when the tag value has been set by the facade.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from deferred_render_PUT in objects.py. So if you change
        this code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'PUT',
                                   AboutTagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentType = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            contentType = contentType.lower()

        if contentType == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        try:
            yield self._setObjectId()
        except error.NoSuchObject:
            # There is no object with this about value. So we create it.
            # This is consistent with /objects, which doesn't require an
            # object id to have been returned from createObject in order
            # for people to PUT tag values onto it.
            self.objectId = yield self.facadeClient.createObject(
                session=self.session, about=self.about)

        yield self.facadeClient.setTagInstance(
            self.session, self.path, self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 45
0
    def _GET_HEAD_common(self, request, verb):
        """
        I handle the common actions taken by GET and HEAD requests, which
        are virtually identical, except HEAD drops the body.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from _GET_HEAD_common in objects.py. So if you change this
        code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.
        @param verb: A C{str}, either 'GET' or 'HEAD'.

        @return: A C{Deferred} which fires with the body of a GET request,
                 having set all the response headers that are common to GET
                 and HEAD.  (The body will be dropped (below) for HEAD
                 requests.)
        """
        usage = registry.findUsage(httpAboutCategoryName, verb,
                                   AboutTagInstanceResource)

        registry.checkRequest(usage, request)
        yield self._setObjectId()

        # This will raise TNoInstanceOnObject if there's no instance,
        # and that will return a 404 (see util.py).
        tvalue, tagValue = yield self.facadeClient.getTagInstance(
            self.session, self.path, self.objectId)
        value = guessValue(tvalue)
        accept = request.getHeader('accept') or '*/*'

        if tvalue.valueType == ThriftValueType.BINARY_TYPE:
            contentType = tvalue.binaryKeyMimeType
            if mimeparse.best_match([contentType], accept) == '':
                raise error.NotAcceptable()
            body = value
            # Mark this value as unwrappable for JSON
            request._fluiddb_jsonp_unwrappable = None
        else:
            contentType = mimeparse.best_match(
                contentTypesForPrimitiveValue, accept)
            if contentType == '':
                raise error.NotAcceptable()
            try:
                serializer = util.primitiveTypeSerializer[contentType]
            except KeyError:
                raise TInternalError('No serializer for %r.' % contentType)
            else:
                body = serializer(value)

            typeValue = self._getTypeHeader(tvalue.valueType)
            request.setHeader(util.buildHeader('Type'), typeValue)

        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', contentType)
        # setting the Last-Modified header for fluiddb/id makes no sense
        if tagValue and tagValue.creationTime:
            request.setHeader(
                'Last-modified',
                tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S'))
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)
Esempio n. 46
0
    def deferred_render_PUT(self, request):
        """
        PUT a tag value onto an object. Return a Deferred that fires with
        None when the tag value has been set by the facade.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from deferred_render_PUT in objects.py. So if you change
        this code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.

        @return: A C{Deferred} that fires with C{None} once the request has
                 completed.
        """
        usage = registry.findUsage(httpAboutCategoryName, 'PUT',
                                   AboutTagInstanceResource)
        payload = registry.checkRequest(usage, request)
        contentType = request.getHeader('content-type')

        if contentType is None:
            if payload is None:
                contentType = contentTypeForPrimitiveJSON
            else:
                raise error.NoContentTypeHeader()
        else:
            contentType = contentType.lower()

        if contentType == contentTypeForPrimitiveJSON:
            if payload is None:
                value = None
            else:
                value = payloads.parseJSONPayload(payload)
            tv = type(value)
            if tv in (bool, int, float, unicode, types.NoneType):
                tvalue = createThriftValue(value)
            elif tv is list:
                strlist = []
                for s in value:
                    if isinstance(s, unicode):
                        s = s.encode("utf-8")
                    elif not isinstance(s, str):
                        raise error.UnsupportedJSONType()
                    strlist.append(s)
                tvalue = createThriftValue(strlist)
            else:
                raise error.UnsupportedJSONType()
        else:
            tvalue = createBinaryThriftValue(payload, contentType)

        try:
            yield self._setObjectId()
        except error.NoSuchObject:
            # There is no object with this about value. So we create it.
            # This is consistent with /objects, which doesn't require an
            # object id to have been returned from createObject in order
            # for people to PUT tag values onto it.
            self.objectId = yield self.facadeClient.createObject(
                session=self.session, about=self.about)

        yield self.facadeClient.setTagInstance(self.session, self.path,
                                               self.objectId, tvalue)
        request.setResponseCode(usage.successCode)
        defer.returnValue(None)
Esempio n. 47
0
    def _GET_HEAD_common(self, request, verb):
        """
        I handle the common actions taken by GET and HEAD requests, which
        are virtually identical, except HEAD drops the body.

        This code, apart from the yield self._setObjectId(), is taken
        verbatim from _GET_HEAD_common in objects.py. So if you change this
        code, you'll likely need to change that, and vice versa.

        @param request: The HTTP request.
        @param verb: A C{str}, either 'GET' or 'HEAD'.

        @return: A C{Deferred} which fires with the body of a GET request,
                 having set all the response headers that are common to GET
                 and HEAD.  (The body will be dropped (below) for HEAD
                 requests.)
        """
        usage = registry.findUsage(httpAboutCategoryName, verb,
                                   AboutTagInstanceResource)

        registry.checkRequest(usage, request)
        yield self._setObjectId()

        # This will raise TNoInstanceOnObject if there's no instance,
        # and that will return a 404 (see util.py).
        tvalue, tagValue = yield self.facadeClient.getTagInstance(
            self.session, self.path, self.objectId)
        value = guessValue(tvalue)
        accept = request.getHeader('accept') or '*/*'

        if tvalue.valueType == ThriftValueType.BINARY_TYPE:
            contentType = tvalue.binaryKeyMimeType
            if mimeparse.best_match([contentType], accept) == '':
                raise error.NotAcceptable()
            body = value
            # Mark this value as unwrappable for JSON
            request._fluiddb_jsonp_unwrappable = None
        else:
            contentType = mimeparse.best_match(contentTypesForPrimitiveValue,
                                               accept)
            if contentType == '':
                raise error.NotAcceptable()
            try:
                serializer = util.primitiveTypeSerializer[contentType]
            except KeyError:
                raise TInternalError('No serializer for %r.' % contentType)
            else:
                body = serializer(value)

            typeValue = self._getTypeHeader(tvalue.valueType)
            request.setHeader(util.buildHeader('Type'), typeValue)

        request.setHeader('Content-length', str(len(body)))
        request.setHeader('Content-type', contentType)
        # setting the Last-Modified header for fluiddb/id makes no sense
        if tagValue and tagValue.creationTime:
            request.setHeader(
                'Last-modified',
                tagValue.creationTime.strftime('%a, %d %b %Y %H:%M:%S'))
        request.setResponseCode(usage.successCode)
        defer.returnValue(body)