{"action":"created","comment":{"url":"https://api.github.com/repos/strongloop/loopback-next/pulls/comments/230672274","pull_request_review_id":171460071,"id":230672274,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIzMDY3MjI3NA==","diff_hunk":"@@ -28,41 +28,30 @@ export function compareRoute(\n   route1: Pick<RouteEntry, 'verb' | 'path'>,\n   route2: Pick<RouteEntry, 'verb' | 'path'>,\n ): number {\n-  // First check verb\n-  const verb1 = HTTP_VERBS[route1.verb.toLowerCase()] || HTTP_VERBS.get;\n-  const verb2 = HTTP_VERBS[route2.verb.toLowerCase()] || HTTP_VERBS.get;\n-  if (verb1 !== verb2) return verb1 - verb2;\n-\n-  // Then check the path tokens\n+  // First check the path tokens\n   const path1 = route1.path.replace(/{([^}]*)}(\\/|$)/g, ':$1$2');\n   const path2 = route2.path.replace(/{([^}]*)}(\\/|$)/g, ':$1$2');\n   const tokensForPath1: pathToRegExp.Token[] = parse(path1);\n   const tokensForPath2: pathToRegExp.Token[] = parse(path2);\n \n-  // Longer path comes before shorter path\n-  if (tokensForPath1.length < tokensForPath2.length) {\n-    return 1;\n-  } else if (tokensForPath1.length > tokensForPath2.length) {\n-    return -1;\n-  }\n+  const length =\n+    tokensForPath1.length > tokensForPath2.length\n+      ? tokensForPath1.length\n+      : tokensForPath2.length;\n \n-  // Now check token by token\n-  for (let i = 0; i < tokensForPath1.length; i++) {\n+  for (let i = 0; i < length; i++) {\n     const token1 = tokensForPath1[i];\n     const token2 = tokensForPath2[i];\n-    if (typeof token1 === 'string' && typeof token2 === 'string') {\n-      if (token1 < token2) return -1;\n-      else if (token1 > token2) return 1;\n-    } else if (typeof token1 === 'string' && typeof token2 === 'object') {\n-      // token 1 is a literal while token 2 is a parameter\n-      return -1;\n-    } else if (typeof token1 === 'object' && typeof token2 === 'string') {\n-      // token 1 is a parameter while token 2 is a literal\n-      return 1;\n-    } else {\n-      // Both token are parameters. Treat as equal weight.\n-    }\n+    if (token1 === token2) continue;\n+    if (token1 === undefined) return 1;\n+    if (token2 === undefined) return -1;\n+    if (token1 < token2) return -1;\n+    if (token1 > token2) return 1;\n   }\n+  // Then check verb\n+  const verb1 = HTTP_VERBS[route1.verb.toLowerCase()] || HTTP_VERBS.get;\n+  const verb2 = HTTP_VERBS[route2.verb.toLowerCase()] || HTTP_VERBS.get;\n+  if (verb1 !== verb2) return verb1 - verb2;\n   return 0;","path":"packages/rest/src/router/route-sort.ts","position":54,"original_position":54,"commit_id":"dff390c4baa14b04473186fb03cd65c776554098","original_commit_id":"dff390c4baa14b04473186fb03cd65c776554098","user":{"login":"bajtos","id":1140553,"node_id":"MDQ6VXNlcjExNDA1NTM=","avatar_url":"https://avatars1.githubusercontent.com/u/1140553?v=4","gravatar_id":"","url":"https://api.github.com/users/bajtos","html_url":"https://github.com/bajtos","followers_url":"https://api.github.com/users/bajtos/followers","following_url":"https://api.github.com/users/bajtos/following{/other_user}","gists_url":"https://api.github.com/users/bajtos/gists{/gist_id}","starred_url":"https://api.github.com/users/bajtos/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bajtos/subscriptions","organizations_url":"https://api.github.com/users/bajtos/orgs","repos_url":"https://api.github.com/users/bajtos/repos","events_url":"https://api.github.com/users/bajtos/events{/privacy}","received_events_url":"https://api.github.com/users/bajtos/received_events","type":"User","site_admin":false},"body":"FWIW, this line is not executed by our test suite according to https://coveralls.io/builds/19876890/source?filename=packages/rest/src/router/route-sort.ts\r\n\r\nPlease consider adding a test to demonstrate what happens when two routes with the same path are configured. (It's probably better to open a new PR for that, so that this patch can be landed ASAP.)","created_at":"2018-11-05T09:03:32Z","updated_at":"2018-11-05T09:03:32Z","html_url":"https://github.com/strongloop/loopback-next/pull/1964#discussion_r230672274","pull_request_url":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/comments/230672274"},"html":{"href":"https://github.com/strongloop/loopback-next/pull/1964#discussion_r230672274"},"pull_request":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964"}}},"pull_request":{"url":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964","id":227833941,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI3ODMzOTQx","html_url":"https://github.com/strongloop/loopback-next/pull/1964","diff_url":"https://github.com/strongloop/loopback-next/pull/1964.diff","patch_url":"https://github.com/strongloop/loopback-next/pull/1964.patch","issue_url":"https://api.github.com/repos/strongloop/loopback-next/issues/1964","number":1964,"state":"open","locked":false,"title":"Fix trie routing","user":{"login":"raymondfeng","id":540892,"node_id":"MDQ6VXNlcjU0MDg5Mg==","avatar_url":"https://avatars0.githubusercontent.com/u/540892?v=4","gravatar_id":"","url":"https://api.github.com/users/raymondfeng","html_url":"https://github.com/raymondfeng","followers_url":"https://api.github.com/users/raymondfeng/followers","following_url":"https://api.github.com/users/raymondfeng/following{/other_user}","gists_url":"https://api.github.com/users/raymondfeng/gists{/gist_id}","starred_url":"https://api.github.com/users/raymondfeng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raymondfeng/subscriptions","organizations_url":"https://api.github.com/users/raymondfeng/orgs","repos_url":"https://api.github.com/users/raymondfeng/repos","events_url":"https://api.github.com/users/raymondfeng/events{/privacy}","received_events_url":"https://api.github.com/users/raymondfeng/received_events","type":"User","site_admin":false},"body":"1. Handle overlapping paths with different vars\r\n\r\nFor example:\r\n\r\n- GET /users/{id}/products\r\n- GET /users/{id}\r\n- GET /users/{userId}/orders\r\n\r\nThe issue was discovered with https://github.com/strongloop/loopback4-example-shopping/pull/23\r\n\r\n2. Improve route sorting to group by path and verb. \r\n\r\nFor example:\r\n```\r\n      {verb: 'get', path: '/orders/count'},\r\n      {verb: 'get', path: '/orders/{id}/exists'},\r\n      {verb: 'put', path: '/orders/{id}'},\r\n      {verb: 'patch', path: '/orders/{id}'},\r\n      {verb: 'get', path: '/orders/{id}'},\r\n      {verb: 'delete', path: '/orders/{id}'},\r\n      {verb: 'post', path: '/orders'},\r\n      {verb: 'patch', path: '/orders'},\r\n      {verb: 'get', path: '/orders'},\r\n      {verb: 'delete', path: '/orders'},\r\n      {verb: 'get', path: '/users/{userId}/orders'},\r\n      {verb: 'get', path: '/users/{id}/products'},\r\n      {verb: 'get', path: '/users/{id}'},\r\n```\r\n\r\nWe currently sort by verb/number of parts/path.\r\n\r\n## Checklist\r\n\r\n- [x] `npm test` passes on your machine\r\n- [x] New tests added or existing tests modified to cover all changes\r\n- [x] Code conforms with the [style guide](http://loopback.io/doc/en/contrib/style-guide.html)\r\n- [ ] API Documentation in code was updated\r\n- [ ] Documentation in [/docs/site](../tree/master/docs/site) was updated\r\n- [ ] Affected artifact templates in `packages/cli` were updated\r\n- [ ] Affected example projects in `examples/*` were updated\r\n","created_at":"2018-11-02T05:18:53Z","updated_at":"2018-11-05T09:03:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a782da9ad33188200782573d0a029b191166a5c5","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":514690858,"node_id":"MDU6TGFiZWw1MTQ2OTA4NTg=","url":"https://api.github.com/repos/strongloop/loopback-next/labels/bug","name":"bug","color":"e99695","default":true}],"milestone":null,"commits_url":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964/commits","review_comments_url":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964/comments","review_comment_url":"https://api.github.com/repos/strongloop/loopback-next/pulls/comments{/number}","comments_url":"https://api.github.com/repos/strongloop/loopback-next/issues/1964/comments","statuses_url":"https://api.github.com/repos/strongloop/loopback-next/statuses/dff390c4baa14b04473186fb03cd65c776554098","head":{"label":"strongloop:fix-trie-routing","ref":"fix-trie-routing","sha":"dff390c4baa14b04473186fb03cd65c776554098","user":{"login":"strongloop","id":3020012,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwMjAwMTI=","avatar_url":"https://avatars1.githubusercontent.com/u/3020012?v=4","gravatar_id":"","url":"https://api.github.com/users/strongloop","html_url":"https://github.com/strongloop","followers_url":"https://api.github.com/users/strongloop/followers","following_url":"https://api.github.com/users/strongloop/following{/other_user}","gists_url":"https://api.github.com/users/strongloop/gists{/gist_id}","starred_url":"https://api.github.com/users/strongloop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/strongloop/subscriptions","organizations_url":"https://api.github.com/users/strongloop/orgs","repos_url":"https://api.github.com/users/strongloop/repos","events_url":"https://api.github.com/users/strongloop/events{/privacy}","received_events_url":"https://api.github.com/users/strongloop/received_events","type":"Organization","site_admin":false},"repo":{"id":78452015,"node_id":"MDEwOlJlcG9zaXRvcnk3ODQ1MjAxNQ==","name":"loopback-next","full_name":"strongloop/loopback-next","private":false,"owner":{"login":"strongloop","id":3020012,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwMjAwMTI=","avatar_url":"https://avatars1.githubusercontent.com/u/3020012?v=4","gravatar_id":"","url":"https://api.github.com/users/strongloop","html_url":"https://github.com/strongloop","followers_url":"https://api.github.com/users/strongloop/followers","following_url":"https://api.github.com/users/strongloop/following{/other_user}","gists_url":"https://api.github.com/users/strongloop/gists{/gist_id}","starred_url":"https://api.github.com/users/strongloop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/strongloop/subscriptions","organizations_url":"https://api.github.com/users/strongloop/orgs","repos_url":"https://api.github.com/users/strongloop/repos","events_url":"https://api.github.com/users/strongloop/events{/privacy}","received_events_url":"https://api.github.com/users/strongloop/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/strongloop/loopback-next","description":"LoopBack makes it easy to build modern API applications that require complex integrations.","fork":false,"url":"https://api.github.com/repos/strongloop/loopback-next","forks_url":"https://api.github.com/repos/strongloop/loopback-next/forks","keys_url":"https://api.github.com/repos/strongloop/loopback-next/keys{/key_id}","collaborators_url":"https://api.github.com/repos/strongloop/loopback-next/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/strongloop/loopback-next/teams","hooks_url":"https://api.github.com/repos/strongloop/loopback-next/hooks","issue_events_url":"https://api.github.com/repos/strongloop/loopback-next/issues/events{/number}","events_url":"https://api.github.com/repos/strongloop/loopback-next/events","assignees_url":"https://api.github.com/repos/strongloop/loopback-next/assignees{/user}","branches_url":"https://api.github.com/repos/strongloop/loopback-next/branches{/branch}","tags_url":"https://api.github.com/repos/strongloop/loopback-next/tags","blobs_url":"https://api.github.com/repos/strongloop/loopback-next/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/strongloop/loopback-next/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/strongloop/loopback-next/git/refs{/sha}","trees_url":"https://api.github.com/repos/strongloop/loopback-next/git/trees{/sha}","statuses_url":"https://api.github.com/repos/strongloop/loopback-next/statuses/{sha}","languages_url":"https://api.github.com/repos/strongloop/loopback-next/languages","stargazers_url":"https://api.github.com/repos/strongloop/loopback-next/stargazers","contributors_url":"https://api.github.com/repos/strongloop/loopback-next/contributors","subscribers_url":"https://api.github.com/repos/strongloop/loopback-next/subscribers","subscription_url":"https://api.github.com/repos/strongloop/loopback-next/subscription","commits_url":"https://api.github.com/repos/strongloop/loopback-next/commits{/sha}","git_commits_url":"https://api.github.com/repos/strongloop/loopback-next/git/commits{/sha}","comments_url":"https://api.github.com/repos/strongloop/loopback-next/comments{/number}","issue_comment_url":"https://api.github.com/repos/strongloop/loopback-next/issues/comments{/number}","contents_url":"https://api.github.com/repos/strongloop/loopback-next/contents/{+path}","compare_url":"https://api.github.com/repos/strongloop/loopback-next/compare/{base}...{head}","merges_url":"https://api.github.com/repos/strongloop/loopback-next/merges","archive_url":"https://api.github.com/repos/strongloop/loopback-next/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/strongloop/loopback-next/downloads","issues_url":"https://api.github.com/repos/strongloop/loopback-next/issues{/number}","pulls_url":"https://api.github.com/repos/strongloop/loopback-next/pulls{/number}","milestones_url":"https://api.github.com/repos/strongloop/loopback-next/milestones{/number}","notifications_url":"https://api.github.com/repos/strongloop/loopback-next/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/strongloop/loopback-next/labels{/name}","releases_url":"https://api.github.com/repos/strongloop/loopback-next/releases{/id}","deployments_url":"https://api.github.com/repos/strongloop/loopback-next/deployments","created_at":"2017-01-09T17:27:14Z","updated_at":"2018-11-05T08:57:34Z","pushed_at":"2018-11-05T08:57:29Z","git_url":"git://github.com/strongloop/loopback-next.git","ssh_url":"git@github.com:strongloop/loopback-next.git","clone_url":"https://github.com/strongloop/loopback-next.git","svn_url":"https://github.com/strongloop/loopback-next","homepage":"https://v4.loopback.io","size":9644,"stargazers_count":1079,"watchers_count":1079,"language":"TypeScript","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":127,"mirror_url":null,"archived":false,"open_issues_count":304,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":127,"open_issues":304,"watchers":1079,"default_branch":"master"}},"base":{"label":"strongloop:master","ref":"master","sha":"216bf85ef119d742984189cff5362ee58ea034fb","user":{"login":"strongloop","id":3020012,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwMjAwMTI=","avatar_url":"https://avatars1.githubusercontent.com/u/3020012?v=4","gravatar_id":"","url":"https://api.github.com/users/strongloop","html_url":"https://github.com/strongloop","followers_url":"https://api.github.com/users/strongloop/followers","following_url":"https://api.github.com/users/strongloop/following{/other_user}","gists_url":"https://api.github.com/users/strongloop/gists{/gist_id}","starred_url":"https://api.github.com/users/strongloop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/strongloop/subscriptions","organizations_url":"https://api.github.com/users/strongloop/orgs","repos_url":"https://api.github.com/users/strongloop/repos","events_url":"https://api.github.com/users/strongloop/events{/privacy}","received_events_url":"https://api.github.com/users/strongloop/received_events","type":"Organization","site_admin":false},"repo":{"id":78452015,"node_id":"MDEwOlJlcG9zaXRvcnk3ODQ1MjAxNQ==","name":"loopback-next","full_name":"strongloop/loopback-next","private":false,"owner":{"login":"strongloop","id":3020012,"node_id":"MDEyOk9yZ2FuaXphdGlvbjMwMjAwMTI=","avatar_url":"https://avatars1.githubusercontent.com/u/3020012?v=4","gravatar_id":"","url":"https://api.github.com/users/strongloop","html_url":"https://github.com/strongloop","followers_url":"https://api.github.com/users/strongloop/followers","following_url":"https://api.github.com/users/strongloop/following{/other_user}","gists_url":"https://api.github.com/users/strongloop/gists{/gist_id}","starred_url":"https://api.github.com/users/strongloop/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/strongloop/subscriptions","organizations_url":"https://api.github.com/users/strongloop/orgs","repos_url":"https://api.github.com/users/strongloop/repos","events_url":"https://api.github.com/users/strongloop/events{/privacy}","received_events_url":"https://api.github.com/users/strongloop/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/strongloop/loopback-next","description":"LoopBack makes it easy to build modern API applications that require complex integrations.","fork":false,"url":"https://api.github.com/repos/strongloop/loopback-next","forks_url":"https://api.github.com/repos/strongloop/loopback-next/forks","keys_url":"https://api.github.com/repos/strongloop/loopback-next/keys{/key_id}","collaborators_url":"https://api.github.com/repos/strongloop/loopback-next/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/strongloop/loopback-next/teams","hooks_url":"https://api.github.com/repos/strongloop/loopback-next/hooks","issue_events_url":"https://api.github.com/repos/strongloop/loopback-next/issues/events{/number}","events_url":"https://api.github.com/repos/strongloop/loopback-next/events","assignees_url":"https://api.github.com/repos/strongloop/loopback-next/assignees{/user}","branches_url":"https://api.github.com/repos/strongloop/loopback-next/branches{/branch}","tags_url":"https://api.github.com/repos/strongloop/loopback-next/tags","blobs_url":"https://api.github.com/repos/strongloop/loopback-next/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/strongloop/loopback-next/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/strongloop/loopback-next/git/refs{/sha}","trees_url":"https://api.github.com/repos/strongloop/loopback-next/git/trees{/sha}","statuses_url":"https://api.github.com/repos/strongloop/loopback-next/statuses/{sha}","languages_url":"https://api.github.com/repos/strongloop/loopback-next/languages","stargazers_url":"https://api.github.com/repos/strongloop/loopback-next/stargazers","contributors_url":"https://api.github.com/repos/strongloop/loopback-next/contributors","subscribers_url":"https://api.github.com/repos/strongloop/loopback-next/subscribers","subscription_url":"https://api.github.com/repos/strongloop/loopback-next/subscription","commits_url":"https://api.github.com/repos/strongloop/loopback-next/commits{/sha}","git_commits_url":"https://api.github.com/repos/strongloop/loopback-next/git/commits{/sha}","comments_url":"https://api.github.com/repos/strongloop/loopback-next/comments{/number}","issue_comment_url":"https://api.github.com/repos/strongloop/loopback-next/issues/comments{/number}","contents_url":"https://api.github.com/repos/strongloop/loopback-next/contents/{+path}","compare_url":"https://api.github.com/repos/strongloop/loopback-next/compare/{base}...{head}","merges_url":"https://api.github.com/repos/strongloop/loopback-next/merges","archive_url":"https://api.github.com/repos/strongloop/loopback-next/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/strongloop/loopback-next/downloads","issues_url":"https://api.github.com/repos/strongloop/loopback-next/issues{/number}","pulls_url":"https://api.github.com/repos/strongloop/loopback-next/pulls{/number}","milestones_url":"https://api.github.com/repos/strongloop/loopback-next/milestones{/number}","notifications_url":"https://api.github.com/repos/strongloop/loopback-next/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/strongloop/loopback-next/labels{/name}","releases_url":"https://api.github.com/repos/strongloop/loopback-next/releases{/id}","deployments_url":"https://api.github.com/repos/strongloop/loopback-next/deployments","created_at":"2017-01-09T17:27:14Z","updated_at":"2018-11-05T08:57:34Z","pushed_at":"2018-11-05T08:57:29Z","git_url":"git://github.com/strongloop/loopback-next.git","ssh_url":"git@github.com:strongloop/loopback-next.git","clone_url":"https://github.com/strongloop/loopback-next.git","svn_url":"https://github.com/strongloop/loopback-next","homepage":"https://v4.loopback.io","size":9644,"stargazers_count":1079,"watchers_count":1079,"language":"TypeScript","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":127,"mirror_url":null,"archived":false,"open_issues_count":304,"license":{"key":"other","name":"Other","spdx_id":"NOASSERTION","url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":127,"open_issues":304,"watchers":1079,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964"},"html":{"href":"https://github.com/strongloop/loopback-next/pull/1964"},"issue":{"href":"https://api.github.com/repos/strongloop/loopback-next/issues/1964"},"comments":{"href":"https://api.github.com/repos/strongloop/loopback-next/issues/1964/comments"},"review_comments":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964/comments"},"review_comment":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/strongloop/loopback-next/pulls/1964/commits"},"statuses":{"href":"https://api.github.com/repos/strongloop/loopback-next/statuses/dff390c4baa14b04473186fb03cd65c776554098"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"bajtos"}}