{"id":13989781,"url":"https://github.com/mrak/stubby4node","last_synced_at":"2025-05-16T19:07:34.704Z","repository":{"id":3332054,"uuid":"4375798","full_name":"mrak/stubby4node","owner":"mrak","description":"A configurable server for mocking/stubbing external systems during development.","archived":false,"fork":false,"pushed_at":"2025-04-09T19:02:01.000Z","size":1496,"stargazers_count":265,"open_issues_count":29,"forks_count":62,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-12T17:50:11.118Z","etag":null,"topics":["javascript","nodejs","server","stubbing","testing"],"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/mrak.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-05-19T05:15:14.000Z","updated_at":"2025-04-09T19:05:46.000Z","dependencies_parsed_at":"2023-01-13T12:26:30.521Z","dependency_job_id":null,"html_url":"https://github.com/mrak/stubby4node","commit_stats":{"total_commits":422,"total_committers":29,"mean_commits":"14.551724137931034","dds":"0.41706161137440756","last_synced_commit":"ca816aa1cc62beb39b2b9a2123ab7ac768a61bde"},"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrak%2Fstubby4node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrak%2Fstubby4node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrak%2Fstubby4node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mrak%2Fstubby4node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mrak","download_url":"https://codeload.github.com/mrak/stubby4node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253989821,"owners_count":21995766,"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":["javascript","nodejs","server","stubbing","testing"],"created_at":"2024-08-09T13:02:03.541Z","updated_at":"2025-05-16T19:07:34.681Z","avatar_url":"https://github.com/mrak.png","language":"JavaScript","readme":"[![Build Status](https://secure.travis-ci.org/mrak/stubby4node.png?branch=master)](http://travis-ci.org/mrak/stubby4node)\n[![NPM version](https://badge.fury.io/js/stubby.png)](http://badge.fury.io/js/stubby)\n\nstubby4node\n===========\n\nA configurable server for mocking/stubbing external systems during development.\n\n`stubby` takes endpoint descriptors in the form of a YAML or JSON file that tell it how to respond to incoming requests. For each incoming request, configured endpoints are checked in-order until a match is found.\n\n## Table of Contents\n\n* [Installation](#installation)\n* [Supported Runtimes](#supported-runtimes)\n* [Starting the Server(s)](#starting-the-servers)\n* [Command-line Switches](#command-line-switches)\n* [Endpoint Configuration](#endpoint-configuration)\n* [Dynamic Token Interpolation](#dynamic-token-interpolation)\n* [The Admin Portal](#the-admin-portal)\n* [The Stubs Portal](#the-stubs-portal)\n* [Programmatic API](#programmatic-api)\n* [See Also](#see-also)\n* [TODO](#todo)\n* [NOTES](#notes)\n\n## Installation\n\n### via npm\n\n    npm install -g stubby\n\nThis will install `stubby` as a command in your `PATH`. Leave off the `-g` flag if you'd like to use stubby as an embedded module in your project.\n\n### via source\n\n    git clone https://github.com/mrak/stubby4node.git\n    cd stubby4node\n    npm start -- \u003cstubby args\u003e\n\n## Supported Runtimes\n\n* [node.js](http://nodejs.org/) - latest and currently supported LTS versions\n\nDevelopment is on x86-64 Linux.\n\n## Starting the Server(s)\n\nSome systems require you to `sudo` before running services on certain ports (like 80)\n\n    [sudo] stubby\n\n## Command-line Switches\n\n```\nstubby [-a \u003cport\u003e] [-c \u003cfile\u003e] [-d \u003cfile\u003e] [-h] [-k \u003cfile\u003e] [-l \u003chostname\u003e] [-p \u003cfile\u003e] [-q]\n       [-s \u003cport\u003e] [-t \u003cport\u003e] [-v] [-w] [-H]\n\n-a, --admin \u003cport\u003e             Port for admin portal. Defaults to 8889.\n-c, --cert \u003cfile\u003e              Certificate file. Use with --key.\n-d, --data \u003cfile\u003e              Data file to pre-load endoints. YAML or JSON format.\n-h, --help                     This help text.\n-k, --key \u003cfile\u003e               Private key file. Use with --cert.\n-l, --location \u003chostname\u003e      Hostname at which to bind stubby.\n-q, --quiet                    Prevent stubby from printing to the console.\n-p, --pfx \u003cfile\u003e               PFX file. Ignored if used with --key/--cert\n-s, --stubs \u003cport\u003e             Port for stubs portal. Defaults to 8882.\n-t, --tls \u003cport\u003e               Port for https stubs portal. Defaults to 7443.\n-v, --version                  Prints stubby's version number.\n-w, --watch                    Auto-reload data file when edits are made.\n-H, --case-sensitive-headers   Do not normalize response headers to lower-case.\n```\n\nWhen used from the command-line, `stubby` responds to the `SIGHUP` signal to reload its configuration.\n\n## Endpoint Configuration\n\nThis section explains the usage, intent and behavior of each property on the `request` and `response` objects.\n\nHere is a fully-populated, unrealistic endpoint:\n```yaml\n-  request:\n      url: ^/your/awesome/endpoint$\n      method: POST\n      query:\n         exclamation: post requests can have query strings!\n      headers:\n         content-type: application/xml\n      post: \u003e\n         \u003c!xml blah=\"blah blah blah\"\u003e\n         \u003cenvelope\u003e\n            \u003cunaryTag/\u003e\n         \u003c/envelope\u003e\n      file: tryMyFirst.xml\n   response:\n    - status: 200\n      latency: 5000\n      headers:\n         content-type: application/xml\n         server: stubbedServer/4.2\n      body: \u003e\n         \u003c!xml blah=\"blah blah blah\"\u003e\n         \u003cresponseXML\u003e\n            \u003ccontent\u003e\u003c/content\u003e\n         \u003c/responseXML\u003e\n      file: responseData.xml\n    - status: 200\n      body: \"Haha!\"\n```\n\n### request\n\nThis object is used to match an incoming request to stubby against the available endpoints that have been configured.\n\n#### url (required)\n\n* is a full-fledged __regular expression__\n* This is the only required property of an endpoint.\n* signify the url after the base host and port (i.e. after `localhost:8882`).\n* any query parameters are stripped (so don't include them, that's what `query` is for).\n    * `/url?some=value\u0026another=value` becomes `/url`\n* no checking is done for URI-encoding compliance.\n    * If it's invalid, it won't ever trigger a match.\n\nThis is the simplest you can get:\n```yaml\n-  request:\n      url: /\n```\n\nA demonstration using regular expressions:\n```yaml\n-  request:\n      url: ^/has/to/begin/with/this/\n\n-  request:\n      url: /has/to/end/with/this/$\n\n-  request:\n      url: ^/must/be/this/exactly/with/optional/trailing/slash/?$\n```\n\n#### method\n\n* defaults to `GET`.\n* case-insensitive.\n* can be any of the following:\n    * HEAD\n    * GET\n    * POST\n    * PUT\n    * DELETE\n    * etc.\n\n```yaml\n-  request:\n      url: /anything\n      method: GET\n```\n\n* it can also be an array of values.\n\n```yaml\n-  request:\n      url: /anything\n      method: [GET, HEAD]\n\n-  request:\n     url: ^/yonder\n     method:\n       -  GET\n       -  HEAD\n       -  POST\n```\n\n#### query\n\n* values are full-fledged __regular expressions__\n* if omitted, stubby ignores query parameters for the given url.\n* a yaml hashmap of variable/value pairs.\n* allows the query parameters to appear in any order in a uri\n\n* The following will match either of these:\n    * `/with/parameters?search=search+terms\u0026filter=month`\n    * `/with/parameters?filter=month\u0026search=search+terms`\n\n```yaml\n-  request:\n     url: ^/with/parameters$\n     query:\n       search: search terms\n       filter: month\n```\n\n__NOTE__: repeated querystring keys (often array representations) will have\ntheir values converted to a comma-separated list.\n\n```\n/url?array=one\u0026array=two\n```\n\nwill be matched by:\n\n```yaml\n- request:\n    url: ^/url$\n    query:\n      array: one,two\n```\n\n#### post\n\n* is a full-fledged __regular expression__\n* if omitted, any post data is ignored.\n* the body contents of the server request, such as form data.\n\n```yaml\n-  request:\n      url: ^/post/form/data$\n      post: name=John\u0026email=john@example.com\n```\n\n#### file\n\n* if supplied, replaces `post` with the contents of the locally given file.\n    * paths are relative from where the `--data` file is located\n* if the file is not found when the request is made, falls back to `post` for matching.\n* allows you to split up stubby data across multiple files\n\n```yaml\n-  request:\n      url: ^/match/against/file$\n      file: postedData.json\n      post: '{\"fallback\":\"data\"}'\n```\n\npostedData.json\n```json\n{\"fileContents\":\"match against this if the file is here\"}\n```\n\n* if `postedData.json` doesn't exist on the filesystem when `/match/against/file` is requested, stubby will match post contents against `{\"fallback\":\"data\"}` (from `post`) instead.\n\n#### json\n\n* not used if `post` or `file` are present.\n* will be parsed into a JavaScript object.\n* allows you to specify a JSON string that will be deeply compared with a JSON request\n\nAlthough not required, it is recommended to also specify a `application/json` header requirement.\n\n```yaml\n-  request:\n      url: ^/match/against/jsonString$\n      headers:\n         content-type: application/json\n      json: '{\"key1\":\"value1\",\"key2\":\"value2\"}'\n```\n\nJSON strings may contain `\"key\": \"value\"` pairs in any order: `{\"key1\":\"value1\", \"key2\":\"value2\"}` is equivalent to `{\"key2\":\"value2\", \"key1\":\"value1\"}`\n\n#### headers\n\n* values are full-fledged __regular expressions__\n* if omitted, stubby ignores headers for the given url.\n* case-insensitive matching of header names.\n* a hashmap of header/value pairs similar to `query`.\n\nThe following endpoint only accepts requests with `application/json` post values:\n\n```yaml\n-  request:\n      url: /post/json\n      method: post\n      headers:\n         content-type: application/json\n```\n\n### response\n\nAssuming a match has been made against the given `request` object, data from `response` is used to build the stubbed response back to the client.\n\n__ALSO:__ The `response` property can also be a yaml sequence of responses that cycle as each request is made.\n\n__ALSO:__ The `response` property can also be a url (string) or sequence of object/urls. The url will be used to record a response object to be used in calls to stubby. When used this way, data from the `request` portion of the endpoint will be used to assemble a request to the url given as the `response`.\n\n```yaml\n- request:\n    url: /single/object\n  response:\n    status: 204\n\n- request:\n    url: /single/url/to/record\n  response: http://example.com\n\n- request:\n    url: /object/and/url/in/sequence\n  response:\n  - http://google.com\n  - status: 200\n    body: 'second hit'\n```\n\n#### status\n\n* the HTTP status code of the response.\n* integer or integer-like string.\n* defaults to `200`.\n\n```yaml\n-  request:\n      url: ^/im/a/teapot$\n      method: POST\n   response:\n      status: 420\n```\n\n#### body\n\n* contents of the response body\n* defaults to an empty content body\n\n```yaml\n-  request:\n      url: ^/give/me/a/smile$\n   response:\n      body: ':)'\n```\n\n#### file\n\n* similar to `request.file`, but the contents of the file are used as the `body`.\n\n```yaml\n-  request:\n      url: /\n   response:\n      file: extremelyLongJsonFile.json\n```\n\n#### headers\n\n* similar to `request.headers` except that these are sent back to the client.\n\n```yaml\n-  request:\n      url: ^/give/me/some/json$\n   response:\n      headers:\n         content-type: application/json\n      body: \u003e\n         [{\n            \"name\":\"John\",\n            \"email\":\"john@example.com\"\n         },{\n            \"name\":\"Jane\",\n            \"email\":\"jane@example.com\"\n         }]\n```\n\n#### latency\n\n* time to wait, in milliseconds, before sending back the response\n* good for testing timeouts, or slow connections\n\n```yaml\n-  request:\n      url: ^/hello/to/jupiter$\n   response:\n      latency: 800000\n      body: Hello, World!\n```\n\n## Dynamic Token Interpolation\n\nWhile `stubby` is matching request data against configured endpoints, it is keeping a hash of all regular expression capture groups along the way.\nThese capture groups can be referenced in `response` data. Here's an example\n\n```yaml\n-  request:\n      method: [GET]\n      url: ^/account/(\\d{5})/category/([a-zA-Z]+)\n      query:\n         date: \"([a-zA-Z]+)\"\n      headers:\n         custom-header: \"[0-9]+\"\n\n   response:\n      status: 200\n      body: Returned invoice number# \u003c% url[1] %\u003e in category '\u003c% url[2] %\u003e' on the date '\u003c% query.date[1] %\u003e', using header custom-header \u003c% headers.custom-header[0] %\u003e\n```\n\nThe `url` regex `^/account/(\\d{5})/category/([a-zA-Z]+)` has two defined capturing groups: `(\\d{5})` and `([a-zA-Z]+)`. The `query` regex has one defined capturing group: `([a-zA-Z]+)`.\n\nAlthough the `headers` do not have capturing groups defined explicitly (no regex sections within parenthesis), the individual headers' fully-matched value is still accessible in a template (see [Capture group IDs](#capture-group-ids)).\n\n### Templating `body` and `file`\n\nThe `response.body` can have token interpolations following the format of `\u003c %PROPERTY_NAME[CAPTURING_GROUP_ID] %\u003e`. If it is a token that corresponds to `headers` or `query` member matches, then the token structure would be `\u003c% HEADERS_OR_QUERY.[KEY_NAME][CAPTURING_GROUP_ID] %\u003e.\n\n```yaml\n  response:\n    body: The \"content-type\" header value was \u003c% headers.content-type[0] %\u003e.\n```\n\n__NOTE:__ If you are using the `file` property for your responses, keep in mind that the\nboth the file _name_ and _contents_ are interpolated. In other words, the `\u003c% ... %\u003e` will appear in the files' contents as well as on the line in your configuration that has `response.file`\n\n### Capture group IDs\n\nThe `CAPTURING_GROUP_ID` is determined by the regular expression used. The index\nof `0` will be the full-text that matches the regular expression.\n\nCapture groups start at index `1` and correspond to the usage of parentheses.\n\nLet's demonstrate with the example from above:\n\n```\n- request:\n    url: ^/account/(\\d{5})/category/([a-zA-Z]+)\n```\n\nIf the incoming `url` is `/account/54/category/users`, the following would be\nthe capture groups:\n\n```\n\u003c% url[0] %\u003e -\u003e /account/54/categroy/users\n\u003c% url[1] %\u003e -\u003e 54\n\u003c% url[2] %\u003e -\u003e users\n```\n\nLet's take a more complicated example with sub-groups as captures:\n\n```yaml\n- request:\n    url: ^/resource/(([a-z]{3})-([0-9]{3}))$\n```\n\nIf the incoming `url` is `/resource/abc-123`, the capture groups would be:\n\n```\n\u003c% url[0] %\u003e -\u003e /resource/abc-123\n\u003c% url[1] %\u003e -\u003e abc-123\n\u003c% url[2] %\u003e -\u003e abc\n\u003c% url[3] %\u003e -\u003e 123\n```\n\n### Troubleshooting\n\n* Make sure that the regex you used in your stubby configuration actually does what it supposed to do. Validate that it works via the node REPL (or similar) before using it in stubby\n* Make sure that the regex has capturing groups for the parts of regex you want to capture as token values. In other words, make sure that you did not forget the parentheses within your regex if your token IDs start from `1`\n* Make sure that you are using token ID zero when wanting to use __full__ regex match as the token value\n* Make sure that the token names you used in your template are correct: check that property name is correct, capturing group IDs, token ID of the __full__ match, the `\u003c%` and `%\u003e`\n\n## The Admin Portal\n\nThe admin portal is a RESTful(ish) endpoint running on `localhost:8889`. Or wherever you described through stubby's options.\n\n### Supplying Endpoints to Stubby\n\nSubmit `POST` requests to `localhost:8889`, `PUT` requests to `localhost:8889/:id`[\\*](#getting-the-id-of-a-loaded-endpoint), or load a data-file (-d) with the following structure for each endpoint:\n\n* `request`: describes the client's call to the server\n   * `method`: GET/POST/PUT/DELETE/etc.\n   * `url`: the URI regex string.\n   * `query`: a key/value map of query string parameters included with the request\n   * `headers`: a key/value map of headers the server should respond to\n   * `post`: a string matching the textual body of the response.\n   * `file`: if specified, returns the contents of the given file as the request post. If the file cannot be found at request time, **post** is used instead\n* `response`: describes the server's response to the client\n   * `headers`: a key/value map of headers the server should use in it's response\n   * `latency`: the time in milliseconds the server should wait before responding. Useful for testing timeouts and latency\n   * `file`: if specified, returns the contents of the given file as the response body. If the file cannot be found at request time, **body** is used instead\n   * `body`: the textual body of the server's response to the client\n   * `status`: the numerical HTTP status code (200 for OK, 404 for NOT FOUND, etc.)\n\n#### YAML\n```yaml\n-  request:\n      url: ^/path/to/something$\n      method: POST\n      headers:\n         authorization: \"Basic usernamez:passwordinBase64\"\n      post: this is some post data in textual format\n   response:\n      headers:\n         Content-Type: application/json\n      latency: 1000\n      status: 200\n      body: Your request was successfully processed!\n\n-  request:\n      url: ^/path/to/anotherThing\n      query:\n         a: anything\n         b: more\n      method: GET\n      headers:\n         Content-Type: application/json\n      post:\n   response:\n      headers:\n         Content-Type: application/json\n         Access-Control-Allow-Origin: \"*\"\n      status: 204\n      file: path/to/page.html\n\n-  request:\n      url: ^/path/to/thing$\n      method: POST\n      headers:\n         Content-Type: application/json\n      post: this is some post data in textual format\n   response:\n      headers:\n         Content-Type: application/json\n      status: 304\n```\n\n#### JSON\n```json\n[\n  {\n    \"request\": {\n      \"url\": \"^/path/to/something$\",\n      \"post\": \"this is some post data in textual format\",\n      \"headers\": {\n         \"authorization\": \"Basic usernamez:passwordinBase64\"\n      },\n      \"method\": \"POST\"\n    },\n    \"response\": {\n      \"status\": 200,\n      \"headers\": {\n        \"Content-Type\": \"application/json\"\n      },\n      \"latency\": 1000,\n      \"body\": \"Your request was successfully processed!\"\n    }\n  },\n  {\n    \"request\": {\n      \"url\": \"^/path/to/anotherThing\",\n      \"query\": {\n         \"a\": \"anything\",\n         \"b\": \"more\"\n      },\n      \"headers\": {\n        \"Content-Type\": \"application/json\"\n      },\n      \"post\": null,\n      \"method\": \"GET\"\n    },\n    \"response\": {\n      \"status\": 204,\n      \"headers\": {\n        \"Content-Type\": \"application/json\",\n        \"Access-Control-Allow-Origin\": \"*\"\n      },\n      \"file\": \"path/to/page.html\"\n    }\n  },\n  {\n    \"request\": {\n      \"url\": \"^/path/to/thing$\",\n      \"headers\": {\n        \"Content-Type\": \"application/json\"\n      },\n      \"post\": \"this is some post data in textual format\",\n      \"method\": \"POST\"\n    },\n    \"response\": {\n      \"status\": 304,\n      \"headers\": {\n        \"Content-Type\": \"application/json\"\n      }\n    }\n  }\n]\n```\n\nIf you want to load more than one endpoint via file, use either a JSON array or YAML list (-) syntax. On success, the response will contain `Location` in the header with the newly created resources' location\n\n### Getting the ID of a Loaded Endpoint\n\nStubby adds the response-header `X-Stubby-Resource-ID` to outgoing responses. This ID can be referenced for use with the Admin portal.\n\n### Getting the Current List of Stubbed Endpoints\n\nPerforming a `GET` request on `localhost:8889` will return a JSON array of all currently saved responses. It will reply with `204 : No Content` if there are none saved.\n\nPerforming a `GET` request on `localhost:8889/\u003cid\u003e` will return the JSON object representing the response with the supplied id.\n\n#### The Status Page\n\nYou can also view the currently configured endpoints by going to `localhost:8889/status`\n\n### Changing Existing Endpoints\n\nPerform `PUT` requests in the same format as using `POST`, only this time supply the id in the path. For instance, to update the response with id 4 you would `PUT` to `localhost:8889/4`.\n\n### Deleting Endpoints\n\nSend a `DELETE` request to `localhost:8889/\u003cid\u003e`\n\n## The Stubs Portal\n\nRequests sent to any url at `localhost:8882` (or wherever you told stubby to run) will search through the available endpoints and, if a match is found, respond with that endpoint's `response` data\n\n### How Endpoints Are Matched\n\nFor a given endpoint, stubby only cares about matching the properties of the request that have been defined in the YAML. The exception to this rule is `method`; if it is omitted it is defaulted to `GET`.\n\nFor instance, the following will match any `POST` request to the root url:\n\n```yaml\n-  request:\n      url: /\n      method: POST\n   response: {}\n```\n\nThe request could have any headers and any post body it wants. It will match the above.\n\nPseudocode:\n\n```\nfor each \u003cendpoint\u003e of stored endpoints {\n\n   for each \u003cproperty\u003e of \u003cendpoint\u003e {\n      if \u003cendpoint\u003e.\u003cproperty\u003e != \u003cincoming request\u003e.\u003cproperty\u003e\n         next endpoint\n   }\n\n   return \u003cendpoint\u003e\n}\n```\n\n## Programmatic API\n\n### The Stubby module\n\nAdd `stubby` as a module within your project's directory:\n\n```\n    npm install stubby\n```\n\nThen within your project files you can do something like:\n\n```javascript\n    var Stubby = require('stubby').Stubby;\n    var mockService = new Stubby();\n\n    mockService.start();\n```\n\nWhat can I do with it, you ask? Read on!\n\n#### start(options, [callback])\n\n* `options`: an object containing parameters with which to start this stubby. Parameters go along with the full-name flags used from the command line.\n   * `stubs`: port number to run the stubs portal\n   * `admin`: port number to run the admin portal\n   * `tls`: port number to run the stubs portal over https\n   * `data`: JavaScript Object/Array containing endpoint data\n   * `location`: address/hostname at which to run stubby.\n   * `key`: keyfile contents (in PEM format)\n   * `cert`: certificate file contents (in PEM format)\n   * `pfx`: pfx file contents (mutually exclusive with key/cert options)\n   * `watch`: filename to monitor and load as stubby's data when changes occur\n   * `quiet`: defaults to `true`. Pass in `false` to have console output (if available)\n   * `_httpsOptions`: additional options to pass to the [underlying tls\n     server](http://nodejs.org/api/tls.html#tls_tls_createserver_options_secureconnectionlistener).\n   * `caseSensitiveHeaders`: if false (the default), all response headers are lower-cased.\n* `callback`: takes one parameter: the error message (if there is one), undefined otherwise\n\n#### start([callback])\nIdentical to previous signature, only all options are assumed to be defaults.\n\n#### stop([callback])\ncloses the connections and ports being used by stubby's stubs and admin portals. Executes `callback` afterward.\n\n#### get(id, callback)\nSimulates a GET request to the admin portal, with the callback receiving the resultant data.\n\n* `id`: the id of the endpoint to retrieve. If omitted, an array of all registered endpoints is passed the callback.\n* `callback(err, endpoint)`: `err` is defined if no endpoint exists with the given id. Else, `endpoint` is populated.\n\n#### get(callback)\nSimulates a GET request to the admin portal, with the callback receiving the resultant data.\n\n* `id`: the id of the endpoint to retrieve. If omitted, an array of all registered endpoints is passed the callback.\n* `callback(endpoints)`: takes a single parameter containing an array of returned results. Empty if no endpoints are registered\n\n#### post(data, [callback])\n* `data`: an endpoint object to store in stubby\n* `callback(err, endpoint)`: if all goes well, gets executed with the created endpoint. If there is an error, gets called with the error message.\n\n#### put(id, data, [callback])\n* `id`: id of the endpoint to update.\n* `data`: data with which to replace the endpoint.\n* `callback(err)`: executed with no passed parameters if successful. Else, passed the error message.\n\n#### delete([id], callback)\n* `id`: id of the endpoint to destroy. If omitted, all endoints are cleared from stubby.\n* `callback()`: called after the endpoint has been removed\n\n#### Example\n```javascript\nvar Stubby = require('stubby').Stubby;\n\nvar stubby1 = new Stubby();\nvar stubby2 = new Stubby();\n\nstubby1.start({\n  stubs: 80,\n  admin: 81,\n  location: 'localhost',\n  data: [{\n    request: { url: \"/anywhere\" }\n  },{\n    request: { url: \"/but/here\" }\n  }]\n});\n\nstubby2.start({\n  stubs: 82,\n  admin: 83,\n  location: '127.0.0.2'\n});\n```\n\n## See Also\n\n* **[stubby4j](https://github.com/azagniotov/stubby4j):** A java implementation of stubby\n* **[stubby4net](https://github.com/mrak/stubby4net):** A .NET implementation of stubby\n* **[grunt-stubby](https://github.com/h2non/grunt-stubby):** grunt integration with stubby\n* **[gulp-stubby-server](https://github.com/felixzapata/gulp-stubby-server):** gulp integration with stubby\n\n## TODO\n\nNon-breaking changes\n\n* Allow multi-value fields (arrays and maps) as query/post params\n\nBreaking changes\n\n* Intepret configuration values beginning and ending with `/` as regular\n  expressions, otherwise consider as exact string matches\n  * if `/` surrounded values do not compile as regex, log error to\n    console/response when adding\n\n## NOTES\n\n* __Copyright__ 2015 Eric Mrak, Alexander Zagniotov\n* __License__ Apache v2.0\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrak%2Fstubby4node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmrak%2Fstubby4node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmrak%2Fstubby4node/lists"}