예제 #1
0
    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "waffleProcessors": [{
                    "versions": [1]
                }]
            }]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": "OK"
            })

        return self.api.test("/v1/example",
                             method="WAFFlE").addCallback(rendered)
예제 #2
0
def run(host="localhost", user="******", password="******", database="opendkim", bindAddress='', bindPort=8000):
    "This program runs a web server to retrieve reputation data from the opendkim database"

    outputRegistry = OutputRegistry('application/reputon+json')
    outputRegistry.register('application/reputon+json', jsonDateFormatter)
    outputRegistry.register('text/html', jsonDateFormatter)
    api = SaratogaAPI(DKIM, DKIM_APIDef, serviceClass=Database(user=user, password=password, host=host, database=database),
                      outputRegistry=outputRegistry)
    api.run(port=bindPort)
예제 #3
0
파일: api.py 프로젝트: hawkowl/twinodedns
def makeService(options): # pragma: no cover
    """
    Make a service.

    @param options: The option parameters.
    @return: A service.
    """
            
    fp = getModule(__name__).filePath.parent().child("api.json")
    sc = api_impl.TwinodeServiceClass(options['dbname'])
    api = SaratogaAPI(api_impl.TwinodeAPI, json.load(fp.open()), serviceClass=sc)

    site = server.Site(api.getResource())
    return strports.service(options['port'], site)
예제 #4
0
    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {"versions": [1]},
            "endpoints": [
                {
                    "endpoint": "example",
                    "waffleProcessors": [{"versions": [1]}]
                }
            ]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": "OK"}
            )

        return self.api.test("/v1/example", method="WAFFlE").addCallback(rendered)
예제 #5
0
    def test_missingImplementationInVersion(self):
        class APIImpl(object):
            class v1(object):
                def example_GET(self, request, params):
                    """"""

            class v2(object):
                """"""

        APIDef = {
            "metadata": {
                "versions": [1, 2]
            },
            "endpoints": [{
                "endpoint": "example",
                "getProcessors": [{
                    "versions": [1, 2]
                }]
            }]
        }

        try:
            SaratogaAPI(APIImpl, APIDef)
        except Exception, e:
            self.assertEqual(
                e.message,
                "Implementation is missing the GET processor in the v2 example "
                "endpoint")
예제 #6
0
    def test_missingMetadata(self):
        APIDef = {"endpoints": []}

        try:
            SaratogaAPI(APIImpl, APIDef)
        except Exception, e:
            self.assertEqual(e.message,
                             "Definition requires a metadata section.")
예제 #7
0
def run(host="localhost",
        user="******",
        password="******",
        database="opendkim",
        bindAddress='',
        bindPort=8000):
    "This program runs a web server to retrieve reputation data from the opendkim database"

    outputRegistry = OutputRegistry('application/reputon+json')
    outputRegistry.register('application/reputon+json', jsonDateFormatter)
    outputRegistry.register('text/html', jsonDateFormatter)
    api = SaratogaAPI(DKIM,
                      DKIM_APIDef,
                      serviceClass=Database(user=user,
                                            password=password,
                                            host=host,
                                            database=database),
                      outputRegistry=outputRegistry)
    api.run(port=bindPort)
예제 #8
0
    def test_serviceClass(self):
        """
        Test to make sure it uses the service class you tell it.
        """
        class Foo(object):
            pass

        serviceClass = Foo()
        api = SaratogaAPI(APIImpl, APIDef, serviceClass)
        self.assertEqual(api.serviceClass, serviceClass)
예제 #9
0
    def test_missingVersionClass(self):
        APIDef = {
            "metadata": {
                "versions": [1, 2]
            },
            "endpoints": [{
                "endpoint": "example",
                "getProcessors": [{
                    "versions": [1, 2]
                }]
            }]
        }

        try:
            SaratogaAPI(APIImpl, APIDef)
        except Exception, e:
            self.assertEqual(e.message, "Implementation is missing version 2")
예제 #10
0
    def test_undeclaredVersion(self):
        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "getProcessors": [{
                    "versions": [1, 2]
                }]
            }]
        }

        try:
            SaratogaAPI(APIImpl, APIDef)
        except Exception, e:
            self.assertEqual(
                e.message,
                "Version mismatch - 2 in example is not a declared version")
