paths:
/phish_finder:
get:
parameters:
- name: alpha2
in: query
type: string
minimum: 2
maximum: 2
- name: link
in: query
type: string
minimum: 5
Should run as expected
"/Users/chez 1/.virtualenvs/flask-apps/bin/python3.6" "/Users/chez 1/flask-apps/phishfinder/phishfinder.py"
ERROR:connexion.apis.abstract:Failed to add operation for GET /v1.0/phish_finder
Traceback (most recent call last):
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apis/abstract.py", line 243, in add_paths
self.add_operation(method, path, endpoint, path_parameters)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apis/abstract.py", line 195, in add_operation
pythonic_params=self.pythonic_params)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/operation.py", line 223, in __init__
resolution = resolver.resolve(self)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/resolver.py", line 40, in resolve
return Resolution(self.resolve_function_from_operation_id(operation_id), operation_id)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/resolver.py", line 67, in resolve_function_from_operation_id
raise ResolverError(str(e), sys.exc_info())
connexion.exceptions.ResolverError:
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/chez 1/flask-apps/phishfinder/phishfinder.py", line 24, in
resolver=RestyResolver('api'))
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apps/flask_app.py", line 54, in add_api
api = super(FlaskApp, self).add_api(specification, *kwargs)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apps/abstract.py", line 159, in add_api
options=api_options.as_dict())
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apis/abstract.py", line 131, in __init__
self.add_paths()
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apis/abstract.py", line 250, in add_paths
self._handle_add_operation_error(path, method, err.exc_info)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/apis/abstract.py", line 264, in _handle_add_operation_error
six.reraise(exc_info)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/six.py", line 693, in reraise
raise value
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/resolver.py", line 62, in resolve_function_from_operation_id
return self.function_resolver(operation_id)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/utils.py", line 43, in get_function_from_name
function = deep_getattr(module, attr_path)
File "/Users/chez 1/.virtualenvs/flask-apps/lib/python3.6/site-packages/connexion/utils.py", line 11, in deep_getattr
return functools.reduce(getattr, attr.split('.'), obj)
AttributeError: module 'api.phish_finder' has no attribute 'search'
Process finished with exit code 1
As above
## Adding a single quote to the path makes it work:
/phish_finder'
Output of the commands:
python --version 3.6pip show connexion | grep "^Version\:" 1.3Any chance of a response to this please?
@Chez could you please provide the complete swagger.yaml or the project structure? The exception seems about resolving the operationId but not sure how a single quote would solve it, and it doesn't appear in you swagger def. I tried reproducing the issue but couldn't.
Here is the swagger doc:
swagger: "2.0"
info:
title: "{{title}}"
version: "1.0"
schemes:
consumes:
basePath: /v1.0
securityDefinitions:
jwt:
type: apiKey
name: Authorization
in: header
x-authentication-scheme: Bearer
security:
paths:
/phish_finder':
get:
parameters:
- name: alpha2
in: query
description: Valid two character Alpha-2 country code
type: string
minimum: 2
maximum: 2
format: query
- name: link
in: query
description: Valid URL for checking against Phishing Database
type: string
minimum: 5
format: query
responses:
'200':
description: 'Test URL Link'
schema:
$ref: '#/definitions/PhishMatch'
definitions:
PhishMatch:
type: object
properties:
match: { type: boolean }
Hi @Chez
I have adjusted the swagger and the application and I find the following to be working fine:
swagger: "2.0"
info:
title: "{{title}}"
version: "1.0"
schemes:
- http
- https
consumes:
- application/json
produces:
- application/json
basePath: /v1.0
securityDefinitions:
jwt:
type: apiKey
name: Authorization
in: header
x-authentication-scheme: Bearer
security:
- jwt: [] # use the same name as above
paths:
/phish_finder:
get:
operationId: app.search
parameters:
- name: alpha2
in: query
description: Valid two character Alpha-2 country code
type: string
minimum: 2
maximum: 2
format: query
- name: link
in: query
description: Valid URL for checking against Phishing Database
type: string
minimum: 5
format: query
responses:
'200':
description: 'Test URL Link'
schema:
$ref: '#/definitions/PhishMatch'
definitions:
PhishMatch:
properties:
match:
type: boolean
Notice that I added operationId: app.search
and added the following in app.py:
#!/usr/bin/env python3
import connexion
def search():
return {'match': True}
if __name__ == '__main__':
app = connexion.FlaskApp(__name__, port=9090, specification_dir='')
app.add_api('swagger.yaml')
app.run()
by running python app.py you can get a server running with responses.
Hi, Mohabusama,
I got around the problem keepng the restyresolve but simply adding the operationid. So it seems like this is a bug.
I also had this issue. Looking at the code it seems its expected behaviour, although the error is super opaque.
In the file connexion/connexion/resolver.py:
class RestyResolver(Resolver):
"""
Resolves endpoint functions using REST semantics (unless overridden by specifying operationId)
"""
def __init__(self, default_module_name, collection_endpoint_name='search'):
"""
:param default_module_name: Default module name for operations
:type default_module_name: str
"""
Resolver.__init__(self)
self.default_module_name = default_module_name
self.collection_endpoint_name = collection_endpoint_name
Basically if you do not pass the collection_endpoint_name kwarg to the RestyResolver call, it will assume that a general get on the collection endpoint maps to the search method. So basically you either add a search method, or pass the method you are using as a collection_endpoint_name.
This behavior described in documentation here
Most helpful comment
I also had this issue. Looking at the code it seems its expected behaviour, although the error is super opaque.
In the file
connexion/connexion/resolver.py:Basically if you do not pass the
collection_endpoint_namekwarg to the RestyResolver call, it will assume that a general get on the collection endpoint maps to thesearchmethod. So basically you either add a search method, or pass the method you are using as acollection_endpoint_name.