{"id":21173635,"url":"https://github.com/systemcrash/rest-cc-prefix-demo-1","last_synced_at":"2026-01-31T18:32:30.742Z","repository":{"id":142970830,"uuid":"209872757","full_name":"systemcrash/rest-cc-prefix-demo-1","owner":"systemcrash","description":null,"archived":false,"fork":false,"pushed_at":"2020-11-03T15:12:41.000Z","size":4,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-17T15:50:24.447Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/systemcrash.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-20T20:09:27.000Z","updated_at":"2020-11-03T15:12:43.000Z","dependencies_parsed_at":"2023-04-18T04:04:19.648Z","dependency_job_id":null,"html_url":"https://github.com/systemcrash/rest-cc-prefix-demo-1","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/systemcrash/rest-cc-prefix-demo-1","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemcrash%2Frest-cc-prefix-demo-1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemcrash%2Frest-cc-prefix-demo-1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemcrash%2Frest-cc-prefix-demo-1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemcrash%2Frest-cc-prefix-demo-1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/systemcrash","download_url":"https://codeload.github.com/systemcrash/rest-cc-prefix-demo-1/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/systemcrash%2Frest-cc-prefix-demo-1/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28949405,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T18:30:42.805Z","status":"ssl_error","status_checked_at":"2026-01-31T18:30:19.593Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T16:48:23.541Z","updated_at":"2026-01-31T18:32:30.701Z","avatar_url":"https://github.com/systemcrash.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# REST CC (Call Control) DB\n\nUse REST Call Control capabilities of your SBC together with a RESTful database to free your SBC of business logic. This example shows how to select a caller ID from the RESTful JSON database.\n\nKeywords: REST, JSON, cURL, SBC\n\nRequired Firmware: v6.3.2\n\n## Description\n\nYou run a call centre abroad, and your SIP trunk has some trunk phone numbers in other countries. You want to tidy up your number presentation. Presentation is, after all, everything. Right? Your call-centre has *inbound* numbers available to present as your CLI/DDI on a per-country basis when calling out from your global call-centre. You want to use a particular CLID or Caller Line ID (one that is available for use) on your SIP trunk. The callee number (the person to whom you are calling), will drive CLID selection. \n\nSummary: to whom you call sets your outbound CLID, the phone number you call from. This number is pulled live from an off-device database. \n\n## Detailed Overview \n\nYour SBC (remote to this repo and which has Internet access) captures a country-code (CC) prefix from an ingress Request-URI, and sends it in a concurrent cURL request to the endpoint hosting this database. In this example database there are three fields for each CC:\n\n- `PAID` - holds the number to go into the `P-Asserted-Identity` header\n- `From` - holds the number to go into the `From` header\n- `Comment` \n\n\nSo for `CC = 1`:\n\n| CC      | 1 |\n|---------|---|\n| PAID    |13105552345|\n| From    |13105552345|\n| Comment |USA|\n\n\nWhen the cURL request returns, the values in this example are supplied to GHM (General Header Manipulation) expressions which supplant headers into egress requests and responses with these provided values. In effect, we can, among other things, rewrite our CLID, with numbers taken from a remote database.\n\n[Click here]( https://my-json-server.typicode.com/systemcrash/rest-cc-prefix-demo-1/prefix?cc=1 ) to see these example values for `CC = 1` returned by the RESTful database.\n\n## Resources and dependencies\n\nFirmware \u003e= 6.3.2\n\n[My JSON Server](https://my-json-server.typicode.com/) which describes itself as a `Fake Online REST server for teams`. Read more about it to understand how this demonstration works. For this demo, My JSON Server uses the `db.json` file in this repository.\n\nOn your Ingate SBC, under:\n- __SIP Services, Basic Settings__: You must have a SIP TCP port configured (only UDP or TLS is not sufficient). It does not need to be `Active`.\n\nNot required but a highly recommended guide if you do not understand Regular Expressions (regexp):\n\n[Regular Expressions for Regular Folk](https://github.com/shreyasminocha/regex-for-regular-folk)\n\n\nNote: hosting your own instance is a good option. TLS up to you. \n\n## Worked Example: Rewrite the `P-Asserted-Identity` header\n\nJohn wants to call to the USA. But the SBC is not configured yet. So it's time to configure the SBC to use the RESTful database for number selection. This example is for the USA. \n\n---\nUnder the Call Control tab, add a REST API Server row:\n\n| ... | ID  | Prefix | Suffix | ... |\n|-----|------|-----|--------|-----|\n|     | `1`  |`https://my-json-server.typicode.com/your-github-repo/rest-cc-prefix-demo-1/prefix?cc=`|        |     |\n\nWhereby\n|Path|Description|\n|---|---|\n|`your-github-repo/` |your github account/org name|\n|`rest-cc-prefix-demo-1/`|this repo path|\n\n\nYou can even try with this repo - everything is ready: `https://my-json-server.typicode.com/systemcrash/rest-cc-prefix-demo-1/prefix?cc=`\n\n\nNote: Later in the dial plan, the shortcut `$curl1` refers to the Server ID `1` above. To use `$curl2`, add a row with ID `2`, and so on.\n\nNote: to adjust cURL timeout on v6.2.2 cumulatively patched, add (basic,advanced,options) advanced option name (sip.cc-timeout) and a value. Firmware \u003e= 6.3.x has a dedicated field for this under REST CC.\n\n---\n\nIn the dial plan, add a new:\n* `Matching R-URI` row which captures a single digit prefix, or CC of 1 or 7 from the Request-URI:\n\n| ... | Name | ... | Regexp | ... |\n|-----|------|-----|--------|-----|\n|     | `1x or 7x` |     | `sip:\\+(1\\|7)(.*)@.*` |     |\n\nNote: `(1|7)` forms capture group `$1` or `$r1`. Capture group `$2` or `$r2` is `(.*)`.\n\n* `Forward To` row which invokes our cURL expression:\n\n| ... | Name | ... | Regexp | Trunk |...|\n|-----|------|-----|--------|-----|---|\n|  |`RESTCCPAID`| | `?P-Asserted-Identity=sip%3a$curl1($r1_XPATH//PAID/text())\u0026!P-Bingo=sip%3a$curl1($r1_XPATH//PAID/text())`|`SIP Trunk 1`| |\n|  |`RESTCCFrom`| | `?From=%3Csip%3a$curl1($r1_XPATH//From/text())%40$(ip.eth1)%3E\u0026P-Asserted-Identity=sip%3a$curl1($r1_XPATH//PAID/text())\u0026!P-Bingo=sip%3a$curl1($r1_XPATH//PAID/text())`|`SIP Trunk 1`| |\n\nNote: `$r1` expresses the first capture group from our ingress Request-URI. In this example `$r1`, supplies the value `1` to the `$curl1(...)` expression.\n\n* `Dial Plan` row: \n\n| ... | From | Request URI | Action | Forward To | ... |\n|-----|------|-----|--------|-----|---|\n|     | ...  | ... | ... | ... |\n|     | ...  | `1x or 7x` | Forward | `RESTCCPAID` |\n\n\n---\n\nOur concurrent cURL request becomes [`https://my-json-server.typicode.com/systemcrash/rest-cc-prefix-demo-1/prefix?cc=1`]( https://my-json-server.typicode.com/systemcrash/rest-cc-prefix-demo-1/prefix?cc=1 ), to which the response comes \n```json\n[\n  {\n    \"cc\": 1,\n    \"PAID\": 13105552345,\n    \"From\": 13105552345,\n    \"comment\": \"USA\"\n  }\n]\n```\n\n\nNote: \n\nThe Call Control function converts received JSON to XML internally, whereupon XPATH expressions are available. Our `$curl1` expression has `XPATH//PAID/text()`. This takes the `PAID` field text (which is a *number* field in the JSON above, but everything gets converted to text anyway). The `?P-Asserted-Identity=sip%3a...` GHM expression tells the B2BUA to insert/modify the `P-Asserted-Identity` header with the returned value `sip:13105552345`.\n\n\nWith everything configured and applied now, here is an ingress SIP INVITE from John:\n\n```http\nINVITE sip:+12125550000@192.0.2.5 SIP/2.0\nVia: SIP/2.0/UDP 192.0.2.254:5060;branch=z9hG4bK-909121779;received=192.0.2.254;rport=5060\nContent-Length: 0\nFrom: \"John\" \u003csip:90501@192.0.2.254\u003e;tag=633\nAccept:\nUser-Agent: Johns-phone\nTo: \"USA\" \u003csip:12125550000@192.0.2.5\u003e\nContact: sip:90501@192.0.2.254:5060\nCSeq: 1 INVITE\nCall-ID: 355593493830278013560573\nMax-Forwards: 70\n```\n\nThe Request-URI contains the user portion `+12125550000`. An INVITE that egresses to our operator might look like:\n\n```http\nINVITE sip:+12125550000@192.0.2.1 SIP/2.0\nVia: SIP/2.0/UDP 192.0.2.5:5060;branch=z9hG4bK-909121779\nContent-Length: 0\nFrom: \"John\" \u003csip:90501@192.0.2.5\u003e;tag=633\nUser-Agent: Franken-SBC\nTo: \"USA\" \u003csip:+12125550000@192.0.2.1\u003e\nP-Asserted-Identity: sip:13105552345\nContact: sip:zyx123@192.0.2.5\nCSeq: 1 INVITE\nCall-ID: 1\nMax-Forwards: 70\n```\n\n## Worked Example: Rewrite the `From` Header\n*Requires Firmware \u003e=6.3.2 to fix a From header rewrite bug with REST Call Control*\n\nChange your Dial plan to:\n\n* `Dial Plan` row: \n\n| ... | From | Request URI | Action | Forward To | ... |\n|-----|------|-----|--------|-----|---|\n|     | ...  | ... | ... | ... |\n|     | ...  | `1x or 7x` | Forward | `RESTCCFrom` |\n\n\nAnd apply your configuration.\n\n\nWith everything configured and applied now, an INVITE that egresses to our operator might look like (note the modified `From` header):\n\n```http\nINVITE sip:+12125550000@192.0.2.1 SIP/2.0\nVia: SIP/2.0/UDP 192.0.2.5:5060;branch=z9hG4bK-909121779\nContent-Length: 0\nFrom: \"John\" \u003csip:13105552345@192.0.2.5\u003e;tag=633\nUser-Agent: Franken-SBC\nTo: \"USA\" \u003csip:+12125550000@192.0.2.1\u003e\nP-Asserted-Identity: sip:13105552345\nContact: sip:zyx123@192.0.2.5\nCSeq: 1 INVITE\nCall-ID: 1\nMax-Forwards: 70\n```\n\n\n## Extra Points\n\nThe `RESTCCPAID` and `RESTCCFrom` GHM above contain: `...\u0026!P-Bingo=sip%3a$curl1($r1_XPATH//PAID/text())` which instructs the B2BUA also to insert a `P-Bingo` header into all (1xx, 200 etc) INVITE responses. Not necessary, just possible, for your inspiration:\n\n```http\nSIP/2.0 180 Ringing\nVia: SIP/2.0/UDP 192.0.2.5:5060;branch=z9hG4bK9d423e35\n...\nP-Bingo: sip:13105552345\n...\n```\n\n## Code and Design (how to reproduce this JSON DB file)\n\nDraw up your javascript DB at the following location\n\n[https://beta5.objgen.com/json/local/design](https://beta5.objgen.com/json/local/design)\n\nClarification of the below JSON object design:\n\n```json\nprefix[]  \u003c-- An array [], named 'prefix' which will hold all of the country codes.\n  cc n = 1,  \u003c-- Number field, country code.\n  PAID n = 13105552345 \u003c-- Number field, to insert into a P-Asserted-Identity header\n  From n = 13105552345 \u003c-- Number field, to insert into a From header\n  comment = USA\n```\n\nCopy the below example JSON object code and paste at the above URL to produce formatted JSON output which will make our database file `db.json`, ready for my-json-server. \n\n```json\n\nprefix[]\n  cc n = 1, \n  PAID n = 13105552345\n  From n = 13105552345\n  comment = USA\n\nprefix[]\n  cc n = 7,\n  PAID n = 74950123456\n  From n = 74950123456\n  comment = Russia\n\nprefix[]\n  cc n = 40\n  PAID n = 40215552345\n  From n = 40215552345\n  comment = Romania\n\nprefix[]\n  cc n = 41\n  PAID n = 414475552345\n  From n = 414475552345\n  comment = Switzerland\n\nprefix[]\n  cc n = 420\n  PAID n = 420275552345\n  From n = 420275552345\n  comment = Czech Republic\n\nprefix[]\n  cc n = 421\n  PAID n = 421275552345\n  From n = 421275552345\n  comment = Slovakia\n\nprefix[]\n  cc n = 423\n  PAID n = 4230123456\n  From n = 4230123456\n  comment = Liechtenstein\n\nprefix[]\n  cc n = 43\n  PAID n = 43175552345\n  From n = 43175552345\n  comment = Austria\n\nprefix[]\n  cc n = 44\n  PAID n = 442075552345\n  From n = 442075552345\n  comment = UK\n\nprefix[]\n  cc n = 45\n  PAID n = 4586007750\n  From n = 4586007750\n  comment = Denmark\n\nprefix[]\n  cc n = 46\n  PAID n = 4686007750\n  From n = 4686007750\n  comment = Sweden\n\nprefix[]\n  cc n = 47\n  PAID n = 4786007750\n  From n = 4786007750\n  comment = Norway\n\nprefix[]\n  cc n = 48\n  PAID n = 48226007750\n  From n = 48226007750\n  comment = Poland\n\nprefix[]\n  cc n = 49\n  PAID n = 49306007750\n  From n = 49306007750\n  comment = Germany\n\nprefix[]\n  cc n = 380\n  PAID n= 380441234567\n  From n= 380441234567\n  comment = Ukraine\n\nprefix[]\n  cc n = 381\n  PAID n = 3810912345678\n  From n = 3810912345687\n  comment = Serbia\n\nprefix[]\n  cc n = 382\n  PAID n = 3820912345678\n  From n = 3820912345678\n  comment = Montenegro\n\nprefix[]\n  cc n = 383\n  PAID n = 3830912345678\n  From n = 3830912345678\n  comment = Kosovo\n\nprefix[]\n  cc n = 385\n  PAID n = 3850912345678\n  From n = 3850912345678\n  comment = Croatia\n\nprefix[]\n  cc n = 386\n  PAID n = 3860912345678\n  From n = 3860912345678\n  comment = Slovenia\n\nprefix[]\n  cc n = 387\n  PAID n = 3870912345678\n  From n = 3870912345678\n  comment = Bosnia and Herzegovina\n\nprofile\n  name = typicode\n\n```\n\n---\n\nThe above JSON object model code should produce the following JSON:\n```json\n\n{\n  \"prefix\": [\n    {\n      \"cc\": 1,\n      \"PAID\": 13105552345,\n      \"From\": 13105552345,\n      \"comment\": \"USA\"\n    },\n    {\n      \"cc\": 7,\n      \"PAID\": 74950123456,\n      \"From\": 74950123456,\n      \"comment\": \"Russia\"\n    },\n    {\n      \"cc\": 40,\n      \"PAID\": 40215552345,\n      \"From\": 40215552345,\n      \"comment\": \"Romania\"\n    },\n    {\n      \"cc\": 41,\n      \"PAID\": 414475552345,\n      \"From\": 414475552345,\n      \"comment\": \"Switzerland\"\n    },\n    {\n      \"cc\": 420,\n      \"PAID\": 420275552345,\n      \"From\": 420275552345,\n      \"comment\": \"Czech Republic\"\n    },\n    {\n      \"cc\": 421,\n      \"PAID\": 421275552345,\n      \"From\": 421275552345,\n      \"comment\": \"Slovakia\"\n    },\n    {\n      \"cc\": 423,\n      \"PAID\": 4230123456,\n      \"From\": 4230123456,\n      \"comment\": \"Liechtenstein\"\n    },\n    {\n      \"cc\": 43,\n      \"PAID\": 43175552345,\n      \"From\": 43175552345,\n      \"comment\": \"Austria\"\n    },\n    {\n      \"cc\": 44,\n      \"PAID\": 442075552345,\n      \"From\": 442075552345,\n      \"comment\": \"UK\"\n    },\n    {\n      \"cc\": 45,\n      \"PAID\": 4586007750,\n      \"From\": 4586007750,\n      \"comment\": \"Denmark\"\n    },\n    {\n      \"cc\": 46,\n      \"PAID\": 4686007750,\n      \"From\": 4686007750,\n      \"comment\": \"Sweden\"\n    },\n    {\n      \"cc\": 47,\n      \"PAID\": 4786007750,\n      \"From\": 4786007750,\n      \"comment\": \"Norway\"\n    },\n    {\n      \"cc\": 48,\n      \"PAID\": 48226007750,\n      \"From\": 48226007750,\n      \"comment\": \"Poland\"\n    },\n    {\n      \"cc\": 49,\n      \"PAID\": 49306007750,\n      \"From\": 49306007750,\n      \"comment\": \"Germany\"\n    },\n    {\n      \"cc\": 380,\n      \"PAID\": 380441234567,\n      \"From\": 380441234567,\n      \"comment\": \"Ukraine\"\n    },\n    {\n      \"cc\": 381,\n      \"PAID\": 3810912345678,\n      \"From\": 3810912345687,\n      \"comment\": \"Serbia\"\n    },\n    {\n      \"cc\": 382,\n      \"PAID\": 3820912345678,\n      \"From\": 3820912345678,\n      \"comment\": \"Montenegro\"\n    },\n    {\n      \"cc\": 383,\n      \"PAID\": 3830912345678,\n      \"From\": 3830912345678,\n      \"comment\": \"Kosovo\"\n    },\n    {\n      \"cc\": 385,\n      \"PAID\": 3850912345678,\n      \"From\": 3850912345678,\n      \"comment\": \"Croatia\"\n    },\n    {\n      \"cc\": 386,\n      \"PAID\": 3860912345678,\n      \"From\": 3860912345678,\n      \"comment\": \"Slovenia\"\n    },\n    {\n      \"cc\": 387,\n      \"PAID\": 3870912345678,\n      \"From\": 3870912345678,\n      \"comment\": \"Bosnia and Herzegovina\"\n    }\n  ],\n  \"profile\": {\n    \"name\": \"typicode\"\n  }\n}\n\n```\n---\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemcrash%2Frest-cc-prefix-demo-1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsystemcrash%2Frest-cc-prefix-demo-1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsystemcrash%2Frest-cc-prefix-demo-1/lists"}