Beispiel #1
0
def entrypoint():
    if not sys.version_info[:3] >= (3, 6, 0):
        print('wax-mock已不支持低版本python,请安装python3.6.0+')
        exit(1)
    if len(sys.argv) <= 1 or sys.argv[1] == '-h':
        print_help()
        exit(0)
    if sys.argv[1] == '-v':
        print_version()
        exit(0)
    if len(sys.argv) <= 2 or sys.argv[1] not in ['run', 'pack', 'unpack']:
        print_help()
        exit(0)
    if sys.argv[1] == 'run':
        if Path('config.json').exists():
            from wax.load_swagger import SwaggerData
            from wax.load_config import config
            SwaggerData.init(json_path=sys.argv[2])
            from wax.index import app
            app.run(port=config['port'], staticpath='wax-www/static')
        else:
            confirm = input("是否创建config.json, wax-www和script (y or n) ? ")
            if confirm.lower() not in ['y', 'n', 'yes', 'no']:
                print("请输入 y 或者 n")
                exit(1)
            if confirm.lower() == 'y':
                from wax.zip_data import zipped_data
                inline_unzip(zipped_data)
                print("修改config.json后即可运行wax")
Beispiel #2
0
def compare_swagger(ctx: Context, actual: dict, ignore: str = '') -> List[str]:
    ret = []
    expect = SwaggerData.get()
    actual_paths = actual.get('paths', {})
    ignores = ignore.split(',') if ignore else []
    for path in actual_paths.keys() | expect['paths'].keys():
        if path in ignores:
            continue
        if path not in actual_paths:
            ret.append(f'actual未包含path: {path}')
            continue
        if path not in expect['paths']:
            ret.append(f'expect未包含path: {path}')
            continue
        for method in actual_paths[path].keys() | expect['paths'][path].keys():
            if method.upper() not in http_methods:
                continue
            if method not in actual_paths[path]:
                ret.append(f'actual未包含接口:{method.upper()} {path}')
                continue
            if method not in expect['paths'][path]:
                ret.append(f'expect未包含接口:{method.upper()} {path}')
                continue
            actual_endpoint = actual_paths[path]
            expect_endpoint = expect['paths'][path]
            actual_op = parse_operation(actual, actual_endpoint,
                                        method.upper())
            expect_op = parse_operation(expect, expect_endpoint,
                                        method.upper())
            ret.extend(
                compare_json(f'{path}:{method}:parameters',
                             actual_op['params'], expect_op['params'], actual,
                             expect))
            ret.extend(
                compare_json(
                    f'{path}:{method}:requestBody:content',
                    actual_endpoint[method].get('requestBody',
                                                {}).get('content'),
                    expect_endpoint[method].get('requestBody',
                                                {}).get('content'), actual,
                    expect))
            try:
                actual_endpoint[method]['responses']['200']['content'][
                    'application/json'] = actual_endpoint[method]['responses'][
                        '200']['content'].pop('*/*')
            except:
                pass
            ret.extend(
                compare_json(f'{path}:{method}:responses',
                             actual_endpoint[method].get('responses'),
                             expect_endpoint[method].get('responses'), actual,
                             expect))
    return ret
Beispiel #3
0
def make_kotlin_code(ctx: Context) -> str:
    swagger_data = SwaggerData.get()
    ret = [import_headers()]
    for name, schema in swagger_data['components']['schemas'].items():
        schema_to_kclass(schema, name, swagger_data, cache=False)
    for path, endpoint in swagger_data['paths'].items():
        ret.append(endpoint_to_kcontroller(path, endpoint, swagger_data))
    for kclass in kclass_index.values():
        ret.append(kclass.to_class_impl())
        if kclass.generics:
            ret.append(kclass.to_inherit())
    ctx.response.send_content_type('txt', encoding='utf-8')
    return '\n'.join(ret)
Beispiel #4
0
def hit_endpoint(realpath: str) -> Tuple[Dict, Dict]:
    """
    :return (endpoint, url_params)
    """
    path = realpath[len(config['mockapi-prefix']):]
    swagger_data = SwaggerData.get()
    for endpoint_path, endpoint in swagger_data['paths'].items():
        if endpoint_path == path:
            return endpoint, {}
    for endpoint_path, endpoint in swagger_data['paths'].items():
        search_ret = re.compile(re_standardize(endpoint_path)).search(path)
        if search_ret:
            return endpoint, search_ret.groupdict()
    raise NotFoundError(methods=[])
Beispiel #5
0
def make_openapi_json() -> Dict:
    swagger_data = SwaggerData.get()
    cleared_swagger = {
        key: (val if key != 'paths' else (lambda items: {
            path: (lambda items: {
                method: ((lambda items: {
                    mkey: (val if mkey != 'tags' else [])
                    for mkey, val in items
                })(val.items()) if isinstance(val, dict) else val)
                for method, val in items
            })(val.items())
            for path, val in items
        })(val.items()))
        for key, val in swagger_data.items()
    }
    return cleared_swagger
Beispiel #6
0
def make_solution_list(ctx: Context) -> str:
    swagger_data = SwaggerData.get()
    task_list = []  # (path, method, summary, label)
    methods = ['POST', 'PUT', 'GET', 'DELETE']
    for path, endpoint in swagger_data['paths'].items():
        for method, operation in endpoint.items():
            if method.upper() not in http_methods: continue
            label = '-'.join(path.strip('/').split('/')[:2]) or 'homepath'
            task_list.append((method.upper(), path, operation.get('summary')
                              or operation.get('operationId'), '~' + label))
    task_list.sort(key=lambda x: (x[1], methods.index(x[0])))
    lines = []
    for task in task_list:
        lines.append(' * ' + ' '.join(task) + '\n')
    ctx.response.send_content_type('txt', encoding='utf-8')
    return ''.join(lines)
