summaryrefslogtreecommitdiffstats
path: root/testapi/opnfv_testapi/tornado_swagger/views.py
blob: 7939997005f1097167e30fe2a13a5b9601be7ca5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
##############################################################################
# Copyright (c) 2016 ZTE Corporation
# feng.xiaowei@zte.com.cn
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Apache License, Version 2.0
# which accompanies this distribution, and is available at
# http://www.apache.org/licenses/LICENSE-2.0
##############################################################################
import inspect
import json

import tornado.template
import tornado.web

from opnfv_testapi.tornado_swagger import settings


def json_dumps(obj, pretty=False):
    return json.dumps(obj,
                      sort_keys=True,
                      indent=4,
                      separators=(',', ': ')) if pretty else json.dumps(obj)


class SwaggerUIHandler(tornado.web.RequestHandler):
    def initialize(self, **kwargs):
        self.static_path = kwargs.get('static_path')
        self.base_url = kwargs.get('base_url')

    def get_template_path(self):
        return self.static_path

    def get(self):
        resource_url = self.reverse_url(settings.RESOURCE_LISTING_NAME)
        discovery_url = self.base_url + resource_url
        self.render('swagger/index.html', discovery_url=discovery_url)


class SwaggerResourcesHandler(tornado.web.RequestHandler):
    def initialize(self, **kwargs):
        self.api_version = kwargs.get('api_version')
        self.swagger_version = kwargs.get('swagger_version')
        self.base_url = kwargs.get('base_url')
        self.exclude_namespaces = kwargs.get('exclude_namespaces')

    def get(self):
        self.set_header('content-type', 'application/json')
        resources = {
            'apiVersion': self.api_version,
            'swaggerVersion': self.swagger_version,
            'basePath': self.base_url,
            'apis': [{
                'path': self.reverse_url(settings.API_DECLARATION_NAME),
                'description': 'Restful APIs Specification'
            }]
        }

        self.finish(json_dumps(resources, self.get_arguments('pretty')))


class SwaggerApiHandler(tornado.web.RequestHandler):
    def initialize(self, **kwargs):
        self.api_version = kwargs.get('api_version')
        self.swagger_version = kwargs.get('swagger_version')
        self.base_url = kwargs.get('base_url')

    def get(self):
        self.set_header('content-type', 'application/json')
        apis = self.find_api(self.application.handlers)
        if apis is None:
            raise tornado.web.HTTPError(404)

        specs = {
            'apiVersion': self.api_version,
            'swaggerVersion': self.swagger_version,
            'basePath': self.base_url,
            'resourcePath': '/',
            'produces': ["application/json"],
            'apis': [self.__get_api_spec__(path, spec, operations)
                     for path, spec, operations in apis],
            'models': self.__get_models_spec(settings.models)
        }
        self.finish(json_dumps(specs, self.get_arguments('pretty')))

    def __get_models_spec(self, models):
        models_spec = {}
        for model in models:
            models_spec.setdefault(model.id, self.__get_model_spec(model))
        return models_spec

    @staticmethod
    def __get_model_spec(model):
        return {
            'description': model.summary,
            'id': model.id,
            'notes': model.notes,
            'properties': model.properties,
            'required': model.required
        }

    @staticmethod
    def __get_api_spec__(path, spec, operations):
        return {
            'path': path,
            'description': spec.handler_class.__doc__,
            'operations': [{
                'httpMethod': api.func.__name__.upper(),
                'nickname': api.nickname,
                'parameters': api.params.values(),
                'summary': api.summary,
                'notes': api.notes,
                'responseClass': api.responseClass,
                'responseMessages': api.responseMessages,
            } for api in operations]
        }

    @staticmethod
    def find_api(host_handlers):
        def get_path(url, args):
            return url % tuple(['{%s}' % arg for arg in args])

        def get_operations(cls):
            return [member.rest_api
                    for (_, member) in inspect.getmembers(cls)
                    if hasattr(member, 'rest_api')]

        for host, handlers in host_handlers:
            for spec in handlers:
                for (_, mbr) in inspect.getmembers(spec.handler_class):
                    if inspect.ismethod(mbr) and hasattr(mbr, 'rest_api'):
                        path = get_path(spec._path, mbr.rest_api.func_args)
                        operations = get_operations(spec.handler_class)
                        yield path, spec, operations
                        break