Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cornice API with optional path parameter #548

Open
tflorac opened this issue Feb 8, 2021 · 1 comment
Open

Cornice API with optional path parameter #548

tflorac opened this issue Feb 8, 2021 · 1 comment

Comments

@tflorac
Copy link

tflorac commented Feb 8, 2021

Hi,

I'm trying to build a Cornice service which should accept an optional path parameter, so I followed Pyramid guidelines and set path as "/api/rest/doc/{doc_id}{version:.*}".

But then:

  • when defined, request.matchdict['version'] is set to "/1" (for example), instead of just "1", as described in Pyramid documentation;
  • when using Swagger extension, I only see a single parameter called "doc_id}{version"!

So is this syntax supported by Cornice, or should I handle it in another way?

Best regards,

Thierry

@leplatrem
Copy link
Contributor

Hi Thierry,

To be honest with you I never used these optional path parameters.
Based on your feedback, it looks like Cornice does not support them well.
It doesn't mean it couldn't, if you want to track this down, the view registering code is this:

# 1. register route
route_args = {}
if hasattr(service, 'factory'):
route_args['factory'] = service.factory
routes = config.get_predlist('route')
for predicate in routes.sorter.names:
# Do not let the custom predicates handle validation of Header Accept,
# which will pass it through to pyramid. It is handled by
# _fallback_view(), because it allows callable.
if predicate == 'accept':
continue
if hasattr(service, predicate):
route_args[predicate] = getattr(service, predicate)
# register route when not using exiting pyramid routes
if not existing_route:
config.add_route(route_name, service.path, **route_args)
# 2. register view(s)
for method, view, args in service.definitions:
args = copy.copy(args) # make a copy of the dict to not modify it
# Deepcopy only the params we're possibly passing on to pyramid
# (Some of those in cornice_parameters, e.g. ``schema``, may contain
# unpickleable values.)
for item in args:
if item not in cornice_parameters:
args[item] = copy.deepcopy(args[item])
args['request_method'] = method
if service.cors_enabled:
args['validators'].insert(0, cors_validator)
decorated_view = decorate_view(view, dict(args), method, route_args)
for item in cornice_parameters:
if item in args:
del args[item]
# filter predicates defined on Resource
route_predicates = config.get_predlist('route').sorter.names
view_predicates = config.get_predlist('view').sorter.names
for pred in set(route_predicates).difference(view_predicates):
if pred in args:
args.pop(pred)
# pop and compute predicates which get passed through to Pyramid 1:1
predicate_definitions = _pop_complex_predicates(args)
if predicate_definitions:
empty_contenttype = [({'kind': 'content_type', 'value': ''},)]
for predicate_list in predicate_definitions + empty_contenttype:
args = dict(args) # make a copy of the dict to not modify it
# prepare view args by evaluating complex predicates
_mungle_view_args(args, predicate_list)
# We register the same view multiple times with different
# accept / content_type / custom_predicates arguments
config.add_view(view=decorated_view, route_name=route_name,
**args)
else:
# it is a simple view, we don't need to loop on the definitions
# and just add it one time.
config.add_view(view=decorated_view, route_name=route_name,
**args)

Alternatively, you can register several routes in the right order to obtain the same result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants