{"id":21692770,"url":"https://github.com/swaggerexpert/openapi-server-url-templating","last_synced_at":"2025-10-07T01:36:21.055Z","repository":{"id":242757641,"uuid":"809665855","full_name":"swaggerexpert/openapi-server-url-templating","owner":"swaggerexpert","description":"OpenAPI Server URL templating parser, validator and substitution mechanism.","archived":false,"fork":false,"pushed_at":"2025-03-25T01:02:08.000Z","size":342,"stargazers_count":4,"open_issues_count":3,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-05T16:58:41.492Z","etag":null,"topics":["openapi3","openapi31","server","substitution","templating","url"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/swaggerexpert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":"GOVERNANCE.md","roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["char0n"],"tidelift":"npm/openapi-server-url-templating","patreon":"char0n","ko_fi":"char0n","liberapay":"char0n","issuehunt":"char0n"}},"created_at":"2024-06-03T08:05:16.000Z","updated_at":"2025-03-31T10:29:54.000Z","dependencies_parsed_at":"2024-09-12T07:29:36.369Z","dependency_job_id":"31f99c2a-6642-406b-b250-59785c81284c","html_url":"https://github.com/swaggerexpert/openapi-server-url-templating","commit_stats":null,"previous_names":["char0n/openapi-server-url-templating","swaggerexpert/openapi-server-url-templating"],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaggerexpert%2Fopenapi-server-url-templating","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaggerexpert%2Fopenapi-server-url-templating/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaggerexpert%2Fopenapi-server-url-templating/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/swaggerexpert%2Fopenapi-server-url-templating/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/swaggerexpert","download_url":"https://codeload.github.com/swaggerexpert/openapi-server-url-templating/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248555189,"owners_count":21123847,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["openapi3","openapi31","server","substitution","templating","url"],"created_at":"2024-11-25T18:17:18.280Z","updated_at":"2025-10-07T01:36:16.031Z","avatar_url":"https://github.com/swaggerexpert.png","language":"JavaScript","funding_links":["https://github.com/sponsors/char0n","https://tidelift.com/funding/github/npm/openapi-server-url-templating","https://patreon.com/char0n","https://ko-fi.com/char0n","https://liberapay.com/char0n","https://issuehunt.io/r/char0n","https://tidelift.com/badges/package/npm/openapi-server-url-templating","https://tidelift.com/subscription/pkg/npm-openapi-server-url-templating?utm_source=npm-openapi-server-url-templating\u0026utm_medium=referral\u0026utm_campaign=readme"],"categories":[],"sub_categories":[],"readme":"# openapi-server-url-templating\n\n[![npmversion](https://badge.fury.io/js/openapi-server-url-templating.svg)](https://www.npmjs.com/package/openapi-server-url-templating)\n[![npm](https://img.shields.io/npm/dm/openapi-server-url-templating.svg)](https://www.npmjs.com/package/openapi-server-url-templating)\n[![Test workflow](https://github.com/swaggerexpert/openapi-server-url-templating/actions/workflows/test.yml/badge.svg)](https://github.com/swaggerexpert/openapi-server-url-templating/actions)\n[![Dependabot enabled](https://img.shields.io/badge/Dependabot-enabled-blue.svg)](https://dependabot.com/)\n[![try on RunKit](https://img.shields.io/badge/try%20on-RunKit-brightgreen.svg?style=flat)](https://npm.runkit.com/openapi-server-url-templating)\n[![Tidelift](https://tidelift.com/badges/package/npm/openapi-server-url-templating)](https://tidelift.com/subscription/pkg/npm-openapi-server-url-templating?utm_source=npm-openapi-server-url-templating\u0026utm_medium=referral\u0026utm_campaign=readme)\n\n[Server URL Templating](https://spec.openapis.org/oas/v3.1.1.html#server-object) supports [Server Variables](https://spec.openapis.org/oas/v3.1.1.html#server-variable-object). Variable substitutions will be made when a variable is named in `{`brackets`}`.\nThis mechanism is used by [Server Object](https://spec.openapis.org/oas/v3.1.1.html#server-object)\nof [OpenAPI specification](https://spec.openapis.org/).\n\n`openapi-server-url-templating` is a **parser**, **validator** and **substitution mechanism** for OpenAPI Server URL Templating,\nwhich played a [foundational role](https://github.com/OAI/OpenAPI-Specification/pull/4264) in defining the official ANBF grammar for Server URL Templating.\n\nIt supports Server Object URL Templating defined in following OpenAPI specification versions:\n\n- [OpenAPI 3.0.0](https://spec.openapis.org/oas/v3.0.0.html)\n- [OpenAPI 3.0.1](https://spec.openapis.org/oas/v3.0.1.html)\n- [OpenAPI 3.0.2](https://spec.openapis.org/oas/v3.0.2.html)\n- [OpenAPI 3.0.3](https://spec.openapis.org/oas/v3.0.3.html)\n- [OpenAPI 3.0.4](https://spec.openapis.org/oas/v3.0.4.html)\n- [OpenAPI 3.1.0](https://spec.openapis.org/oas/v3.1.0.html)\n- [OpenAPI 3.1.1](https://spec.openapis.org/oas/v3.1.1.html)\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"right\" valign=\"middle\"\u003e\n        \u003cimg src=\"https://cdn2.hubspot.net/hubfs/4008838/website/logos/logos_for_download/Tidelift_primary-shorthand-logo.png\" alt=\"Tidelift\" width=\"60\" /\u003e\n      \u003c/td\u003e\n      \u003ctd valign=\"middle\"\u003e\n        \u003ca href=\"https://tidelift.com/subscription/pkg/npm-openapi-server-url-templating?utm_source=npm-openapi-server-url-templating\u0026utm_medium=referral\u0026utm_campaign=readme\"\u003e\n            Get professionally supported openapi-server-url-templating with Tidelift Subscription.\n        \u003c/a\u003e\n      \u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Table of Contents\n\n- [Getting started](#getting-started)\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Parsing](#parsing)\n    - [Validation](#validation)\n    - [Substitution](#substitution)\n    - [Grammar](#grammar)\n- [More about OpenAPI Server URL Templating](#more-about-openapi-server-url-templating)\n- [License](#license)\n\n## Getting started\n\n### Installation\n\nYou can install `openapi-server-url-templating` using `npm`:\n\n```sh\n $ npm install openapi-server-url-templating\n```\n\n### Usage\n\n`openapi-server-url-templating` currently supports **parsing**, **validation** and **substitution**.\nBoth parser and validator are based on a superset of [ABNF](https://www.rfc-editor.org/rfc/rfc5234) ([SABNF](https://github.com/ldthomas/apg-js2/blob/master/SABNF.md))\nand use [apg-lite](https://github.com/ldthomas/apg-lite) parser generator.\n\n#### Parsing\n\nParsing a Server URL Templating is as simple as importing the **parse** function\nand calling it.\n\n```js\nimport { parse } from 'openapi-server-url-templating';\n\nconst parseResult = parse('https://{username}.gigantic-server.com:{port}/{basePath}');\nparseResult.result.success; // =\u003e true\n```\n\n**parseResult** variable has the following shape:\n\n```\n{\n  result: {\n    success: true,\n    state: 101,\n    stateName: 'MATCH',\n    length: 56,\n    matched: 56,\n    maxMatched: 56,\n    maxTreeDepth: 12,\n    nodeHits: 758\n  },\n  ast: fnast {\n    callbacks: [\n      'server-url-template': [Function: serverUrlTemplate],\n      'server-variable': [Function: serverVariable],\n      'server-variable-name': [Function: serverVariableName],\n      literals: [Function: literals]\n    ],\n    init: [Function (anonymous)],\n    ruleDefined: [Function (anonymous)],\n    udtDefined: [Function (anonymous)],\n    down: [Function (anonymous)],\n    up: [Function (anonymous)],\n    translate: [Function (anonymous)],\n    setLength: [Function (anonymous)],\n    getLength: [Function (anonymous)],\n    toXml: [Function (anonymous)]\n  }\n}\n```\n\n###### Interpreting AST as list of entries\n\n```js\nimport { parse } from 'openapi-server-url-templating';\n\nconst parseResult = parse('https://{username}.gigantic-server.com:{port}/{basePath}');\nconst parts = [];\n\nparseResult.ast.translate(parts);\n```\n\nAfter running the above code, **parts** variable has the following shape:\n\n```js\n[\n  [\n    'server-url-template',\n    'https://{username}.gigantic-server.com:{port}/{basePath}'\n  ],\n  [ 'literals', 'https://' ],\n  [ 'server-variable', '{username}' ],\n  [ 'server-variable-name', 'username' ],\n  [ 'literals', '.gigantic-server.com:' ],\n  [ 'server-variable', '{port}' ],\n  [ 'server-variable-name', 'port' ],\n  [ 'literals', '/' ],\n  [ 'server-variable', '{basePath}' ],\n  [ 'server-variable-name', 'basePath' ]\n]\n```\n\n###### Interpreting AST as XML\n\n```js\nimport { parse } from 'openapi-server-url-templating';\n\nconst parseResult = parse('https://{username}.gigantic-server.com:{port}/{basePath}');\nconst xml = parseResult.ast.toXml();\n```\n\nAfter running the above code, **xml** variable has the following content:\n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003croot nodes=\"10\" characters=\"56\"\u003e\n  \u003c!-- input string --\u003e\n  https://{username}.gigantic-server.com:{port}/{basePath}\n  \u003cnode name=\"server-url-template\" index=\"0\" length=\"56\"\u003e\n    https://{username}.gigantic-server.com:{port}/{basePath}\n    \u003cnode name=\"literals\" index=\"0\" length=\"8\"\u003e\n      https://\n    \u003c/node\u003e\u003c!-- name=\"literals\" --\u003e\n    \u003cnode name=\"server-variable\" index=\"8\" length=\"10\"\u003e\n      {username}\n      \u003cnode name=\"server-variable-name\" index=\"9\" length=\"8\"\u003e\n        username\n      \u003c/node\u003e\u003c!-- name=\"server-variable-name\" --\u003e\n    \u003c/node\u003e\u003c!-- name=\"server-variable\" --\u003e\n    \u003cnode name=\"literals\" index=\"18\" length=\"21\"\u003e\n      .gigantic-server.com:\n    \u003c/node\u003e\u003c!-- name=\"literals\" --\u003e\n    \u003cnode name=\"server-variable\" index=\"39\" length=\"6\"\u003e\n      {port}\n      \u003cnode name=\"server-variable-name\" index=\"40\" length=\"4\"\u003e\n        port\n      \u003c/node\u003e\u003c!-- name=\"server-variable-name\" --\u003e\n    \u003c/node\u003e\u003c!-- name=\"server-variable\" --\u003e\n    \u003cnode name=\"literals\" index=\"45\" length=\"1\"\u003e\n      /\n    \u003c/node\u003e\u003c!-- name=\"literals\" --\u003e\n    \u003cnode name=\"server-variable\" index=\"46\" length=\"10\"\u003e\n      {basePath}\n      \u003cnode name=\"server-variable-name\" index=\"47\" length=\"8\"\u003e\n        basePath\n      \u003c/node\u003e\u003c!-- name=\"server-variable-name\" --\u003e\n    \u003c/node\u003e\u003c!-- name=\"server-variable\" --\u003e\n  \u003c/node\u003e\u003c!-- name=\"server-url-template\" --\u003e\n\u003c/root\u003e\n```\n\n\u003e NOTE: AST can also be traversed in classical way using [depth first traversal](https://www.tutorialspoint.com/data_structures_algorithms/depth_first_traversal.htm). For more information about this option please refer to [apg-js](https://github.com/ldthomas/apg-js) and [apg-js-examples](https://github.com/ldthomas/apg-js-examples).\n\n#### Validation\n\nValidating a Server URL Templating is as simple as importing the **test** function and calling it.\n\n\n```js\nimport { test } from 'openapi-server-url-templating';\n\ntest('https://{username}.gigantic-server.com:{port}/{basePath}'); // =\u003e true\ntest('https://gigantic-server.com/base-path'); // =\u003e true\ntest('https://gigantic-server.com/base-path', { strict: true }); // =\u003e false (doesn't contain any server-variable)\n```\n\n#### Substitution\n\nPerforming Server URL template substitution is as simple as importing the **substitute** function and calling it.\n\n```js\nimport { substitute } from 'openapi-server-url-templating';\n\nsubtitute('https://{username}.gigantic-server.com', { username: 'char0n' }); // =\u003e \"https://char0n.gigantic-server.com\"\n```\n\nSubstituted Server URL Templating is automatically encoded using [encodeURIComponent](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) function.\nIt is possible to provide a custom encoder.\n\n```js\nimport { substitute } from 'openapi-server-url-templating';\n\nsubstitute('https://{username}.gigantic-server.com', { username: '/?#' }, {\n  encoder: (serverVariable) =\u003e serverVariable, // no encoding\n}); // =\u003e \"https:///?#.gigantic-server.com\"\n```\n\n#### Grammar\n\nNew grammar instance can be created in following way:\n\n```js\nimport { Grammar } from 'openapi-server-url-templating';\n\nconst grammar = new Grammar();\n```\n\nTo obtain original ABNF (SABNF) grammar as a string:\n\n```js\nimport { Grammar } from 'openapi-server-url-templating';\n\nconst grammar = new Grammar();\n\ngrammar.toString();\n// or\nString(grammar);\n```\n\n## More about OpenAPI Server URL Templating\n\nThe Server URL Templating is defined by the following [ABNF](https://tools.ietf.org/html/rfc5234) syntax\n\n```abnf\n; OpenAPI Server URL templating ABNF syntax\nserver-url-template    = 1*( literals / server-variable ) ; variant of https://www.rfc-editor.org/rfc/rfc6570#section-2\nserver-variable        = \"{\" server-variable-name \"}\"\nserver-variable-name   = 1*( %x00-7A / %x7C / %x7E-10FFFF ) ; every UTF8 character except { and } (from OpenAPI)\n\n; https://www.rfc-editor.org/rfc/rfc6570#section-2.1\n; https://www.rfc-editor.org/errata/eid6937\nliterals               = 1*( %x21 / %x23-24 / %x26-3B / %x3D / %x3F-5B\n                       / %x5D / %x5F / %x61-7A / %x7E / ucschar / iprivate\n                       / pct-encoded)\n                            ; any Unicode character except: CTL, SP,\n                            ;  DQUOTE, \"%\" (aside from pct-encoded),\n                            ;  \"\u003c\", \"\u003e\", \"\\\", \"^\", \"`\", \"{\", \"|\", \"}\"\n\n; https://www.rfc-editor.org/rfc/rfc6570#section-1.5\nDIGIT          =  %x30-39             ; 0-9\nHEXDIG         =  DIGIT / \"A\" / \"B\" / \"C\" / \"D\" / \"E\" / \"F\" ; case-insensitive\n\npct-encoded    =  \"%\" HEXDIG HEXDIG\n\nucschar        =  %xA0-D7FF / %xF900-FDCF / %xFDF0-FFEF\n               /  %x10000-1FFFD / %x20000-2FFFD / %x30000-3FFFD\n               /  %x40000-4FFFD / %x50000-5FFFD / %x60000-6FFFD\n               /  %x70000-7FFFD / %x80000-8FFFD / %x90000-9FFFD\n               /  %xA0000-AFFFD / %xB0000-BFFFD / %xC0000-CFFFD\n               /  %xD0000-DFFFD / %xE1000-EFFFD\n\niprivate       =  %xE000-F8FF / %xF0000-FFFFD / %x100000-10FFFD\n```\n\n## License\n\n`openapi-server-url-templating` is licensed under [Apache 2.0 license](https://github.com/swaggerexpert/openapi-server-url-templating/blob/main/LICENSE).\n`openapi-server-url-templating` comes with an explicit [NOTICE](https://github.com/swaggerexpert/openapi-server-url-templating/blob/main/NOTICE) file\ncontaining additional legal notices and information.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswaggerexpert%2Fopenapi-server-url-templating","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fswaggerexpert%2Fopenapi-server-url-templating","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fswaggerexpert%2Fopenapi-server-url-templating/lists"}