class Server(object): """ The web server for html and miscell. """ app = Klein() @app.route("/static/", branch=True) def static(self, request): # remove the hash if request.postpath and request.postpath[0].startswith('HASH-'): del request.postpath[0] else: print "WARNING: request under /static/ with no HASH- cache busting" return static.File("./static") @app.route("/") def index(self, request): return rendering.HumanReadable('index.html') @app.route("/recipes") def showRecipes(self, request): return rendering.HumanReadable('application.html', partial='recipe-list.html') @app.route("/recipes/new") def createRecipe(self, request): return rendering.HumanReadable('application.html', partial='recipe-create.html') @app.route("/recipes/<string:urlKey>") def showRecipe(self, request, urlKey): """ Show individual recipe pages """ # urlKey = unique id made up of author's email + recipe name return rendering.HumanReadable('application.html', partial='recipe-read.html', preload={'urlKey': urlKey}) @app.route("/api/", branch=True) @enter('noms.server.APIServer') def api(self, request, subKlein): """ Endpoints under here are served as application/json with no caching allowed. We memoize APIServer().app.resource() so we only have to create one. """ request.setHeader('content-type', 'application/json') request.setHeader('expires', "-1") request.setHeader( "cache-control", "private, max-age=0, no-cache, no-store, must-revalidate") request.setHeader("pragma", "no-cache") return subKlein
class _One(object): app = Klein() def __eq__(self, other): return True def __ne__(self, other): return False def __hash__(self): return id(self)
class ExternalAPIFactory(object): """ Create an application object that contains all of the necessary resources for the external HTTP api. The applications used on the external API are: 1. InboundRequestsEndPoint 2. FileEndpoint """ app = Klein() def __init__(self, outbound, inbound=[], downloadTo=".", requestParser=parseFileRequest): """ The external API is a parent resource for all resources that should be available from other users. :param outbound: all of the outbound requests :paramtype outbound: an OutboundRequests object :param inbound: a structure that can hold inboud requests :param downloadTo: a string representing the location where files will be downloaded. :param requestParser: a function that can parse requests """ self._fileEndpoint = FileEndpoint(outbound) self._inboundRequestEndpoint = InboundRequestEndpoint( inbound, downloadTo, requestParser) @app.route('/files', branch=True) def getFiles(self, request): """ Passes a request onto the `FileEndpoint` :param request: a klein request :rtype resource: returns what the response generated by the `FileEndpoint` """ return self._fileEndpoint.app.resource() @app.route('/requests') def inboundRequest(self, request): """ Passes a request onto the `InboundRequestEndpoint` :param request: a klein request :rtype resource: returns what the response generated by the `InboundRequestEndpoint` """ return self._inboundRequestEndpoint.app.resource()
def test_runTCP6(self, reactor, mock_sfs, mock_log, mock_kr): """ L{Klein.run} called with tcp6 endpoint description. """ app = Klein() interface = "2001\:0DB8\:f00e\:eb00\:\:1" spec = "tcp6:8080:interface={0}".format(interface) app.run(endpoint_description=spec) reactor.run.assert_called_with() mock_sfs.assert_called_with(reactor, spec) mock_log.startLogging.assert_called_with(sys.stdout) mock_kr.assert_called_with(app)
def test_inlinePropertyInSchema(self): """ The generated API documentation support JSON schemas with inlined properties. """ app = Klein() @app.route(b"/", methods=[b"GET"]) @structured( inputSchema={}, outputSchema={'$ref': '/v0/test.json#/endpoint'}, schema_store=self.INLINED_SCHEMAS, ) def f(): """ Developer docs, """ rest = list(makeRst(b"/prefix", app, None, self.OUTPUT_SCHEMAS)) self.assertEqual(rest, [ '', '.. http:get:: /prefix/', '', ' Undocumented.', ' ', ' .. hidden-code-block:: json', ' :label: + Response JSON Schema', ' :starthidden: True', ' ', ' {', ' "$schema": "http://json-schema.org/draft-04/schema#",', ' "properties": {', ' "param": {', ' "description": "one\\ntwo",', ' "title": "TITLE",', ' "type": "integer"', ' }', ' },', ' "required": [', ' "param"', ' ],', ' "type": "object"', ' }', ' ', ' :>json integer param: *(required)* TITLE', ' ', ' one', ' two', ' ', '', ])
class NetworkApi(object): routes = Klein() def __init__(self): pass @routes.route("/devices", methods=["GET"]) def get_devices(self, request): """ List connected devices. """ """ Get detailed information about connected wireless stations. **Example request**: .. sourcecode:: http GET /api/v1/network/devices **Example response**: .. sourcecode:: http HTTP/1.1 200 OK Content-Type: application/json [ { "as_of": 1511806276, "client_id": "01:5c:59:48:7d:b9:e6", "expires": 1511816276, "ip_addr": "192.168.128.64", "mac_addr": "5c:59:48:7d:b9:e6", "hostname": "paradrops-iPod" } ] """ cors.config_cors(request) request.setHeader('Content-Type', 'application/json') leases = {} for root, dirs, files in os.walk(settings.RUNTIME_HOME_DIR): for file in fnmatch.filter(files, "dnsmasq-*.leases"): path = os.path.join(root, file) for entry in read_leases(path): update_lease(leases, entry) return json.dumps(leases.values())
class HealthCheck(object): app = Klein() log = get_logger() @app.route('/health') def health_check(self, request): # TODO this is just a placeholder, very crude health check self.log.debug("health-check-received") return '{"status": "ok"}' def get_site(self): return Site(self.app.resource())
class ApiService(object): app = Klein() def __init__(self): pass @app.route('/api') def items(self, request): log.msg('Received request: %r' % (dict(request.args,))) log.msg('Headers: %r' % ( dict(request.requestHeaders.getAllRawHeaders()),)) log.msg('Received data: %r' % (request.content.read(),)) return 'hello'
class VolumeAPIUser(object): """ A user accessing the API. """ app = Klein() @app.route("/noop") @structured({}, {}) def noop(self): """ Do nothing. """ return None
class InternalAPIFactory(object): """ Create the internal resources needed to start the internal API. The applications used on the internal API are: 1. UsersEndpoint 2. OutboundRequestsEndpoint """ app = Klein() def __init__(self, rootUrl, outboundRequests, fileNameGetter=getFilenames, fileRequestSubmitter=submitFileRequest, peerList=PeerList()): """ Builds a new api factory, with defaults preloaded. :ivar rootUrl: the root url from which files can be downloaded :ivar outboundRequests: data structure that will hold outbound requests :ivar fileNameGetter: a function that can return filenames :ivar fileRequestSubmitter: a function that can submit new file requests to other users :ivar peerlist: a data structure that tracks the other users. """ self._usersEndpoint = UsersEndpoint(peerList) self._outboundRequestsEndpoint = OutboundRequestEndpoint( outboundRequests, getFilenames, fileRequestSubmitter, rootUrl) @app.route('/files', branch=True) def getOutboundRequestsEndpoint(self, request): """ Passes a request onto the `OutboundRequestEndpoint` :param request: a klein request :rtype resource: returns what the response generated by the `OutboundRequestEndpoint` """ return self._outboundRequestsEndpoint.app.resource() @app.route('/users', branch=True) def getUserEndpoint(self, request): """ Passes a request onto the `UserEndpoint` :param request: a klein request :rtype resource: returns what the response generated by the `UserEndpoint` """ return self._usersEndpoint.app.resource()
class BindProxyWebService(object): app = Klein() def __init__(self, bindCache, portal): self.bindCache = bindCache self.portal = portal @app.route('/cache/<string:dn>', methods=['DELETE']) @inlineCallbacks def cache_DELETE(self, request, dn): request.setHeader("Content-Type", "application/json") client_ip = request.getClientIP() result = decode_basic_auth(request) if result is None: request.setResponseCode(UNAUTHORIZED) request.setHeader("WWW-Authenticate", 'Basic realm="BindProxyWS"') returnValue("""{"result": "not authorized"}""") user, passwd = result try: iface, avatar, logout = yield self.portal.login( UsernamePassword(*result), None, IBindProxyWSUser) except (error.UnauthorizedLogin, exceptions.NotImplementedError) as ex: log.msg( ("[ERROR] client_ip={client_ip}, login={login}: " "Unauthorized login attempt to web service.\n{err}").format( client_ip=client_ip, login=user, err=str(ex))) request.setResponseCode(UNAUTHORIZED) returnValue("""{"result": "not authorized"}""") except Exception as ex: log.msg("[ERROR] {0}".format(str(ex))) request.setResponseCode(500) returnValue('''{"result": "error"}''') self.bindCache.store(dn, None) log.msg(("[INFO] client_ip={client_ip}, login={login}: " "Successfully removed cached entry for {dn}").format( client_ip=client_ip, login=user, dn=dn)) returnValue('''{"result": "ok"}''') @app.handle_errors(werkzeug.exceptions.NotFound) def error_handler_404(self, request, failure): log.msg("[ERROR] http_status=404, client_ip={client_ip}: {err}".format( client_ip=request.getClientIP(), err=str(failure))) request.setResponseCode(404) return '''{"result": "not found"}''' @app.handle_errors def error_handler_500(self, request, failure): request.setResponseCode(500) log.msg("[ERROR] http_status=500, client_ip={client_ip}: {err}".format( client_ip=request.getClientIP(), err=str(failure))) return '''{"result": "error"}'''
def get_test_db(): eng = create_engine("sqlite://") con = eng.connect() meta.create_all(eng) con.execute(area.insert().values(test_area)) con.execute(sector.insert().values(test_sector)) for b in test_boulders: con.execute(boulder.insert().values(b)) for p in test_problems: con.execute(problem.insert().values(p)) return get_klein(Klein(), con)
def test_private_not_visible(self): """ When an endpoint is decorated with ``@private_api`` it is omitted from result of ``makeRst``. """ app = Klein() @private_api def g(): pass app.route(b"/g", methods=[b"GET"])(g) rest = list(makeRst(b"/", "section", app, None, {})) self.assertEqual(rest, [])
class listener: app = Klein() def __init__(self): print('start listener') # while True: # sleep(1) @app.route('/', methods=['POST']) def handle_post(self, request): print('receive post') self.content = json.loads(str(request.content.read(), encoding='utf-8'))
def test_node_substitution(self): """ A fake hostname is substituted for I{NODE_0} in the route body. """ example = dict(request=("GET / HTTP/1.1\n" "\n" "%(NODE_0)s\n"), response=("HTTP/1.1 200 OK\n" "\n"), doc=u"Documentation of some example.") app = Klein() @app.route(b"/", methods=[b"GET"]) @user_documentation("", ["dummy id"]) def f(): pass rst = makeRst(b"/prefix", app, lambda identifier: example, {}) self.assertEqual( # Unfortunately a lot of stuff that's not relevant to this test # comes back from makeRst. [ u'', u'.. http:get:: /prefix/', u'', u' **Example:** Documentation of some example.', u' ', u' Request', u' ', u' .. sourcecode:: http', u' ', u' GET / HTTP/1.1', u' Host: api.example.com', u' Content-Type: application/json', u' ', # Here is the important line. u' 192.0.2.1', u' ', u' Response', u' ', u' .. sourcecode:: http', u' ', u' HTTP/1.1 200 OK', u' Content-Type: application/json', u' ', u' ', u'' ], list(rst))
class SubApp(object): app = Klein() @app.route('/idk', methods=['GET']) def idk(self, request): # pragma: nocover """ This is an endpoint that can be filtered out It takes nothing and returns "idk" """ return 'idk' @app.route('/end', methods=['POST', 'HEAD']) def end(self, request): """ This is an endpoint It takes nothing and returns "ended" """ return 'ended' @openAPIDoc(responses=textHTML( {'x-page-class': 'codado.test.conftest.PageClass'})) @app.route('/end', methods=['GET']) def getEnd(self, request): # pragma: nocover """ What is the end? This is the end. --- tags: [a, z] fish: [red, blue] """ return 'status: unending' @openAPIDoc( responses={ 'default': { 'content': { 'text/html': { 'x-page-class': 'codado.test.conftest.OtherPageClass' } } } }) @app.route('/end', methods=['PUT']) def putEnd(self, request): # pragma: nocover # this has no docstring, for test coverage pass
def test_branchDoesntRequireTrailingSlash(self): """ L{Klein.route} should create a branch path which consumes all children, when the branch keyword argument is True and there is no trailing / on the path. """ app = Klein() @app.route("/foo", branch=True) def foo(request): return "foo" c = app.url_map.bind("foo") self.assertEqual(c.match("/foo/bar"), ("foo_branch", {"__rest__": "bar"}))
class StubFeed(object): _feeds = attr.ib() _app = Klein() def resource(self): return self._app.resource() @_app.route('/rss.xml') def return_xml(self, request): host = request.getHeader(b'host') try: return self._feeds[host] except KeyError: request.setResponseCode(404) return b'Unknown host: ' + host
class WebhookService(object): app = Klein() def __init__(self, verify_token): self.verify_token = verify_token @app.route('/', methods=['GET']) def items(self, request): [mode] = request.args.get('hub.mode') [challenge] = request.args.get('hub.challenge') [verify_token] = request.args.get('hub.verify_token') if (verify_token == self.verify_token and mode == 'subscribe'): return challenge request.setResponseCode(404) return 'Bad Request'
def test_route(self): """ L{Klein.route} adds functions as routable endpoints. """ app = Klein() @app.route("/foo") def foo(request): return "foo" c = app.url_map.bind("foo") self.assertEqual(c.match("/foo"), ("foo", {})) self.assertEqual(len(app.endpoints), 1) self.assertEqual(app.execute_endpoint("foo", DummyRequest(1)), "foo")
def test_error_handlers_list_is_copied(self): """ L{Klein.__copy__} returns a new L{Klein} with all the error handlers """ app = Klein() app.handle_errors(ValueError)(lambda request, failure: 'foo') app_copy = copy.copy(app) self.assertEquals(app._error_handlers, app_copy._error_handlers) app.handle_errors(KeyError)(lambda request, failure: 'foo') self.assertNotEquals(app._error_handlers, app_copy._error_handlers)
def test_runSSL(self, reactor, mock_sfs, mock_log, mock_kr): """ L{Klein.run} called with SSL endpoint specification. """ app = Klein() key = "key.pem" cert = "cert.pem" dh_params = "dhparam.pem" spec_template = "ssl:443:privateKey={0}:certKey={1}" spec = spec_template.format(key, cert, dh_params) app.run(endpoint_description=spec) reactor.run.assert_called_with() mock_sfs.assert_called_with(reactor, spec) mock_log.startLogging.assert_called_with(sys.stdout) mock_kr.assert_called_with(app)
class RequestLoggingApi(object): app = Klein() def __init__(self): self.requests = [] self.url = None def setup(self): self.port = reactor.listenTCP(0, Site(self.app.resource()), interface='127.0.0.1') addr = self.port.getHost() self.url = "http://%s:%s" % (addr.host, addr.port) def teardown(self): self.port.stopListening() @app.route('/') def log_request(self, request): self.requests.append({ 'request': request, 'body': request.content.read(), }) return '' @app.route('/bad/') def bad_request(self, request): self.requests.append({ 'request': request, 'body': request.content.read(), }) request.setResponseCode(500) return 'test-error-response' @app.route('/auth/') def auth_token(self, request): headers = request.requestHeaders self.requests.append({ 'Authorization': headers.getRawHeaders('Authorization'), }) request.setResponseCode(200) return 'auth-response' @app.route('/implode/') def imploding_request(self, request): request.transport.connectionLost(reason=Failure(ConnectionDone()))
def test_route(self): """ L{Klein.route} adds functions as routable endpoints. """ app = Klein() @app.route("/foo") def foo(request): return "foo" c = app.url_map.bind("foo") self.assertEqual(c.match("/foo"), ("foo", {})) self.assertEqual(len(app.endpoints), 1) self.assertIdentical(app.endpoints["foo"], foo) self.assertEqual(app.endpoints["foo"](None), "foo")
def test_must_be_documented(self): """ If any route doesn't have documentation, then ``SphinxError`` is raised. """ app = Klein() @app.route(b"/", methods=[b"GET"]) def f(): """ Developer docs. """ self.assertRaises( SphinxError, lambda: list(makeRst(b"/prefix", 'section', app, None, {})))
def test_runWithLogFile(self, reactor, mock_log, mock_site, mock_kr): """ L{Klein.run} logs to the specified C{logFile}. """ app = Klein() logFile = Mock() app.run("localhost", 8080, logFile=logFile) reactor.listenTCP.assert_called_with( 8080, mock_site.return_value, interface="localhost") reactor.run.assert_called_with() mock_site.assert_called_with(mock_kr.return_value) mock_kr.assert_called_with(app) mock_log.startLogging.assert_called_with(logFile)
class AirsharkApi: routes = Klein() def __init__(self, airshark_manager): self.airshark_manager = airshark_manager @routes.route('/status') def status(self, request): cors.config_cors(request) request.setHeader('Content-Type', 'application/json') hardware_ready, software_ready, airshark_running \ = self.airshark_manager.status() data = dict() data['hardware_ready'] = hardware_ready data['software_ready'] = software_ready data['airshark_running'] = airshark_running return json.dumps(data)
def test_submountedRoute(self): """ L{Klein.subroute} adds functions as routable endpoints. """ app = Klein() with app.subroute("/sub") as app: @app.route("/prefixed_uri") def foo_endpoint(request): return b"foo" c = app.url_map.bind("sub/prefixed_uri") self.assertEqual(c.match("/sub/prefixed_uri"), ("foo_endpoint", {})) self.assertEqual(len(app.endpoints), 1) self.assertEqual(app.execute_endpoint("foo_endpoint", DummyRequest(1)), b"foo")
class IntentClassifierServer: app = Klein() @app.route("/predict", methods=['POST']) def get_prediction(request): request.setHeader('Content-Type', 'application/json') request_params = json.loads(request.content.read().decode( 'utf-8', 'strict')) if 'query' in request_params: query = request_params.pop('query') else: return (json.dumps( {"bad request": "query field is manadatory in request"})) prediction = IntentClassifier.predict(query) return json.dumps(prediction)
def test_subroutedBranch(self): subapp = Klein() @subapp.route('/foo') def foo(request): return b'foo' app = self.app with app.subroute('/sub') as app: @app.route('/app', branch=True) def subapp_endpoint(request): return subapp.resource() request = requestMock(b'/sub/app/foo') d = _render(self.kr, request) self.assertFired(d) self.assertEqual(request.getWrittenData(), b'foo')