def testQueryParseErrorNoPath(self): # This query does not parse because 'big' is not a path (no slash). query = 'has big' d = self.query(query) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): TParseError.__name__}) d.addErrback(self.checkErrorHeaders, {buildHeader('Query'): query}) d.addErrback(self.checkErrorHeaders, {buildHeader('Message'): "Illegal character u'b'."}) self.failUnlessFailure(d, Error) yield d
def testQueryParseErrorExtraParen(self): query = 'has big/feet except has (big/ears' d = self.query(query) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): TParseError.__name__}) d.addErrback(self.checkErrorHeaders, {buildHeader('Query'): query}) d.addErrback( self.checkErrorHeaders, {buildHeader('Message'): "Syntax error: production.value = u'('"}) self.failUnlessFailure(d, Error) yield d
def render(self, request): log.msg('Request %s: NoResource: %s, status %s' % (request._fluidDB_reqid, request.uri, self.code)) request.setResponseCode(self.code) request.setHeader(buildHeader('Error-Class'), 'NoSuchResource') request.setHeader(buildHeader('Request-Id'), request._fluidDB_reqid) request.setHeader('content-type', 'text/html') return ("""<html> <head><title>%s - %s</title></head> <body><h1>%s</h1> <p>%s</p> </body></html>\n\n""" % (self.code, self.brief, self.brief, self.detail))
def testMissingQuery(self): """ If no query= argument is given in the URI, we should get a BAD_REQUEST error, with appropriately set error headers. """ d = self.getPage(queryDict={tagArg: _usernamePath}) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.MissingArgument.__name__, buildHeader('argument'): queryArg}) self.failUnlessFailure(d, Error) yield d
def render(self, request): log.msg('Request %s: NoResource: %s, status %s' % ( request._fluidDB_reqid, request.uri, self.code)) request.setResponseCode(self.code) request.setHeader(buildHeader('Error-Class'), 'NoSuchResource') request.setHeader(buildHeader('Request-Id'), request._fluidDB_reqid) request.setHeader('content-type', 'text/html') return ("""<html> <head><title>%s - %s</title></head> <body><h1>%s</h1> <p>%s</p> </body></html>\n\n""" % (self.code, self.brief, self.brief, self.detail))
def _prepareErrorResponse(requestID, code, message, requestPayload=None): """Handle a failure in the request. @param requestID: Either the request id from the incoming request or C{None} if the request had no id. @param code: An C{int} error code. @param message: A C{str} error message. @param requestPayload: A C{str} with the request payload, or C{None} if no payload was present or extractable. @return: The C{str} body of a JSON RPC error response. """ errorHeader = buildHeader('Request-Id') body = dumps({ 'id': requestID, 'error': { 'code': code, 'message': message }, 'jsonrpc': '2.0' }) requestPayload = requestPayload or '<Payload empty or unparseable>' if len(requestPayload) > 500: requestPayload = (requestPayload[:500] + ' ... <payload truncated for logging>') logging.info('JSON RPC error. Request payload: %s. ' 'Response payload: %s' % (requestPayload, body)) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setHeader(errorHeader, request._fluidDB_reqid) request.setResponseCode(OK) return body
def testBadExceptionTypes(self): headers = { 'content-type': 'application/json', } self.addBasicAuthHeader(headers) path = defaults.sep.join( [defaults.namespaceCategoryName, defaults.adminUsername]) for field in ('exceptions', ): data = { 'policy': 'open', 'exceptions': [], } for value in ('x', None, 3, 6.7, True, False, [6, 'y'], {'x': 3}): data[field] = value d = self.getPage(path, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, { buildHeader('Error-Class'): error.InvalidPayloadField.__name__ }) self.failUnlessFailure(d, Error) yield d
def testPUTWithNoContentTypeButWithPayload(self): """ Check that if we attempt a PUT with a payload but don't send a Content-Type, we get a BAD_REQUEST response and a NoContentTypeHeader response error-class header. """ about = 'africa' tag = 'ntoll/binary' payload = 'random payload' objectIdAboutAfrica = util.generateObjectId() fakeQueryResolver = FakeQueryResolver( about, [objectIdAboutAfrica], self) fakeTagsClient = FakeTagsClient() facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient, fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) # Test PUT. headers = { 'Content-Length': [str(len(payload))], } d = defer.Deferred() request = FakeRequest('PUT', d, headers) request.content = StringIO.StringIO(payload) resource.render(request) yield d self.assertEqual(request.status, http.BAD_REQUEST) self.assertEqual( request.getResponseHeader(buildHeader('Error-Class')), error.NoContentTypeHeader.__name__)
def testGetUserWithUnknownUnicodeUsername(self): """ Getting a user that doesn't exist, with a unicode username, correctly returns an C{HTTP 400 Not Found} status and a C{X-FluidDB-Error-Class} header with a C{TNoSuchUser} value. """ username = u'\N{HIRAGANA LETTER A}' headers = {'accept': 'application/json'} self.addBasicAuthHeader(headers) deferred = self.getPage(urllib.quote(username.encode('utf-8')), headers=headers) deferred.addErrback(self.checkErrorStatus, http.NOT_FOUND) deferred.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): 'TNoSuchUser', buildHeader('Name'): username.encode('utf-8')}) return self.assertFailure(deferred, Error)
def testBadTypes(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) for field in ('username', 'name', 'password', 'email'): data = { 'username': '******', 'name': 'new', 'password': '******', 'email': 'email', } for value in (None, 3, 6.7, True, False, ['a', 'list'], {'x': 3}): data[field] = value d = self.getPage('', headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, { buildHeader('Error-Class'): error.InvalidPayloadField.__name__ }) self.failUnlessFailure(d, Error) yield d
def testPUTSetOfStringsNotAllStrings(self): """ PUT a set of strings (that are in fact not all strings) value for ntoll/rating onto the object about africa. This should result in a BAD_REQUEST status and an UnsupportedJSONType error class. """ about = 'africa' tag = 'ntoll/rating' tagset = ['good', 'bad', 6] objectIdAboutAfrica = util.generateObjectId() fakeQueryResolver = FakeQueryResolver( about, [objectIdAboutAfrica], self) fakeTagsClient = FakeTagsClient() facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient, fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) # Test PUT. payload = json.dumps(tagset) headers = { 'Content-Length': [str(len(payload))], 'Content-Type': [contentTypeForPrimitiveJSON], } d = defer.Deferred() request = FakeRequest('PUT', d, headers) request.content = StringIO.StringIO(payload) resource.render(request) yield d self.assertEqual(request.status, http.BAD_REQUEST) self.assertEqual( request.getResponseHeader(buildHeader('Error-Class')), error.UnsupportedJSONType.__name__)
def testBadTypes(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) for field in ('username', 'name', 'password', 'email'): data = { 'username': '******', 'name': 'new', 'password': '******', 'email': 'email', } for value in (None, 3, 6.7, True, False, ['a', 'list'], {'x': 3}): data[field] = value d = self.getPage('', headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.InvalidPayloadField.__name__}) self.failUnlessFailure(d, Error) yield d
def testPUTWithNoContentTypeButWithPayload(self): """ Check that if we attempt a PUT with a payload but don't send a Content-Type, we get a BAD_REQUEST response and a NoContentTypeHeader response error-class header. """ about = 'africa' tag = 'ntoll/binary' payload = 'random payload' objectIdAboutAfrica = util.generateObjectId() fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica], self) fakeTagsClient = FakeTagsClient() facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient, fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) # Test PUT. headers = { 'Content-Length': [str(len(payload))], } d = defer.Deferred() request = FakeRequest('PUT', d, headers) request.content = StringIO.StringIO(payload) resource.render(request) yield d self.assertEqual(request.status, http.BAD_REQUEST) self.assertEqual(request.getResponseHeader(buildHeader('Error-Class')), error.NoContentTypeHeader.__name__)
def assertXFluidDBHeaderForType(self, method, value, expectedTypeString): """ Helper method to check if a resource is returning the appropriate C{X-FluidDB-Type} header for a given HTTP method. @param method: The HTTP method to use. Should be 'GET' or 'HEAD'. @param value: The value to test. @param expectedTypeString: The expected string that should be returned by C{X-FluidDB-Type}. """ facadeClient = FakeFacade() session = FakeSession() # Tell our FakeFacade to preload some data for a given tag. facadeClient.values = { 'fe2f50c8-997f-4049-a180-9a37543d001d': { 'tag/test': value}} resource = TagInstanceResource(facadeClient, session, 'fe2f50c8-997f-4049-a180-9a37543d001d', 'tag/test') request = FakeRequest(method=method) yield getattr(resource, 'render_' + method)(request) typeValue = request.getResponseHeader(buildHeader('Type')) self.assertEqual(expectedTypeString, typeValue)
def testPUTSetOfStringsNotAllStrings(self): """ PUT a set of strings (that are in fact not all strings) value for ntoll/rating onto the object about africa. This should result in a BAD_REQUEST status and an UnsupportedJSONType error class. """ about = 'africa' tag = 'ntoll/rating' tagset = ['good', 'bad', 6] objectIdAboutAfrica = util.generateObjectId() fakeQueryResolver = FakeQueryResolver(about, [objectIdAboutAfrica], self) fakeTagsClient = FakeTagsClient() facadeClient = FakeFacadeClient(fakeTagsClient=fakeTagsClient, fakeQueryResolver=fakeQueryResolver) session = FakeSession() resource = AboutTagInstanceResource(facadeClient, session, about, tag) # Test PUT. payload = json.dumps(tagset) headers = { 'Content-Length': [str(len(payload))], 'Content-Type': [contentTypeForPrimitiveJSON], } d = defer.Deferred() request = FakeRequest('PUT', d, headers) request.content = StringIO.StringIO(payload) resource.render(request) yield d self.assertEqual(request.status, http.BAD_REQUEST) self.assertEqual(request.getResponseHeader(buildHeader('Error-Class')), error.UnsupportedJSONType.__name__)
def _prepareErrorResponse(requestID, code, message, requestPayload=None): """Handle a failure in the request. @param requestID: Either the request id from the incoming request or C{None} if the request had no id. @param code: An C{int} error code. @param message: A C{str} error message. @param requestPayload: A C{str} with the request payload, or C{None} if no payload was present or extractable. @return: The C{str} body of a JSON RPC error response. """ errorHeader = buildHeader('Request-Id') body = dumps({ 'id': requestID, 'error': { 'code': code, 'message': message}, 'jsonrpc': '2.0'}) requestPayload = requestPayload or '<Payload empty or unparseable>' if len(requestPayload) > 500: requestPayload = (requestPayload[:500] + ' ... <payload truncated for logging>') logging.info('JSON RPC error. Request payload: %s. ' 'Response payload: %s' % (requestPayload, body)) request.setHeader('Content-length', str(len(body))) request.setHeader('Content-type', 'application/json') request.setHeader(errorHeader, request._fluidDB_reqid) request.setResponseCode(OK) return body
def testNameEmpty(self): name = '' d = self.createRandomUser(username=name) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): TInvalidUsername.__name__}) self.failUnlessFailure(d, Error) return d
def testNameTooLong(self): name = (users.maxUsernameLength + 1) * 'x' d = self.createRandomUser(username=name) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): TUsernameTooLong.__name__}) self.failUnlessFailure(d, Error) return d
def testNameEmpty(self): name = '' d = self.createRandomUser(username=name) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TInvalidUsername.__name__}) self.failUnlessFailure(d, Error) return d
def testGetUserWithUnknownUnicodeUsername(self): """ Getting a user that doesn't exist, with a unicode username, correctly returns an C{HTTP 400 Not Found} status and a C{X-FluidDB-Error-Class} header with a C{TNoSuchUser} value. """ username = u'\N{HIRAGANA LETTER A}' headers = {'accept': 'application/json'} self.addBasicAuthHeader(headers) deferred = self.getPage(urllib.quote(username.encode('utf-8')), headers=headers) deferred.addErrback(self.checkErrorStatus, http.NOT_FOUND) deferred.addErrback( self.checkErrorHeaders, { buildHeader('Error-Class'): 'TNoSuchUser', buildHeader('Name'): username.encode('utf-8') }) return self.assertFailure(deferred, Error)
def testNonExistentTag(self): objectId = yield self.createObject() d = self.setTagValue('xx/yy/zz', objectId, '5') d.addErrback(self.checkErrorStatus, http.NOT_FOUND) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TNonexistentTag.__name__}) self.failUnlessFailure(d, Error) yield d
def testNonType4ObjectId(self): aboutPath = defaults.sep.join(paths.aboutPath()) d = self.getTagValue(aboutPath, base.nonType4ObjectIdStr()) d.addErrback(self.checkErrorStatus, http.NOT_FOUND) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TNoInstanceOnObject.__name__}) self.failUnlessFailure(d, Error) return d
def testNonsenseAccept(self): objectId = yield self.createObject() d = self.getObject(str(objectId), accept='x/y') d.addErrback(self.checkErrorStatus, http.NOT_ACCEPTABLE) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NotAcceptable.__name__}) self.failUnlessFailure(d, Error) yield d
def testRidiculousObjectId(self): objectId = 'hey!' d = self.deleteTagValue(defaults.sep.join(paths.aboutPath()), objectId) d.addErrback(self.checkErrorStatus, http.NOT_FOUND) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NoSuchResource.__name__}) self.failUnlessFailure(d, Error) return d
def testRepeatedArgument(self): argument = 'returnDescription' headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) d = self.getPage('%s?%s=True&%s=True' % (defaults.adminUsername, argument, argument), headers=headers) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.MultipleArgumentValues.__name__, buildHeader('argument'): argument}) self.failUnlessFailure(d, Error) yield d
def testPathTooLong(self): n = paths.maxPathLength - len(defaults.adminUsername) name = 'X' * n d = self.createTag(name, defaults.adminUsername) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback(self.checkErrorHeaders, {buildHeader('Error-Class'): TInvalidPath.__name__}) self.failUnlessFailure(d, Error) return d
def testNameTooLong(self): name = (users.maxUsernameLength + 1) * 'x' d = self.createRandomUser(username=name) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TUsernameTooLong.__name__}) self.failUnlessFailure(d, Error) return d
def testPathTooLong(self): n = paths.maxPathLength - len(defaults.adminUsername) name = 'X' * n d = self.createTag(name, defaults.adminUsername) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TInvalidPath.__name__}) self.failUnlessFailure(d, Error) return d
def testUnknownPayloadField(self): headers = { 'content-type': 'application/json', } self.addBasicAuthHeader(headers) data = { 'dummy': 'A dummy value', 'name': 'Joe the plumber', 'email': '*****@*****.**', } d = self.getPage(defaults.adminUsername, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.UnknownPayloadField.__name__, buildHeader('fieldName'): 'dummy'}) self.failUnlessFailure(d, Error) return d
def testNotAcceptableMIMEvMIME(self): path = 'fluiddb/testing/test1' objectId = yield self.createObject() primitiveOrAnything = '%s, */*' % defaults.contentTypeForPrimitiveJSON # data is given as a tuple of tuples. Each sub-tuple has 3 things: # a value, the accept string with which to try GETting the value, # and a flag to indicate whether the GET is expected to succeed. # The value may be a (x, ct) pair, where x is the actual value to # be PUT and ct is the content-type to PUT it with. testdata = [ (('xxx', 'application/pdf'), 'no/pdf', False), (('xxx', 'application/pdf'), 'application/pdf', True), (('xxx', 'application/pdf'), 'application/pdf, */*', True), (('xxx', 'yyy/zzz'), defaults.contentTypeForPrimitiveJSON, False), ] for value in (True, False, 4, 7.3, None, 'ducks', ['Hey', 'Jude']): for ct in ('application/pdf', 'text/plain', 'xx/yy, ii/jj; q=0.5'): testdata.append((value, ct, False)) for ct in ('*/*', defaults.contentTypeForPrimitiveJSON, primitiveOrAnything): testdata.append((value, ct, True)) try: for value, accept, succeed in testdata: if type(value) is tuple: value, ct = value yield self.setTagValue( path, objectId, value, contentType=ct) d = self.getTagValueAndContentType( path, objectId, accept=accept) if succeed: result, resultCt = yield d self.assertEqual(value, result) self.assertEqual(ct, resultCt) else: yield self.setTagValue(path, objectId, value) d = self.getTagValue(path, objectId, accept=accept) if succeed: result = yield d self.assertEqual(value, result) if not succeed: d.addErrback(self.checkErrorStatus, http.NOT_ACCEPTABLE) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NotAcceptable.__name__}) self.failUnlessFailure(d, Error) yield d finally: yield self.deleteTagValue(path, objectId)
def render(self, request): msg = 'ErrorResource: status %r' % self.status request.setResponseCode(self.status) headers = self.headers headers.setdefault('Error-Class', self.errorClass.__name__) headers.setdefault('Request-Id', request._fluidDB_reqid) for key, value in headers.iteritems(): request.setHeader(buildHeader(key), value) msg += (', %s=%r' % (key, value)) log.msg(msg) request.finish() return server.NOT_DONE_YET
def testUnknownPayloadType(self): headers = { 'content-type': 'application/WTF', } self.addBasicAuthHeader(headers) d = self.getPage(defaults.adminUsername, headers=headers, postdata='x') d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.UnknownContentType.__name__}) self.failUnlessFailure(d, Error) return d
def testUnknownPayloadField(self): headers = { 'content-type': 'application/json', } self.addBasicAuthHeader(headers) data = { 'dummy': 'A dummy value', 'name': 'Joe the plumber', 'email': '*****@*****.**', } d = self.getPage(defaults.adminUsername, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, { buildHeader('Error-Class'): error.UnknownPayloadField.__name__, buildHeader('fieldName'): 'dummy' }) self.failUnlessFailure(d, Error) return d
def testListContainingNonString(self): path = 'fluiddb/testing/test1' objectId = yield self.createObject() try: d = self.setTagValue(path, objectId, ['hi', 6]) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.UnsupportedJSONType.__name__}) self.failUnlessFailure(d, Error) yield d finally: yield self.deleteTagValue(path, objectId)
def testNoContentType(self): headers = {} self.addBasicAuthHeader(headers) data = { 'description': 'A totally new description.', } d = self.getPage(defaults.adminUsername, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NoContentTypeHeader.__name__}) self.failUnlessFailure(d, Error) yield d
def testNoQuery(self): headers = { 'accept': 'application/json', } self.addBasicAuthHeader(headers) d = getPage('%s/%s' % (self.endpoint, defaults.httpObjectCategoryName), headers=headers, method='GET') d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.MissingArgument.__name__}) self.failUnlessFailure(d, Error) return d
def testUnexpectedPayload(self): # Put rubbish into the payload to trigger an error. headers = { 'accept': 'application/json', } self.addBasicAuthHeader(headers) d = self.getPage(defaults.adminUsername, headers=headers, postdata='x') d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.UnexpectedContentLengthHeader.__name__}) self.failUnlessFailure(d, Error) return d
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)
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)
def testNoContentType(self): headers = {} self.addBasicAuthHeader(headers) data = { 'name': 'Joe the plumber', 'email': '*****@*****.**', } d = self.getPage(defaults.adminUsername, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NoContentTypeHeader.__name__}) self.failUnlessFailure(d, Error) return d
def testUnexpectedPayload(self): # Put rubbish into the payload to trigger an error. headers = { 'accept': 'application/json', } self.addBasicAuthHeader(headers) d = self.getPage(defaults.adminUsername, headers=headers, postdata='x') d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, { buildHeader('Error-Class'): error.UnexpectedContentLengthHeader.__name__ }) self.failUnlessFailure(d, Error) return d
def testPayloadWithNoContentType(self): headers = {} self.addBasicAuthHeader(headers) objectId = yield self.createObject() uri = '%s/%s/%s/dummy' % ( self.endpoint, defaults.httpObjectCategoryName, str(objectId)) d = getPage(uri, headers=headers, postdata=json.dumps('x'), method='PUT') d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.NoContentTypeHeader.__name__}) self.failUnlessFailure(d, Error) yield d
def testUnknownPayloadField(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) data = { 'xxx_about': 'wee-hoo', } d = getPage('%s/%s' % (self.endpoint, defaults.httpObjectCategoryName), headers=headers, method='POST', postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.UnknownPayloadField.__name__}) self.failUnlessFailure(d, Error) return d
def testMissingAction(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) data = { 'policy': 'closed', 'exceptions': [], } path = defaults.sep.join([ defaults.namespaceCategoryName, defaults.adminUsername]) d = self.getPage(path, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.MissingArgument.__name__}) self.failUnlessFailure(d, Error) return d
def testInvalidPolicy(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) data = { 'policy': 'ajar', 'exceptions': [], } path = defaults.sep.join([ defaults.namespaceCategoryName, defaults.adminUsername]) d = self.getPage(path, headers=headers, postdata=json.dumps(data), queryDict={'action': 'LIST'}) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): TInvalidPolicy.__name__}) self.failUnlessFailure(d, Error) return d
def testBadTypes(self): headers = { 'content-type': 'application/json', } self.addBasicAuthHeader(headers) for field in ('description',): data = { 'description': 'description', } for value in (3, 6.7, True, False, ['a', 'list'], {'x': 3}): data[field] = value d = self.getPage('whatever', headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.InvalidPayloadField.__name__, }) self.failUnlessFailure(d, Error) yield d
def assertXFluidDBHeaderForType(self, method, value, expectedTypeString): """ L{TagInstanceResource.render_HEAD} should put an X-FluidDB-Type header indicating the type of the value that it's returning. This tests checks float types. """ facadeClient = SimpleFakeFacade() session = FakeSession() # Tell our FakeFacade to preload some data for a given tag. facadeClient.values = { 'fe2f50c8-997f-4049-a180-9a37543d001d': { 'tag/test': value, 'fluiddb/about': 'about tag'}} resource = AboutTagInstanceResource(facadeClient, session, 'about tag', 'tag/test') request = FakeRequest(method, {}, {}, '') yield getattr(resource, 'render_' + method)(request) typeValue = request.getResponseHeader(buildHeader('Type')) self.assertEqual(expectedTypeString, typeValue)
def testBadIndexedTypes(self): headers = { 'accept': 'application/json', 'content-type': 'application/json', } self.addBasicAuthHeader(headers) for field in ('indexed',): data = { 'name': 'name', 'description': 'description', 'indexed': True, } for value in (None, 3, 6.7, ['a', 'list'], {'x': 3}): data[field] = value d = self.getPage('%s' % defaults.adminUsername, headers=headers, postdata=json.dumps(data)) d.addErrback(self.checkErrorStatus, http.BAD_REQUEST) d.addErrback( self.checkErrorHeaders, {buildHeader('Error-Class'): error.InvalidPayloadField.__name__}) self.failUnlessFailure(d, Error) yield d