예제 #11
0
from saratoga.api import SaratogaAPI
import json


class ExampleAPI(object):
    class v1(object):
        def example_GET(self, request, params):
            raise Exception("oh no!")


SaratogaAPI(ExampleAPI, json.load(open("simple.json"))).run()
예제 #12
0
import json
from saratoga.api import SaratogaAPI

class PlanetAPI(object):
    class v1(object):
        def yearlength_GET(self, request, params):
            planetName = params["params"]["name"].lower()
            if planetName == "earth":
                return {"seconds": 31536000}
            elif planetName == "pluto":
                return {"seconds": 7816176000}

APIDescription = json.load(open("planets.json"))
myAPI = SaratogaAPI(PlanetAPI, APIDescription)
myAPI.run(port=8094)
예제 #13
0
    def test_customOutputFormatRegistry(self):

        o = OutputRegistry("application/json")
        api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o)
        self.assertIs(o, api.outputRegistry)
예제 #14
0
 def setUp(self):
     self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())
예제 #15
0
    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path, "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)
예제 #16
0
from saratoga.api import SaratogaAPI
import json


class ServiceClassExample(object):
    stuff = "foo"


class ExampleAPI(object):
    class v1(object):
        def example_GET(self, request, params):
            return self.stuff


api = SaratogaAPI(ExampleAPI,
                  json.load(open("simple.json")),
                  serviceClass=ServiceClassExample())
api.run()
예제 #17
0
 def setUp(self):
     self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())
예제 #18
0
class SaratogaAPITestsWithAuthenticator(TestCase):
    def setUp(self):
        self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())

    def test_wrongPasswordBasicAuth(self):
        """
        Test that a wrong password with BASIC auth is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication failed."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:word"))]
                             }).addCallback(rendered)

    def test_malformedAuthHeader(self):
        """
        Test that something that a malformed auth header is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Malformed Authorization header."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization": ["BASIC HITHERE"]
                             }).addCallback(rendered)

    def test_weirdAuthorizationHeader(self):
        """
        Test that weird auth headers are handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Malformed Authorization header."
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:pass:word"))]
                             }).addCallback(rendered)

    def test_unsupportedAuthType(self):
        """
        Test that a malformed auth header is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "fail",
                    "data": "Unsupported Authorization type "
                    "'OMGLOLAUTH'"
                })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["OMGLOLAUTH FIODGNDSEGOUER"]
                             }).addCallback(rendered)

    def test_noAuthTypeGiven(self):
        """
        Test that something that Saratoga doesn't support is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication required."
            })

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_correctBasicAuth(self):
        """
        Test that authentication works.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "username": "******"
                }
            })

        return self.api.test("/v1/requiresAuth",
                             headers={
                                 "Authorization":
                                 ["BASIC {}".format(b64("bob:pass"))]
                             }).addCallback(rendered)

    def test_correctHMACAuth(self):
        """
        Test that HMAC authentication works.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "username": "******"
                }
            })

        return self.api.test("/v1/requiresAuth",
                             params={},
                             enableHMAC=("bob", "pass")).addCallback(rendered)

    def test_wrongHMACAuth(self):
        """
        Test that wrong HMACs are rejected.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Authentication failed."
            })

        return self.api.test(
            "/v1/requiresAuth",
            params={
                "hi": "there"
            },
            headers={
                "Authorization": [
                    'Signature signature="dXoOMfIkyAUFrnATzPoR2lpXpW'
                    '9Ei5irJByzfKG3hpc=",algorithm="hmac-sha256",keyId="alice"'
                ]
            }).addCallback(rendered)
예제 #19
0
파일: simple.py 프로젝트: hawkowl/saratoga
from saratoga.api import SaratogaAPI
import json

class ServiceClassExample(object):
    stuff = "foo"

class ExampleAPI(object):
    class v1(object):
        def example_GET(self, request, params):
            return self.stuff

api = SaratogaAPI(ExampleAPI, json.load(open("simple.json")), serviceClass=ServiceClassExample())
api.run()
예제 #20
0
class SaratogaAPITests(TestCase):

    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path, "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)


    def test_EmbeddedSaratogaBasic(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/nothing")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_EmbeddedSaratogaWithRegex(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"id": "4"}}
            )

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/example/4")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_EmbeddedSaratogaWithRegex404(self):

        def rendered(res, request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Bad ID :("}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(len(warnings), 1)

        r = Resource()
        r.putChild("api", self.api.getResource())
        req = requestMock("/api/v1/example/9999")
        endup = getChildForRequest(r, req)
        d = _render(endup, req)
        d.addCallback(rendered, req)
        return r


    def test_customOutputFormatRegistry(self):

        o = OutputRegistry("application/json")
        api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o)
        self.assertIs(o, api.outputRegistry)


    def test_getResource(self):
        """
        Check that Saratoga returns the correct resource.
        """
        self.assertIs(self.api.resource, self.api.getResource())


    def test_basic(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/example").addCallback(rendered)


    def test_basicNothing(self):
        """
        Double check we handle functons that return nothing.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/nothing").addCallback(rendered)


    def test_basicWithEmptyParams(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {}}
            )

        return self.api.test("/v1/example", replaceEmptyWithEmptyDict=True
            ).addCallback(rendered)


    def test_basicRegex(self):
        """
        Basic Saratoga test, testing the regex stuff.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"id": "4"}}
            )

        return self.api.test("/v1/example/4").addCallback(rendered)


    def test_basicRegexFail(self):
        """
        Basic Saratoga test, testing the regex stuff, and handing 404s
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Bad ID :("}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(len(warnings), 1)

        return self.api.test("/v1/example/9999").addCallback(rendered)


    def test_handlingOfExceptions(self):
        """
        Test that throwing a generic exception is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error", "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "OMG LOL WTF")

        return self.api.test("/v1/exception").addCallback(rendered)


    def test_authRequiredWhenDefaultServiceClass(self):
        """
        Test that authentication without an authenticator fails.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error", "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "Authentication required, but there is not an available "
                "authenticator.")

        return self.api.test("/v1/requiresAuth").addCallback(rendered)


    def test_dictResponse(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"hi": "there"}}
            )

        return self.api.test("/v1/dictResponse",
            params={"data": {"hi": "there"}}).addCallback(rendered)

    def test_dictResponsePOSTArgs(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": {"hi": "there"}}
            )

        return self.api.test("/v1/dictResponse",
                             params={"data": {"hi": "there"}}, useBody=False).addCallback(rendered)


    def test_listResponse(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": ["hi", "there"]}
            )

        return self.api.test("/v1/listResponse",
            params={"data": ["hi", "there"]}).addCallback(rendered)

    def test_listResponsePOSTArgs(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": ["hi", "there"]}
            )

        return self.api.test("/v1/listResponse",
                             params={"data": [["hi", "there"]]}, useBody=False).addCallback(rendered)

    def test_dictResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "[u'hi', u'there'] is not of type 'object'")

        d = self.api.test("/v1/dictResponse",
            params={"data": ["hi", "there"]})
        return d.addCallback(rendered)


    def test_listResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "{u'hi': u'there'} is not of type 'array'")

        d = self.api.test("/v1/listResponse",
            params={"data": {"hi": "there"}})
        return d.addCallback(rendered)


    def test_serviceClass(self):
        """
        Test to make sure it uses the service class you tell it.
        """
        class Foo(object):
            pass

        serviceClass = Foo()
        api = SaratogaAPI(APIImpl, APIDef, serviceClass)
        self.assertEqual(api.serviceClass, serviceClass)


    def test_nonExistingEndpoint(self):
        """
        Test that it handles non-existing endpoints gracefully.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Endpoint does not exist."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                "Endpoint does not exist.")

        d = self.api.test("/v1/nowhere")
        return d.addCallback(rendered)


    def test_requiredResponseParamsAllowsOptionalParams(self):
        """
        Test that required response params work, and will return an error if
        given extras.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success",
                "data": {"cake": "yes", "muffin": "yes", "pizza": "slice"}}
            )

        d = self.api.test("/v1/responseParams",
            params={"cake": "yes", "muffin": "yes", "pizza": "slice"})
        return d.addCallback(rendered)


    def test_extLoadJSONSchema(self):
        """
        Test that it loads external JSON Schema by loading in something that it
        will fail.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "u'cake' is a "
                "required property, u'muffin' is a required property")

        return self.api.test("/v1/responseParamsExtLoad").addCallback(rendered)


    def test_requiredResponseParamsReturnsErrorIfNotGiven(self):
        """
        Test that required response params work, and will return an error if
        not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "error",
                "data": "Internal server error."}
            )
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "'cake' is a "
                "required property, 'muffin' is a required property")

        return self.api.test("/v1/responseParams").addCallback(rendered)


    def test_requiredParamsReturnsErrorIfNotGiven(self):
        """
        Test that required params work, and will return an error if not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail",
                "data": "'hello' is a required property, 'goodbye' is a "
                    "required property"}
            )

        d = self.api.test("/v1/requestParams")
        return d.addCallback(rendered)


    def test_requiredParamsReturnsErrorIfGivenExtra(self):
        """
        Test that if required params are set, it will disallow unspecified
        params.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail",
                "data": "Additional properties are not allowed (u'unspecified'"
                    " was unexpected)"}
            )

        d = self.api.test("/v1/requestParams", params={
            "hello": "yes", "goodbye": "no", "unspecified": "yes"
            })
        return d.addCallback(rendered)


    def test_requiredParamsAllowsOptionalParams(self):
        """
        Test that if required params are set, it will allow params set as
        optional.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success",
                "data": {"hello": "yes", "goodbye": "no", "the": "beatles"}}
            )

        d = self.api.test("/v1/requestParams", params={
            "hello": "yes", "goodbye": "no", "the": "beatles"
            })
        return d.addCallback(rendered)

    def test_undefinedHTTPMethod(self):
        """
        Test that an undefined HTTP method returns a nice value.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Method not allowed."}
            )

        return self.api.test("/v1/example", method="WAFFLE").addCallback(rendered)


    def test_customHTTPMethods(self):

        APIDef = {
            "metadata": {"versions": [1]},
            "endpoints": [
                {
                    "endpoint": "example",
                    "waffleProcessors": [{"versions": [1]}]
                }
            ]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WAFFLE"])

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": "OK"}
            )

        return self.api.test("/v1/example", method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {"versions": [1]},
            "endpoints": [
                {
                    "endpoint": "example",
                    "waffleProcessors": [{"versions": [1]}]
                }
            ]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "success", "data": "OK"}
            )

        return self.api.test("/v1/example", method="WAFFlE").addCallback(rendered)
예제 #21
0
class SaratogaAPITests(TestCase):
    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path,
             "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)

    def test_customOutputFormatRegistry(self):

        o = OutputRegistry("application/json")
        api = SaratogaAPI(APIImpl, APIDef, outputRegistry=o)
        self.assertIs(o, api.outputRegistry)

    def test_getResource(self):
        """
        Check that Saratoga returns the correct resource.
        """
        self.assertIs(self.api.resource, self.api.getResource())

    def test_basic(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test("/v1/example").addCallback(rendered)

    def test_basic_nothing(self):
        """
        Double check we handle functons that return nothing.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test("/v1/nothing").addCallback(rendered)

    def test_basicWithEmptyParams(self):
        """
        Basic Saratoga test.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {}
            })

        return self.api.test(
            "/v1/example",
            replaceEmptyWithEmptyDict=True).addCallback(rendered)

    def test_basicRegex(self):
        """
        Basic Saratoga test, testing the regex stuff.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "id": "4"
                }
            })

        return self.api.test("/v1/example/4").addCallback(rendered)

    def test_handlingOfExceptions(self):
        """
        Test that throwing a generic exception is handled gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(), "OMG LOL WTF")

        return self.api.test("/v1/exception").addCallback(rendered)

    def test_authRequiredWhenDefaultServiceClass(self):
        """
        Test that authentication without an authenticator fails.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(),
                "Authentication required, but there is not an available "
                "authenticator.")

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_dictResponse(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "hi": "there"
                }
            })

        return self.api.test("/v1/dictResponse",
                             params={
                                 "data": {
                                     "hi": "there"
                                 }
                             }).addCallback(rendered)

    def test_dictResponsePOSTArgs(self):
        """
        Test that it allows a dict response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": {
                    "hi": "there"
                }
            })

        return self.api.test("/v1/dictResponse",
                             params={
                                 "data": {
                                     "hi": "there"
                                 }
                             },
                             useBody=False).addCallback(rendered)

    def test_listResponse(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": ["hi", "there"]
            })

        return self.api.test("/v1/listResponse",
                             params={
                                 "data": ["hi", "there"]
                             }).addCallback(rendered)

    def test_listResponsePOSTArgs(self):
        """
        Test that it allows a list response.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": ["hi", "there"]
            })

        return self.api.test("/v1/listResponse",
                             params={
                                 "data": [["hi", "there"]]
                             },
                             useBody=False).addCallback(rendered)

    def test_dictResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "[u'hi', u'there'] is not of type 'object'")

        d = self.api.test("/v1/dictResponse", params={"data": ["hi", "there"]})
        return d.addCallback(rendered)

    def test_listResponseFailure(self):
        """
        Test that it handles responding with a non-dict gracefully when it is
        set to respond with a dict.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "{u'hi': u'there'} is not of type 'array'")

        d = self.api.test("/v1/listResponse", params={"data": {"hi": "there"}})
        return d.addCallback(rendered)

    def test_serviceClass(self):
        """
        Test to make sure it uses the service class you tell it.
        """
        class Foo(object):
            pass

        serviceClass = Foo()
        api = SaratogaAPI(APIImpl, APIDef, serviceClass)
        self.assertEqual(api.serviceClass, serviceClass)

    def test_nonExistingEndpoint(self):
        """
        Test that it handles non-existing endpoints gracefully.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Endpoint does not exist."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(warnings[0].getErrorMessage(),
                             "Endpoint does not exist.")

        d = self.api.test("/v1/nowhere")
        return d.addCallback(rendered)

    def test_requiredResponseParamsAllowsOptionalParams(self):
        """
        Test that required response params work, and will return an error if
        given extras.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "success",
                    "data": {
                        "cake": "yes",
                        "muffin": "yes",
                        "pizza": "slice"
                    }
                })

        d = self.api.test("/v1/responseParams",
                          params={
                              "cake": "yes",
                              "muffin": "yes",
                              "pizza": "slice"
                          })
        return d.addCallback(rendered)

    def test_extLoadJSONSchema(self):
        """
        Test that it loads external JSON Schema by loading in something that it
        will fail.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(), "u'cake' is a "
                "required property, u'muffin' is a required property")

        return self.api.test("/v1/responseParamsExtLoad").addCallback(rendered)

    def test_requiredResponseParamsReturnsErrorIfNotGiven(self):
        """
        Test that required response params work, and will return an error if
        not given.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "error",
                "data": "Internal server error."
            })
            warnings = self.flushLoggedErrors()
            self.assertEqual(
                warnings[0].getErrorMessage(), "'cake' is a "
                "required property, 'muffin' is a required property")

        return self.api.test("/v1/responseParams").addCallback(rendered)

    def test_requiredParamsReturnsErrorIfNotGiven(self):
        """
        Test that required params work, and will return an error if not given.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status":
                    "fail",
                    "data":
                    "'hello' is a required property, 'goodbye' is a "
                    "required property"
                })

        d = self.api.test("/v1/requestParams")
        return d.addCallback(rendered)

    def test_requiredParamsReturnsErrorIfGivenExtra(self):
        """
        Test that if required params are set, it will disallow unspecified
        params.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status":
                    "fail",
                    "data":
                    "Additional properties are not allowed (u'unspecified'"
                    " was unexpected)"
                })

        d = self.api.test("/v1/requestParams",
                          params={
                              "hello": "yes",
                              "goodbye": "no",
                              "unspecified": "yes"
                          })
        return d.addCallback(rendered)

    def test_requiredParamsAllowsOptionalParams(self):
        """
        Test that if required params are set, it will allow params set as
        optional.
        """
        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {
                    "status": "success",
                    "data": {
                        "hello": "yes",
                        "goodbye": "no",
                        "the": "beatles"
                    }
                })

        d = self.api.test("/v1/requestParams",
                          params={
                              "hello": "yes",
                              "goodbye": "no",
                              "the": "beatles"
                          })
        return d.addCallback(rendered)

    def test_undefinedHTTPMethod(self):
        """
        Test that an undefined HTTP method returns a nice value.
        """
        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "fail",
                "data": "Method not allowed."
            })

        return self.api.test("/v1/example",
                             method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethods(self):

        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "waffleProcessors": [{
                    "versions": [1]
                }]
            }]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WAFFLE"])

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": "OK"
            })

        return self.api.test("/v1/example",
                             method="WAFFLE").addCallback(rendered)

    def test_customHTTPMethodsFunnyCasing(self):
        """
        Test funny casing works.
        """
        APIDef = {
            "metadata": {
                "versions": [1]
            },
            "endpoints": [{
                "endpoint": "example",
                "waffleProcessors": [{
                    "versions": [1]
                }]
            }]
        }

        class APIImpl(object):
            class v1(object):
                def example_WAFFLE(self, request, params):
                    return "OK"

        self.api = SaratogaAPI(APIImpl, APIDef, methods=["WaFfLE"])

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {
                "status": "success",
                "data": "OK"
            })

        return self.api.test("/v1/example",
                             method="WAFFlE").addCallback(rendered)
예제 #22
0
    def setUp(self):
        fp = getModule(__name__).filePath
        copy(fp.parent().child("jsonschemaext.json").path,
             "jsonschemaext.json")

        self.api = SaratogaAPI(APIImpl, APIDef)
예제 #23
0
class SaratogaAPITestsWithAuthenticator(TestCase):
    def setUp(self):
        self.api = SaratogaAPI(APIImpl, APIDef, APIServiceClass())

    def test_wrongPasswordBasicAuth(self):
        """
        Test that a wrong password with BASIC auth is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication failed."})

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:word"))]}
        ).addCallback(rendered)

    def test_malformedAuthHeader(self):
        """
        Test that something that a malformed auth header is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Malformed Authorization header."}
            )

        return self.api.test("/v1/requiresAuth", headers={"Authorization": ["BASIC HITHERE"]}).addCallback(rendered)

    def test_weirdAuthorizationHeader(self):
        """
        Test that weird auth headers are handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Malformed Authorization header."}
            )

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:pass:word"))]}
        ).addCallback(rendered)

    def test_unsupportedAuthType(self):
        """
        Test that a malformed auth header is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()),
                {"status": "fail", "data": "Unsupported Authorization type " "'OMGLOLAUTH'"},
            )

        return self.api.test("/v1/requiresAuth", headers={"Authorization": ["OMGLOLAUTH FIODGNDSEGOUER"]}).addCallback(
            rendered
        )

    def test_noAuthTypeGiven(self):
        """
        Test that something that Saratoga doesn't support is handled gracefully.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication required."}
            )

        return self.api.test("/v1/requiresAuth").addCallback(rendered)

    def test_correctBasicAuth(self):
        """
        Test that authentication works.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "success", "data": {"username": "******"}}
            )

        return self.api.test(
            "/v1/requiresAuth", headers={"Authorization": ["BASIC {}".format(b64("bob:pass"))]}
        ).addCallback(rendered)

    def test_correctHMACAuth(self):
        """
        Test that HMAC authentication works.
        """

        def rendered(request):
            self.assertEqual(
                json.loads(request.getWrittenData()), {"status": "success", "data": {"username": "******"}}
            )

        return self.api.test("/v1/requiresAuth", params={}, enableHMAC=("bob", "pass")).addCallback(rendered)

    def test_wrongHMACAuth(self):
        """
        Test that wrong HMACs are rejected.
        """

        def rendered(request):
            self.assertEqual(json.loads(request.getWrittenData()), {"status": "fail", "data": "Authentication failed."})

        return self.api.test(
            "/v1/requiresAuth",
            params={"hi": "there"},
            headers={
                "Authorization": [
                    'Signature signature="dXoOMfIkyAUFrnATzPoR2lpXpW'
                    '9Ei5irJByzfKG3hpc=",algorithm="hmac-sha256",keyId="alice"'
                ]
            },
        ).addCallback(rendered)