<p>Friendly Automation <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/12752">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_ari.c:  Prefer exact handler match over wildcard<br><br>Given the following request path and 2 handler paths...<br>Request: /channels/externalMedia<br>Handler: /channels/{channelId}      "wildcard"<br>Handler: /channels/externalmedia    "non-wildcard"<br><br>...if /channels/externalMedia was registered as a handler after<br>/channels/{channelId} as shown above, the request would automatically<br>match the wildcard handler and attempt to parse "externalMedia" into<br>the channelId variable which isn't what was intended.  It'd work<br>if the non-wildard entry was defined in rest-api/api-docs/channels.json<br>before the wildcard entry but that makes the json files<br>order-dependent which isn't a good thing.<br><br>To combat this issue, the search loop saves any wildcard match but<br>continues looking for exact matches at the same level.  If it finds<br>one, it's used.  If it hasn't found an exact match at the end of<br>the current level, the wildcard is used.  Regardless, after<br>searching the current level, the wildcard is cleared so it won't<br>accidentally match for a different object or a higher level.<br><br>BTW, it's currently not possible for more than 1 wildcard entry<br>to be defined for a level.  For instance, there couldn't be:<br>Handler: /channels/{channelId}<br>Handler: /channels/{channelName}<br>We wouldn't know which one to match.<br><br>Change-Id: I574aa3cbe4249c92c30f74b9b40e750e9002f925<br>---<br>M res/res_ari.c<br>1 file changed, 18 insertions(+), 5 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_ari.c b/res/res_ari.c</span><br><span>index ee4a00e..682d3e9 100644</span><br><span>--- a/res/res_ari.c</span><br><span>+++ b/res/res_ari.c</span><br><span>@@ -495,6 +495,7 @@</span><br><span> {</span><br><span>       RAII_VAR(struct stasis_rest_handlers *, root, NULL, ao2_cleanup);</span><br><span>    struct stasis_rest_handlers *handler;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct stasis_rest_handlers *wildcard_handler = NULL;</span><br><span>        RAII_VAR(struct ast_variable *, path_vars, NULL, ast_variables_destroy);</span><br><span>     char *path = ast_strdupa(uri);</span><br><span>       char *path_segment;</span><br><span>@@ -503,37 +504,49 @@</span><br><span>  root = handler = get_root_handler();</span><br><span>         ast_assert(root != NULL);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Finding handler for %s\n", path);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  while ((path_segment = strsep(&path, "/")) && (strlen(path_segment) > 0)) {</span><br><span>                 struct stasis_rest_handlers *found_handler = NULL;</span><br><span>           int i;</span><br><span> </span><br><span>           ast_uri_decode(path_segment, ast_uri_http_legacy);</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_debug(3, "Finding handler for %s\n", path_segment);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_debug(3, "  Finding handler for %s\n", path_segment);</span><br><span> </span><br><span>              for (i = 0; found_handler == NULL && i < handler->num_children; ++i) {</span><br><span>                         struct stasis_rest_handlers *child = handler->children[i];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                       ast_debug(3, "  Checking %s\n", child->path_segment);</span><br><span>                   if (child->is_wildcard) {</span><br><span>                                 /* Record the path variable */</span><br><span>                               struct ast_variable *path_var = ast_variable_new(child->path_segment, path_segment, __FILE__);</span><br><span>                            path_var->next = path_vars;</span><br><span>                               path_vars = path_var;</span><br><span style="color: hsl(0, 100%, 40%);">-                           found_handler = child;</span><br><span style="color: hsl(120, 100%, 40%);">+                                wildcard_handler = child;</span><br><span style="color: hsl(120, 100%, 40%);">+                             ast_debug(3, "        Checking %s %s:  Matched wildcard.\n", handler->path_segment, child->path_segment);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                  } else if (strcmp(child->path_segment, path_segment) == 0) {</span><br><span>                              found_handler = child;</span><br><span style="color: hsl(120, 100%, 40%);">+                                ast_debug(3, "        Checking %s %s:  Explicit match with %s\n", handler->path_segment, child->path_segment, path_segment);</span><br><span style="color: hsl(120, 100%, 40%);">+                  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_debug(3, "        Checking %s %s:  Didn't match %s\n", handler->path_segment, child->path_segment, path_segment);</span><br><span>                    }</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         if (!found_handler && wildcard_handler) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_debug(3, "  No explicit handler found for %s.  Using wildcard %s.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           path_segment, wildcard_handler->path_segment);</span><br><span style="color: hsl(120, 100%, 40%);">+                     found_handler = wildcard_handler;</span><br><span style="color: hsl(120, 100%, 40%);">+                     wildcard_handler = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          if (found_handler == NULL) {</span><br><span>                         /* resource not found */</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_debug(3, "  Handler not found\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_debug(3, "  Handler not found for %s\n", path_segment);</span><br><span>                        ast_ari_response_error(</span><br><span>                              response, 404, "Not Found",</span><br><span>                                "Resource not found");</span><br><span>                     return;</span><br><span>              } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_debug(3, "  Got it!\n");</span><br><span>                       handler = found_handler;</span><br><span>             }</span><br><span>    }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/12752">change 12752</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/12752"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: I574aa3cbe4249c92c30f74b9b40e750e9002f925 </div>
<div style="display:none"> Gerrit-Change-Number: 12752 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>