Beispiel #7
0
def load_tag():
    tag_set = {}
    swagger_data = SwaggerData.get()
    for endpoint_path, endpoint in swagger_data['paths'].items():
        for op_method, operation in endpoint.items():
            if op_method.upper() not in http_methods: continue
            for tag in operation.get('tags', []) or ['']:
                major_tag, dir_tag, menu_tag = split_tag(tag)
                tag_tree.setdefault(major_tag, {})
                tag_tree[major_tag].setdefault(dir_tag, {})
                tag_tree[major_tag][dir_tag].setdefault(menu_tag, [])
                op = Operation()
                op.method = op_method.upper()
                op.path = endpoint_path
                try:
                    op.summary = operation['summary']
                    op.operationId = operation['operationId']
                except:
                    print(endpoint_path, op_method.upper())
                    raise
                op.description = operation.get('description', '')
                op.all_example = []
                for status_code, response_val in operation.get(
                        'responses', {}).items():
                    if not response_val.get('content'):
                        print(
                            f'WARNING: responses is empty -> {op.method} {op.path}'
                        )
                    for content_key, content_val in response_val.get(
                            'content', {}).items():
                        for example_name, _ in content_val.get('examples',
                                                               {}).items():
                            op.all_example.append(
                                f'{status_code}:{content_key}:{example_name}')
                tag_tree[major_tag][dir_tag][menu_tag].append(op)
                #
                tag_tree.setdefault('API', {'API': {'API': []}})
                tag_tree[major_tag].setdefault('API', {'API': []})
                if first_time_append_op(tag_set, 'API', op):
                    tag_tree['API']['API']['API'].append(op)
                if first_time_append_op(tag_set, major_tag,
                                        op) and dir_tag != 'API':
                    tag_tree[major_tag]['API']['API'].append(op)
                #
                op_index[op.operationId] = op
Beispiel #8
0
def operation_detail(opId: str, show: str = ''):
    op = op_index.get(opId)
    swagger_data = SwaggerData.get()
    endpoint = [
        val for key, val in swagger_data['paths'].items() if key == op.path
    ][0]
    operation = endpoint[op.method.lower()]
    data = {
        'op': operation,
        'path': op.path,
        'method': op.method,
        'mock_prefix': config['mockapi-prefix']
    }
    data.update(parse_operation(swagger_data, endpoint, op.method))
    if show == 'json':
        return data
    return Template(filename='wax-www/tpl/op_detail_page.mako',
                    input_encoding='utf-8',
                    output_encoding='utf-8').render(tag_tree=tag_tree,
                                                    git_url=config['git-url'],
                                                    **data)
Beispiel #9
0
def default_json(schema: dict):
    return jsonschema_to_json('$', schema, SwaggerData.get())
Beispiel #10
0
def mock_dealer(request: Request, response: Response, state: StateServ):
    try:
        endpoint, url_params = hit_endpoint(request.path)
        request.param_input.url_input.update(url_params)
        if 'parameters' in endpoint:
            param_check(endpoint['parameters'],
                        request=request,
                        url_params=url_params)
        operation = hit_operation(endpoint, method=request.method)
        params = operation.get('parameters', [])
        param_check(params, request=request, url_params=url_params)
        if operation.get('requestBody'):
            body_check(operation, request=request)
        state.operation_id = operation['operationId']
        status_code, schema, example_json = hit_example(operation, state=state)
        if example_json == '':  # 没有example时产生默认的json
            if status_code != 200:
                response.set_status(HttpStatus.of(status_code))
            return jsonschema_to_json('$', schema, SwaggerData.get())
        example = json.loads(example_json)
        # 准备pql的上下文环境
        if request.is_json():
            req_body = request.json_input
        elif request.is_form():
            req_body = {}
            try:
                property_dict = operation['requestBody']['content'].popitem(
                )[-1]['schema']['properties']
                for param_name, param_prop in property_dict.items():
                    if param_name in request.param_input.form_input:
                        req_body[param_name] = cast_param(
                            request.param_input.form_input[param_name],
                            param_prop.get('type', ''))
            except:
                pass
        else:
            req_body = request.body_data
        req_query, req_path, req_header = {}, {}, {}
        for param in endpoint.get('parameters', []) + params:
            param_name = param.get('name')
            if not param_name:
                continue
            param_type = eafp(lambda: param['schema']['type'], '')
            if param.get('in') == 'path':
                if param_name in request.param_input.url_input:
                    req_path[param_name] = cast_param(
                        [request.param_input.url_input[param_name]],
                        param_type)
            elif param.get('in') == 'header':
                header_value = request.get_header(param_name)
                if header_value is not None:
                    req_header[param_name] = cast_param([header_value],
                                                        param_type)
            else:
                if param_name in request.param_input.query_input:
                    req_query[param_name] = cast_param(
                        request.param_input.query_input[param_name],
                        param_type)
        env = {
            'body': req_body,
            'query': req_query,
            'path': req_path,
            'header': req_header,
        }
        resp_obj = apply_schema(env, dict_schema=example)
        response_check(schema=schema, resp_obj=resp_obj)
        if status_code != 200:
            response.set_status(HttpStatus.of(status_code))
        return resp_obj
    except (InternalError, PqlRuntimeError) as e:
        response.send_content_type(mimekey='txt', encoding='utf-8')
        response.set_status(HttpStatus.InternalServerError)
        return str(e)