You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
mitmproxy2swagger/mitmproxy2swagger/swagger_util.py

143 lines
4.1 KiB

import urllib
VERBS = [
'add',
'create',
'delete',
'get',
'attach',
'detach',
'update',
'push',
'extendedcreate',
'activate'
]
# generate a name for the endpoint from the path template
# POST /api/v1/things/{id}/create -> POST create thing by id
def path_template_to_endpoint_name(method, path_template):
path_template = path_template.strip('/')
segments = path_template.split('/')
# remove params to a separate array
params = []
for idx, segment in enumerate(segments):
if segment.startswith('{') and segment.endswith('}'):
params.append(segment)
segments[idx] = '{}'
# remove them from the segments
segments = [segment for segment in segments if segment != '{}']
# reverse the segments
segments.reverse()
name_parts = []
for segment in segments:
if segment in VERBS:
# prepend to the name_parts
name_parts.insert(0, segment.lower())
else:
name_parts.insert(0, segment.lower())
break
for param in params:
name_parts.append("by " + param.replace('{', '').replace('}', ''))
break
return method.upper() + ' ' + ' '.join(name_parts)
# when given an url and its path template, generates the parameters section of the request
def url_to_params(url, path_template):
path_template = path_template.strip('/')
segments = path_template.split('/')
url_segments = url.split('?')[0].strip('/').split('/')
params = []
for idx, segment in enumerate(segments):
if segment.startswith('{') and segment.endswith('}'):
params.append({
'name': segment.replace('{', '').replace('}', ''),
'in': 'path',
'required': True,
'schema': {
'type': 'number' if url_segments[idx].isdigit() else 'string'
}
})
query_string = urllib.parse.urlparse(url).query
if query_string:
query_params = urllib.parse.parse_qs(query_string)
for key in query_params:
params.append({
'name': key,
'in': 'query',
'required': False,
'schema': {
'type': 'number' if query_params[key][0].isdigit() else 'string'
}
})
return params
def value_to_schema(value):
# check if value is a number
if type(value) == int or type(value) == float:
return {
'type': 'number'
}
# check if value is a boolean
elif type(value) == bool:
return {
'type': 'boolean'
}
# check if value is a string
elif type(value) == str:
return {
'type': 'string'
}
# check if value is a list
elif type(value) == list:
if len(value) == 0:
return {
'type': 'array',
'items': {}
}
return {
'type': 'array',
'items': value_to_schema(value[0])
}
# check if value is a dict
elif type(value) == dict:
return {
'type': 'object',
'properties': {
key: value_to_schema(value[key])
for key in value
}
}
# if it is none, return null
elif value is None:
return {
'type': 'object'
}
MAX_EXAMPLE_ARRAY_ELEMENTS = 10
MAX_EXAMPLE_OBJECT_PROPERTIES = 150
# recursively scan an example value and limit the number of elements and properties
def limit_example_size(example):
if type(example) == list:
new_list = []
for element in example:
if len(new_list) >= MAX_EXAMPLE_ARRAY_ELEMENTS:
break
new_list.append(limit_example_size(element))
return new_list
elif type(example) == dict:
new_dict = {}
for key in example:
if len(new_dict) >= MAX_EXAMPLE_OBJECT_PROPERTIES:
break
new_dict[key] = limit_example_size(example[key])
return new_dict
else:
return example