Giter Site home page Giter Site logo

apimocker's Introduction

apimocker Build Status

NPM

This is a node.js module to run a simple http server, which can serve up mock service responses. Responses can be JSON or XML to simulate REST or SOAP services. Access-Control HTTP Headers are set by default to allow CORS requests. Mock services are configured in the config.json file, or on the fly, to allow for easy functional testing. Apimocker can return different responses or HTTP status codes, based on request parameters - even complex JSON requests. Using apimocker, you can develop your web or mobile app with no dependency on back end services. (There are lots of these projects out there, but I wrote this one to support all kinds of responses, to allow on-the-fly configuration, and to run in node.)

Installation

	sudo npm install -g apimocker

That will install globally, and allow for easier usage. (On Windows, you don't need "sudo".)

Usage

    apimocker \[-c, --config <path>\] \[-q, --quiet\] \[-p <port>\] \[-f, --proxy <proxyURL>\] \[-i, --intercept <proxyIntercept>\]

Out of the box, you can just run "apimocker" with no arguments. (Except on windows, you'll need to edit config.json first. See below.)

Then you can visit "http://localhost:7878/first" in your browser to see it work. The quiet and port options can also be set in the config.json file, and values from config.json will override values from the command line. After you get up and running, you should put your config.json and mock responses in a better location. It's not a good idea to keep them under the "node_modules" directory. Make sure another process is not already using the port you want. If you want port 80, you may need to use "sudo" on Mac OSX.

Windows note

After installing from npm, you may need to edit this file: /Users/xxxxx/AppData/Roaming/npm/node_modules/apimocker/config.json Change the "mockDirectory" to point to this location. (Or another location where you put the mock responses.) mockDirectory: /Users/xxxxx/AppData/Roaming/npm/node_modules/apimocker/samplemocks

Proxy

Sometimes you only want some service endpoints to be mocked, but have other requests forwarded to real service endpoints. In this case, provide the proxy URL option on startup e.g. apimocker --proxy http://myrealservice.io When the proxy option is set, any requests to apimocker with URLs that are not configured with mock files, will be forwarded to the specified URL.

A proxy intercept function can be specified to modify responses, using the proxy intercept option (apimocker --proxy http://myrealservice.io --intercept config/proxyResponseCustomizer`). The value of the option should be the path, relative to the current working directory, to a module that exports an intercept function as documented in the express-http-proxy docs.

Uploads

There is a simple support of multipart form data upload process of a single or multiple files. A global option uploadRoot determines where the files will be saved after successful upload, and another option - useUploadFieldname tells apimocker (actually - multer) whether to save the uploaded file with the original filename found in the request (default), or the name of the field. Although the latter may sound strange, it can make certain testing procedure simpler.

With Grunt or Gulp

If you're using Grunt for your project, there's a grunt plugin you can use to start up apimocker: https://github.com/gstroup/grunt-apimocker

For Gulp, there's also a plugin contributed by kent-wu: https://github.com/kent-wu/gulp-apimocker

Running in Cloud Foundry

You can deploy apimocker into a cloud foundry instance by running cf push. The port you specify will be ignored, and you'll use the standard port 80 to access apimocker. When specifying your mockDirectory, you will need to use a relative path, like "samplemocks/". At this time, you'll need to do another build and push whenever you change a mock file.

Help

    apimocker -h

Configuration

On startup, config values are loaded from the config.json file. During runtime, mock services can be configured on the fly. See the sample config.json file in this package.

  • Config files can be either .json format, or in .js. When using .js, the module should export a config object, or a function that returns a config object.
  • Services can be configured to return different responses, depending on a request parameter or request header.
  • Content-type for a service response can be set for each service. If not set, content-type defaults to application/xml for .xml files, and application/json for .json files.
  • HTTP Status code can be set for each service.
  • Latency (ms) can be set to simulate slow service responses. Latency can be set for a single service, or globally for all services.
  • Allowed domains can be set to restrict CORS requests to certain domains.
  • Allowed headers can be set. (Default is to set "access-control-allow-headers: Content-Type" if not specified in config file.)
  • config.json file format has changed with the 0.1.6 release. See below for the new format. (Old config.json file format is deprecated and doesn't support new features, but still functioning.)
  • mockDirectory value can include tilde (~) for user's home directory.
  • A basepath can be specified to set a prefix on all web services. Preceding slash is required. For instance if basepath is set to "/apimocker", then all requests must go to "http://localhost:7878/apimocker/..."
  • A static route can be opened up to serve up static assets like images. Both staticDirectory and staticPath must be set. If either is not set, then nothing happens.
  • Additional headers can be defined for responses, in the headers object. Different headers could be returned for different requests, by enabling a switch.
  • Request headers can be logged, with the logRequestHeaders setting.
  • Alternate URL paths can be specified with the alternatePaths setting.
  • With the enableTemplate setting, values from the request can be inserted into the mock response.
  • With the templateSwitch setting, parameter names and values from the request can be mapped and inserted into the mock response, including POST requests and powerful JSONPath parameter substitution into a JSON POST body.
  • Set the allowAvoidPreFlight config option to true to allow requests sent with Content-Type: text/plain to be processed as json if possible. (default is false). This allows apimocker to work with servers such as Parse Server.
{
  "note": "This is a sample config file. You should change the mockDirectory to a more reasonable path.",
  "mockDirectory": "/usr/local/lib/node_modules/apimocker/samplemocks/",
  "staticDirectory": "/optional/file/system/path/to/static/directory",
  "staticPath": "/optional/web/path/to/static/directory",
  "quiet": false,
  "port": "7878",
  "latency": 50,
  "logRequestHeaders": false,
  "allowedDomains": ["abc.com"],
  "allowedHeaders": ["Content-Type", "my-custom-header"],
  "corsCredentials": "true",
  "webServices": {
    "first": {
      "mockFile": "king.json",
      "latency": 20,
      "verbs": ["get"],
      "alternatePaths": ["1st"]
    },
    "second": {
      "verbs": ["delete", "post"],
      "responses": {
        "delete": {"httpStatus": 204},
        "post": {
          "contentType": "foobar",
          "mockFile": "king.json"
        }
      }
    },
    "nested/ace": {
      "mockFile": "ace.json",
      "verbs": ["post", "get"],
      "switch": "customerId"
    },
    "nested/ace2": {
      "mockFile": "ace.json",
      "verbs": ["post", "get"],
      "switch": ["customerId","multitest"]
    },
    "var/:id": {
      "mockFile": "xml/queen.xml",
      "verbs": ["all"],
      "switch": "id"
    },
    "login": {
      "verbs": ["post"],
      "switch": ["userId", "password"],
      "responses": {
        "post": {"httpStatus": 401, "mockFile": "sorry.json"}
      },
      "switchResponses": {
        "userIduser1passwordgood": {"httpStatus": 200, "mockFile": "king.json"},
        "userIdadminpasswordgood": {"httpStatus": 200}
      }
    },
    "nested/aceinsleeve": {
      "verbs": [
        "post"
      ],
      "switch": "$..ItemId[(@.length-1)]",
      "responses": {
        "post": {"httpStatus": 200, "mockFile": "aceinsleeve.json"}
      },
      "switchResponses": {
        "$..ItemId[(@.length-1)]4": {"httpStatus": 500, "mockFile": "ItemId4.aceinsleeve.json"}
      }
    },
    "firstheaders": {
      "mockFile": "king.json",
      "contentType": "foobar",
      "headers": {
        "x-requested-by": "4c2df03a17a803c063f21aa86a36f6f55bdde1f85b89e49ee1b383f281d18c09c2ba30654090df3531cd2318e3c",
        "dummyheader": "dummyvalue"
      },
      "verbs": ["get"]
    },
    "template/:Name/:Number" :{
      "mockFile": "templateSample.json",
      "verbs":["get"],
      "enableTemplate": true,
      "contentType":"application/json"
    },
    "raw": {
      "mockBody": "{ \"text\" : \"Good Job!\" }",
      "verbs": ["all"]
    }
  }
}

The most interesting part of the configuration file is the webServices section. This section contains a JSON object describing each service. The key for each service object is the service URL (endpoint.) Inside each service object, the mockFile (or mockBody) and verbs are required. All other attributes of the service objects are optional. For instance, a GET request sent to "http://server:port/first" will return the king.json file from the samplemocks directory, with a 20 ms delay. Alternatively one can specify the mockBody directly, bypassing the need for a specific mock file. If you'd like to return different responses for a single URL with different HTTP verbs ("get", "post", etc) then you'll need to add the "responses" object. See above for the "second" service. The "responses" object should contain keys for the HTTP verbs, and values describing the response for each verb.

Switch response based on request parameter

In your configuration, you can set up a "switch" parameter for each service. If set, apimocker will check the request for this parameter, and return a different file based on the value. (Apimocker will check the request for the parameter in this order: first request body, second query string, third request headers.) For instance, if you set up a switch as seen above for "nested/ace", then you will get different responses based on the request sent to apimocker. A JSON POST request to the URL "http://localhost:7878/nested/ace" with this data:

{
  "customerId": 1234
}

will return data from the mock file called "customerId1234.ace.json". Switch values can also be passed in as query parameters: http://localhost:7878/nested/ace?customerId=1234 or as part of the URL, if you have configured your service to handle variables, like the "var/:id" service above: http://localhost:7878/var/789 If the specific file, such as "customerId1234.ace.json" is not found, then apimocker will attempt to return the base file: "ace.json".

For simple switching, you can use strings as shown in the configuration above. For more complex switching, using RegExp or JsonPath, you can use switch objects, to describe each switch.

{
	"type": "one of these strings: default|regexp|jsonpath",
	"key": "identifier used in mock file name",
	"switch": "string | regular expression | json path expression"
}

Multiple switches

You can now also define an array of values to switch on. Given the configuration in "ace2", a request to "nested/ace2" containing:

{
  "multitest": "abc",
  "customerId": 1234
}

will return data from the mock file called "customerId1234multitestabc.ace.json". Note that when using multiple switches, the filename must have parameters in the same order as configured in the "switch" setting in config.json. Also, apimocker will look for the filename that matches ALL the request parameters. If one does not match, then the base file will be returned.

Switch HTTP Status

To specify a different HTTP status, depending on a request parameter, you'll need to set up the "switchResponses" as shown above for the "login" service. You can also set a specific mock file using the "switchRespones" configuration. The switchReponses config section is an object, where the key is a composite of the switch keys specified in the "switch" setting for the service, and the values for each key, passed in as request parameters. For instance, a post request to "/login" containing:

{
  "userId": "user1",
  "password": "good"
}

will return data from the mock file called "king.json", with HTTP status 200. Any other password will return "sorry.json" with HTTP status 401.

JsonPath Support

For complex JSON requests, JsonPath expressions are supported in the switch parameter. If your switch parameter begins with "$." then it will be evaluated as a JsonPath expression. For example to switch the response based on the value of the last occurence of ItemId in a JSON request, use configuration as shown for "aceinsleeve":

"switch": "$..ItemId[(@.length-1)]",
  "responses": {
    "post": {"httpStatus": 200, "mockFile": "aceinsleeve.json"}
  },
  "switchResponses": {
    "$..ItemId[(@.length-1)]4": {"httpStatus": 500, "mockFile": "ItemId4.aceinsleeve.json"}
  }

According to this configuration, if the value of the last occurence of ItemId is 4, the mockFile "ItemId4.aceinsleeve.json" will be retured with a HTTP status code of 500. Otherwise, mockFile "aceinsleeve.json" will be returned with HTTP status 200. Note: If the JsonPath expression evaluates to more then 1 element (for example, all books cheaper than 10 as in $.store.book[?(@.price < 10)] ) then the first element is considered for testing the value.

JsonPath with Switch Response support

For requests that without any params should be returning a list of items (e.g. /users), and with some param just single item (e.g. /users/:id) there are special configuration options provided to select those single items from prepared mock json file containing list of items. No need to create separate files per each parameter. Example mock file could look like this:

[
    {
        "name": "Han Solo",
        "role": "pilot",
        "id": 1
    },
    {
        "name": "Chewbacca",
        "role": "first officer",
        "id": 2
    },
    {
        "name": "C3P0",
        "role": "droid",
        "id": 3
    },
    {
        "name": "R2D2",
        "role": "droid",
        "id": 4
    }
]

and example configurataion like this:

"users": {
  "mockFile": "users.json",
  "verbs": [
    "get"
  ]
},
"users/:id": {
  "mockFile": "users.json",
  "verbs": [
    "get"
  ],
  "switch": "id",
  "jsonPathSwitchResponse": {
      "jsonpath": "$[?(@.id==#id#)]",
      "mockFile": "users.json",
      "forceFirstObject": true
  }
},
"users/role/:role": {
  "mockFile": "users.json",
  "verbs": [
    "get"
  ],
  "switch": "role",
  "jsonPathSwitchResponse": {
    "jsonpath": "$[?(@.role==\"#role#\")]",
    "mockFile": "users.json",
    "forceFirstObject": false
  }
}

The first config property (users) contains just a standard get for all users. The second (users/:id) and third though (users/role/:role), contains a proper switch configuration and jsonPathSwitchResponse config that contains following parameters:

  • jsonpath - this is a JsonPath selector for objects to match inside mockFile; parameters values from switch are transferred to it's corresponding names wrapped in # characters,
  • mockFile - a file name with mocked response to search through,
  • forceFirstOject - (default: false) this is a switch telling if we should return all found items as an array, or select first one and return it as an object.

So it is possible to select just a single user by id as an object (/users/1), but it is also possible to return multiple users as an array (users/role/droid).

RegExp Support

As an alternative to JsonPath, Javascript Regular Expressions are supported in the switch parameter. See unit tests in the test.js file for examples of using Regular Expressions.

Returning additional headers with the response

To return additional custom headers in the response, set the headers map in the configuration file, like this example:

    "firstheaders": {
      "mockFile": "king.json",
      "contentType": "foobar",
      "headers": {
        "x-requested-by": "4c2df03a17a803c063f21aa86a36f6f55bdde1f85b89e49ee1b383f281d18c09c2ba30654090df3531cd2318e3c",
        "dummyheader": "dummyvalue"
      },
      "verbs": ["get"]
    }

In this example the headers x-requested-by and dummy will be returned on the response. contentType can be specified separately, as it is above, or specified as "content-type" in the "headers" map.

Templating your response

Templating is a powerful feature which allows values in the route, request parameters, or POST data to be inserted into the response, be it JSON, HTML, etc.

To utilize this capability, in the request string, insert a colon followed by a variable identifier at the location where the value should be substituted. Then set "enableTemplate" to true, specify a content type, and in the response file, wherever the substitution should appear, insert the '@' symbol followed by the chosen variable identifier. This placeholder can appear anywhere in the mock template file, including in multiple places.

In this first example, the values represented by Name and Number will be taken from the request and substituted into the response:

config.json

 "template/:Name/:Number" :{
   "mockFile": "templateSample.json",
   "verbs":["get"],
   "enableTemplate": true
   "contentType":"application/json"
 }

templateSample.json

{
  "Name": "@Name",
  "Number": "@@Number"
}

When you call /John/12345 you will be returned:

{
	"Name": "John"
	"Number": 12345
}

TemplateSwitch your response

Another form of templating uses the templateSwitch setting. This feature uses the same structure as the switch setting and is similar but more flexible than the enableTemplate feature in order to map parameter names and values from the request into the mock template response. GET and POST requests are supported including powerful JSONPath parameter substitution, even substitution into a JSON POST BODY.

To utilize this capability, add the templateSwitch section, specify a content type for the template file, and in the response file, wherever the substitution should appear, insert the '@' symbol followed by the chosen variable identifier. This placeholder can appear anywhere in the mock template file, including in multiple places.

The two templateSwitch examples show the flexibility of the templateSwitch syntax.

config.json with full switch attributes:

    "referral" : {
      "mockFile": "referral_error.json",
      "verbs": ["post"],
      "templateSwitch": [{"key": "partnerUserId",
                         "switch": "$.data.partner_user_id",
                         "type": "default"},
                         {"key": "affiliateKey",
                          "switch": "$.data.affiliate_key",
                          "type": "default"},
                         {"key": "email",
                          "switch": "$.data.contact_details.email",
                          "type": "default"},
                         {"key": "phone",
                          "switch": "$.data.contact_details.phone_number",
                          "type": "default"}],
      "contentType": "application/json",
      "responses": {
        "post": {"httpStatus": 200, "mockFile": "referral_success.json"}
      }
    },

config.json using key == switch, and type as default. This route returns an HTML mock template.

    "partner-join" : {
        "mockFile": "ijd_partner_smartbanner.html",
        "verbs":["get"],
        "templateSwitch": ["partner_user_id",
                           "affiliate_key",
                           "referral_id",
                           "email",
                           "phone"],
        "contentType":"text/html"
    },

with referral_success.json:

{
    "data" : {
      "partner_user_id": "@@partnerUserId",
      "referral_id": "21EC2020-3AEA-4069-A2DD-08002B30309D",
      "download_url" : "http://localhost:7878/app-download?affiliate_key=@affiliateKey&partner_user_id=@partnerUserId&referral_id=21EC2020-3AEA-4069-A2DD-08002B30309D&email=@email&phone=@phone"
    }
}

A POST request to /referral with a JSON POST body of:

   {
       "data": {
             "partner_user_id": 123456789,
             "affiliate_key": "ABCDEFG12345",
             "contact_details": {
                 "email": "[email protected]",
                 "phone": "800-555-1212"
             }
       }
   }

Will result in the referral_success.json with the POST body parameters inserted as follows:

{
    "data" : {
      "partner_user_id": 123456789,
      "referral_id": "21EC2020-3AEA-4069-A2DD-08002B30309D",
      "download_url" : "http://localhost:7878/app-download?affiliate_key=ABCDEFG12345&partner_user_id=123456789&referral_id=21EC2020-3AEA-4069-A2DD-08002B30309D&email=test%40apimocker.com&phone=800-555-1212"
    }
}

NOTE: In the template and templateSwitch examples above, special cases are included which will now be described below:

For a JSON template, if the value for the JSON key to be returned should be a numeric value, not a value wrapped in quotes, it is recommended to use the following convention: prefix the variable identifier with two '@' instead of one and within quotes: (e.g: "@@Number"). This tells the template parser to replace the quotes immediately before and after the placeholder as part of the templating process. This allows the mock JSON templates to remain valid JSON while still providing the ability to return numeric-only values.

Adding custom middleware

For advanced users, apimocker accepts any custom middleware functions you'd like to add. The middlewares property is an array of middleware functions you can modify. Here's a basic example:

var apiMocker = require("../lib/apimocker.js");
var customMiddleware = function(req, res, next) {
		res.header('foo', 'bar');
		next();
	};
var mocker = apiMocker.createServer({quiet: true}).setConfigFile("test/test-config.json");
mocker.middlewares.unshift(customMiddleware);
mocker.start(null, done);

Runtime configuration

After starting apimocker, mocks can be configured using a simple http api. This http api can be called easily from your functional tests, to test your code's handling of different responses.

/admin/setMock

This allows you to set a different response for a single service at any time by sending an http request. Request can be a post containing a JSON object in the body:

{
	"verb":"get",
	"serviceUrl":"third",
	"mockFile":"queen.xml",
    "latency": 100,
    "contentType": "anythingyouwant"
}

or a get with query string parameters: localhost:7878/admin/setMock?verb=get&serviceUrl=second&mockFile=ace.json

/admin/reload

If the config.json file is edited, you can send an http request to /admin/reload to pick up the changes.

Versions

See version history here: HISTORY.md

Contributors

Run "grunt watch" in the root "apimocker" directory to start the grunt watch task. This will run eslint and mocha tests. All Pull Requests must include at least one test.

Acknowledgements

Big thanks to magalhas for his httpd-mock project. This gave me a great starting point. Also thanks to clafonta and the Mockey project for inspiration.

License

This projected is licensed under the terms of the MIT license.

apimocker's People

Contributors

abhijeetahuja avatar aburmeis avatar aleofreddi avatar asnov avatar dependabot[bot] avatar dmeenhuis avatar dploeger avatar ebasilecimpress avatar enhan avatar ferrerod avatar gstroup avatar igutsaliuk avatar ivank avatar jcstover avatar jimihford avatar kopach avatar pawel-mika avatar pgraham avatar pgraham-acn avatar renovate-bot avatar samurai336 avatar stelio avatar thejonan avatar thomaslomas avatar twalker avatar wprater avatar ztsmith avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

apimocker's Issues

different content-type values for different responses

It would be great if we could specify different headers for different responses. For example, I would like to return either a file or a json string, depending on the Accept header in the request.

I can use "switch" to send back a different response based on the Accept Header, but there doesn't seem to be any way to set the response headers (e.g. content-type, etc.) per response.

Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response

Hi,

We are facing an issue - XMLHttpRequest cannot load http://localhost:7879/myApp/myService/v1/account. Method PATCH is not allowed by Access-Control-Allow-Methods in preflight response.

I tried adding CORS module and also tried adding response headers in my mock server but it didn't work, later found that adding the PATCH in apimaker.js resolved the issue.

node_modules\apimocker\lib\apimocker.js should have res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE'); instead res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');

Is there specific reason for not supporting PATCH ? without PATCH it works fine from postman but not working from our application.

It would be great if this could be resolved.

thanks,
Ashish Pashap

Switches aren't working for :id on get

Hi,
I want to do a simple switch based on and id for example:

"dogs/:id" { 
 "mockFile": "dogs/dog.json"
"verbs": [ "get"],
"switch": "id"
}

but it wont pick up dog1.dog.json with a request like:

GET /dogs/dog1

if I have it in the dogs directory. Thoughts? This is on the latest.

Hide <pre> Tags in DOM

Hi Greg,

how can I easily turn off that you node parses JSON into the < pre > Tags automatically?
Thank you for your help!

Is it also possible to output an empty DOM?

Is it possible to dump or list all expecations?

Clearly, the configuration is the starting point of the service.
However, since it's possible to create more expectations using the admin API, is it also possible to dump or reflect the in-memory configuration of the server, so that the next time we could have all configuration in a file?

Provide support for optional basepath in URL

I would like to be able to specify a "basepath" which is basically a prefix on webservices.

That helps me to use apimocker locally and in my Apigee API proxy, which specifies its own "basepath".

GET http://localhost:4000/basepath/customers

Then I can just change the value of basepath to "" when I deploy into Apigee
GET http://api-gateway:9000/basepath/customers

This can be done with express pretty straightforward.

apiMocker.express.use(options.basePath,apiMocker.router);

Cannot send empty body for default response

I cannot set a default response that only has httpStatus and no body:

"responses": {
"post": {"httpStatus": 401 }
}

I get the following error

/Users/myuser/Projects//mock-api/apiproxy/resources/node/node_modules/apimocker/lib/apimocker.js:394
mockFileParts = options.mockFile.split("/");
^

TypeError: Cannot read property 'split' of undefined
at Object.apiMocker.setSwitchOptions (/Users/miren/Projects/mock-api/apiproxy/resources/node/node_modules/myuser/lib/apimocker.js:394:35)
at Timeout._onTimeout (/Users/myuser/Projects/mock-api/apiproxy/resources/node/node_modules/apimocker/lib/apimocker.js:231:17)
at tryOnTimeout (timers.js:224:11)
at Timer.listOnTimeout (timers.js:198:5)

How to set paths in cloud foundry ?

I ma newbie and trying ti install server in cloud foundry. I have few questions

  • How to specify mockdirectory or static directory in CF world as there is no persistence available ?

'$' sign in URL is not working

Hi,

My service URL is like "abc/flights/$/incoming" and I am unable to mock this URL. Also there is no error in console.

Any workaround or solution.

Regards,

Jawwad

POST- Body regex support

Sers,

a common use case for e.g. POST, PUT is to have e.g. json in the request body.
Within the request, an ID is given, which I want to return a concrete response to.

A simple regex would be enough, I think.

How do you think about such an improvement?

POST parameters (switch?) available for template feature?

I would like to use the values of parameters in a JSON POST body and substitute them into a JSON template file that I will return as a response to this request. Is this possible? How would I accomplish this? Do I need to use a smart JSON-Path based switch statement to identify the parameters and then use the template naming convention within the response .json file? The current simplistic template example shows the templated parameters in the GET request query string, while I would like to use the my POST parameters.

Request params

Is it possible to deal with request params with apimocker? I'd like to handle the request e.g. /api/resource?page=1 and /api/resource?page=2 and so on.

Is it possible to negate value in switchResponses part of config.json?

Let's assume the code:

"switch": ["name", "age"],
"responses": {
  "post": {"mockFile": "default.json"}
},
"switchResponses": {
  "nameJohnage[NOT]20": {"mockFile": "John.json"},
  "nameJohnage20": {"mockFile": "John20.json"}
}

I expect that providing parameters name=John and age=99 would give a response from anyOtherJohn.json

I also thought about skipping the second parameter:

"switch": ["name", "age"],
"responses": {
  "post": {"mockFile": "default.json"}
},
"switchResponses": {
  "nameJohn": {"mockFile": "John.json"},
  "nameJohnage20": {"mockFile": "John20.json"}
}

But, by the documentation apimocker will look for the filename that matches ALL the request parameters. If one does not match, then the base file will be returned. So I guess I would get default.json instead of John.json for parameters name=John and age=99.
And I'm not sure what I would get for name=John and age=20

Please advice.

accept callback function for user requests as a parameter for apimock

Hi @gstroup ,

I use apimock like this:

var ApiMocker = require("apimocker");
var apiMocker = ApiMocker.createServer(options)
    .setConfigFile(__dirname + '/config.json')
    .start(port, function() {/* callback for establish connection */});

Now I faced the task to use TimeStamp in responses because of the strict security restrictions of the .Net WCF library.

Is it possible to add response callback function to apimock?

Not start apimocker -p -8081 -c config.json

Hi!
After update 0.3.3 my mock not working.
What's the problem?

config.json

{
    "note": "",
    "mockDirectory": "./api",
    "staticDirectory": "./static",
    "staticPath": "/",
    "quiet": false,
    "allowedDomains": ["*"],
    "allowedHeaders": ["access-control-allow-origin", "accept", "access-control-allow-headers", "access-control-allow-methods"],
    "latency": 0,

    "webServices": {
        "api/account/userinfo": {
            "httpStatus": 401,
            "mockFile": "200.json",
            "verbs": ["get"]
        },
        "api/account/logout": {
            "verbs": ["post"],
            "httpStatus": 200,
            "mockFile": "200.json"
        }
    }
}

c:\Code\apimocker>apimocker -p -8081 -c config.json

Loading config file: c:\Code\apimocker\config.json
Set route: GET api/account/userinfo : 200.json
Set route: POST api/account/logout : 200.json
Mock server listening on port -8081

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: listen EACCES
    at errnoException (net.js:904:11)
    at Server._listen2 (net.js:1023:19)
    at listen (net.js:1064:10)
    at Server.listen (net.js:1132:5)
    at Function.app.listen (C:\Users\DRyltsov\AppData\Roaming\npm\node_modules\apimocker\node_module
s\express\lib\application.js:525:24)
    at Object.apiMocker.start (C:\Users\DRyltsov\AppData\Roaming\npm\node_modules\apimocker\lib\apim
ocker.js:272:49)
    at Object.<anonymous> (C:\Users\DRyltsov\AppData\Roaming\npm\node_modules\apimocker\bin\apimocke
r.js:19:6)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)

Incorrect documentation around templating

Hey! Really great tool. We depend on this heavily here at Citi for our mobile apps.

Just wanted to call out an issue we had that unfortunately was caused by incorrect documentation here in your 'readme.md' file. Specifically, it's around templating.

In your example, you stated that for this configuration...

 "template/:Name/:Number" :{
   "mockFile": "templateSample.json",
   "verbs":["get"],
   "enableTemplate": true
   "contentType":"application/json"
 }

With this template...

{
  "Name": "@Name",
  "Number": "@Number"
}

When you call /John/12345 you claim it will return this:

{
	"Name": "John"
	"Number": 12345
}

But we're actually getting this...

{
	"Name": "John"
	"Number": "12345"  <-- Note the quotes
}

For one of our service calls, we needed the non-quote-wrapped number.

The confusion came in when we opened up our template in a JSON editor and tried removing the quotes around '@Number' but it started barking at us that we now had invalid JSON, so thinking that wasn't the correct approach, we abandoned it.

The problem is that actually is the correct way to format the template to have it return the placeholder without quotes. It just means that your template pre-filled-in is not valid JSON, and thus has to be edited with a text file. That's what tripped us up.

If you put a note/caveat/warning/whatever stating that if you need the non-quoted version, your template will no longer be valid JSON, but is still valid for Mocker (since it will become valid once merged) it would've gone a long way to helping people like us avoiding going down a rabbit hole trying to debug something we didn't actually have to debug.

That said, have you considered doing something like this for the tokens you don't want to have to wrap?

"#Number" or
"@@Number" or
"@Number@"
etc...

By implementing something like that (I'm personally partial to the '@@' myself) we can still keep our templates editable with a JSON editor without sacrificing output which is essential considering we run validation scripts against our JSON response files and now we have to explicitly exclude one.

It shouldn't be too difficult to implement with RegEx either. Just search for that version first, consuming the quotes as part of the search, then run the parsing again with the second flavor just as you do now. (You may even be able to format a single RegEx that handles both!)

Anyway, hope this helps. Again, keep up the really, really great work!

Mark

Unable to proxy request to https enpoint with selfsigned certificate

Certificate is valid for *.ab*.net
I'm trying to get data from path.abexample.net
As the result I'm getting:

Error: self signed certificate
    at Error (native)
    at TLSSocket.<anonymous> (_tls_wrap.js:1065:38)
    at emitNone (events.js:80:13)
    at TLSSocket.emit (events.js:179:7)
    at TLSSocket._init.ssl.onclienthello.ssl.oncertcb.TLSSocket._finishInit (_tls_wrap.js:593:8)
    at TLSWrap.ssl.onclienthello.ssl.oncertcb.ssl.onnewsession.ssl.onhandshakedone (_tls_wrap.js:425:38)

Any chances for switch to ignore that kind of errors?

configuring different types of HTTP status codes for routes

Hi @gstroup,

First to all, excellent tool you have here.

I have a suggestion for adding an improvement. It would be great if I can configure for certain routes that they return an specific HTTP status code rather than 200. For instance, I need to mock up a server which exposes a API with a DELETE verb. In this particular case, the only thing the server will respond is 204 HTTP status code (no body at all) to confirm that the removal I asked for worked fine. Unfortunately I cannot do this with the current code of apimocker.

Makes sense?

Thx in advance.

How to make multiple verbs in the same url return different files?

Hello, I am trying to mock a get/post using something like this:

"webServices": {
"user/:userId": {
"latency": 700,
"verbs": ["get", "post"],
"responses": {
"get": {
"mockFile": "user.json"
},
"post": {
"mockFile": "user_save.json"
}
}
},
...

But I am receiving the following warning from grunt:

WARNING: apimocker config file format is deprecated.
Warning: undefined is not a function Use --force to continue.

Aborted due to warnings.

It only happens when I try using the "responses" object, if I remove it and use a single "mockFile" it works fine.

Specify status code based on request/form parameter

Is there a way to specify a http status code based on a request/form parameter? For example if I have a rest api mock for authentication I wanna return 401 by default but in case they submit the password parameter with password it should return 200

Windows cannot switch parameters

Switch values can also be passed in as query parameters: http://localhost:7878/nested/ace?customerId=1234 or as part of the URL, if you have configured your service to handle variables, like the "var/:id" service above: http://localhost:7878/var/789 If the specific file, such as "customerId1234.ace.json" is not found, then apimocker will attempt to return the base file: "ace.json".

If the mockfile is set to api\\test\\get.json of endpoint api/:test and the user uses Windows and access api/foo it will return testfoo.api\test\get.json instead of api\test\testfoo.get.json.

Add proxy option

It would be great to have a function that allows any non-configured webservice endpoints to be forwarded to a proxy.

A possible use case might be if you only want to partially mock an API, and forward all non-mocked endpoints to the real API.

This looks relatively straight forward to implement, and I would be happy to submit a PR if there is interest.

One implementation question I have is - should we forward only for endpoints that are not configured, or also include endpoints where no switch value is matched?

support 404 by missing default mockFile

How to configure a mock that only returns a resource where the file is present for the switch but returns 404 otherwise? I would expect if I configure a mockFile test.json and have a switch id I would get id42.test.json contents if exists or 404 if test.json does not exists.

Even better would be to have an option to set the status for a missing mock file for a switch.

Dynamic content in response

Suppose I want dynamic content in reponse json/xml, like time-stamp, random number, uuid, then there should be some provision with enableTemplate feature to serve dynamic content if we annotate our json/xml like:
<queen> <suit>@name</suit> <time>@timestamp</time> <setup>@uuid</setup> </queen>

Mock url only if parameter contains variable

Hi,

I have a usecase where i want urls to be mocked only if they contain certain parameters, and else they should not deliver a mock, they should point to the real endpoint.

something like this:
"var/:id": { "mockFile": "xml/queen.xml", "verbs": ["all"], "switch": "id" }

but with the combination that the default points to the real endpoint and if there is a mock file with the correct switch value than this should be delivered.

Could you please think about implementing this ?
With regards,
Fabian

credentials

can't find how to add access-control-allow-credentials to header response

Optional or wildcard switch values

It would be great if there was a way to ignore values that are not important.
One possibility would be to use some kind of wildcard.

e.g. config setup with:
"switch": [ "Foo", "Bar" ],
"mockFile": "data.json"

A request URL of:
/example?Foo=1&Bar=2

Would match the files:
Foo1Bar2.data.json
FooBar2.data.json
Foo1Bar
.json

Where '*' is a wildcard matching any value.
The wildcard would likely need to be some kind of token to avoid filename issues:
e.g. Foo_any_Bar_any_

Another approach would be to make switch parameters optional. Effectively making any skipped parameter a wildcard.

The same request URL would match:
Bar2.data.json
Foo1.data.json

Looking at the code, this would require the setSwitchOptions function to return a collection of switch parameters and values. This would allow different (ordered) permutations of mock file loading to be tried.

Any thoughts? Would this be a major breaking change for some people?
If this sounds reasonable and I can find some time, I could put a PR together.

Issue with switches

Hi Greg,

I have defined a switch for my event.json.

"app/events/event_detail": {
"mockFile": "events/event.json",
"verbs": ["get"],
"switch": "event_id"
},

My case:

If I call the url "http://localhost:8888/app/events/event_detail?event_id=test"
and I have no specific json file created: the browser outputs me the "event.json". Everything is fine until here.

But is there a possibility to out put another "summertime.json" File when I call the URL "http://localhost:8888/app/events/event_detail" than the base file "event.json"?

What I want to do?

I want to handle error codes. So if I want to get back different ".json" files when I call:
"http://localhost:8888/app/events/event_detail?event_id=test" ( if not exist should return base file) AND
"http://localhost:8888/app/events/event_detail" (should not return the base file like in the case before)

I hope you can help me!

Cheers

204 response prevent any switchResponses to be executed

Take this simple endpoint config example:

"cards/updatePin": {
      "verbs": ["post"],
      "switch": ["notfound", "unauthorised"],
      "responses":{
        "post": {
            "httpStatus": 204
        }
      },
      "switchResponses": {
        "notfoundtrue": {"httpStatus": 404, "mockFile": "notfound.json"},
        "unauthorisedtrue": {"httpStatus": 403, "mockFile": "unauthorised.json"}
      }
    }

make a post request to cards/updatePin?notfound=true or cards/updatePin?unauthorised=true

EXPECTED result:

a 404 or 403 response is returned with payload defined in notfound.json or unauthorised.json

ACTUAL result:
204 code is always returned

How to mock 'Content-Type: application/soap+xml' requests?

Hello Guys!
I am trying to mock some soap xml API but I stucked with the problem that API receives gzip-ed request only So I have to send gzip-ed request from my app.
The question is how I can receive a gzip-ed request by apimock?
I have the next config for apimock: IIS + iisnode + node.js + apimock (using regexp type switchs to parse xml). Requests are gzip-ed xml files.
Thank you!

Handle multiple query parameters

I have the requirement to handle multiple query parameters and send switch responses based on that. For example: my client would trigger the URL as "{host-name}/management/v1/organizations/org/oauth2/revoke?enduser=abcd&app=efgh". How should the mocker resource in api mocker should look like ?
Currently, the documentation does not specify any implicit way to handle this requirement. Can you please confirm if we can handle this scenario ?

Apimocker crashes when mockFile is missing

Apimocker (v.0.4.0) crashes when required element mockFile is missing for webservice:

{
    "mockDirectory": "/home/me/apimocker",
    "quiet": false,
    "port": "8300",
    "webServices": {
        "items/1": {
            "verbs": ["get"]
        }
    }
}
$ apimocker -c config.json
Loading config file: /home/me/apimocker/config.json
Set route: GET items/1 : <no mockFile> 
Mock server listening on port 8300
curl -v localhost:8300/items/1                                                                                                                    โŽ
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 8300 (#0)
> GET /items/1 HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:8300
> Accept: */*
> 
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
path.js:360
        throw new TypeError('Arguments to path.join must be strings');
              ^
TypeError: Arguments to path.join must be strings
    at path.js:360:15
    at Array.filter (native)
    at Object.exports.join (path.js:358:36)
    at null._onTimeout (/usr/lib/node_modules/apimocker/lib/apimocker.js:151:21)
    at Timer.listOnTimeout [as ontimeout] (timers.js:112:15)

Maybe it should return 5xx server error HTTP status code insted?

Proxy post request hangs

With proxy request, posting with body hangs. You have to push bodyParser after proxy, this will fix the issue

Sample with SOAP request and swich SOAP response

Hi,

I can not find an example where the SOAP response change depending on what the SOAP request sent.
For example, if I send

<code>es</code>

I need receive (countryEs.xml)
<country>Spain</country>

and if I send
<code>fr</code>

I need receive (countryFr.xml)
<country>France</country>

could you help me with config.json?

Thank You!!!

Json coming in Request Parameter

Is the JSON coming in Request Parameter supported ?
like :

responseJSON= {
"customerId" : "12";
"city" : "Cincinnati"

}

can you use a switch statement on the request parameter : responseJSON and then parse it for customerId or city or both ?

Thanks

server shutdown when request data is invalid

Please see my log output. if the request data is invalid, the server will be shutdown.
I am working on window, i am not sure if linux have the sample probleam

C:\Users\pauldeng>apimocker
Loading config file: C:\Users\pauldeng\AppData\Roaming\npm\node_modules\apimocker\config.json
Set route: GET first : king.json 20 ms
Set route: POST first : ace.json 20 ms
Set route: DELETE second : 50 ms
Set route: POST second : king.json 50 ms
Set route: POST nested/ace : ace.json 50 ms
with switch on param: customerId
Set route: GET nested/ace : ace.json 50 ms
with switch on param: customerId
Set route: POST nested/ace2 : ace.json 50 ms
with switch on param: [ 'customerId', 'multitest' ]
Set route: GET nested/ace2 : ace.json 50 ms
with switch on param: [ 'customerId', 'multitest' ]
Set route: ALL var/:id/:color : xml/queen.xml 50 ms
with switch on param: [ 'id', 'color' ]
Set route: POST login : sorry.json 50 ms
with switch on param: [ 'userId', 'password' ]
Set route: GET template/:name/:number : templateSample.json 50 ms
Set route: GET templateSwitchGetParams : templateSwitchSample.json 50 ms
Set route: POST templateSwitchPostJsonPath : templateSwitchSample.json 50 ms
Mock server listening on port 7878
Returning mock: GET first : king.json
templateSwitch[appID] value NOT FOUND
templateSwitch[appName] value NOT FOUND
templateSwitch[userName] value NOT FOUND
templateSwitch[userAge] value NOT FOUND
Returning mock: GET templateSwitchGetParams : templateSwitchSample.json
C:\Users\pauldeng\AppData\Roaming\npm\node_modules\apimocker\lib\apimocker.js:190
key = switches[s].key;
^

TypeError: Cannot read property 'key' of undefined
at C:\Users\pauldeng\AppData\Roaming\npm\node_modules\apimocker\lib\apimocker.js:190:24
at Array.forEach (native)
at Object.apiMocker.fillTemplateSwitch (C:\Users\pauldeng\AppData\Roaming\npm\node_modules\apimocker\lib\apimocker.js:186:12)
at C:\Users\pauldeng\AppData\Roaming\npm\node_modules\apimocker\lib\apimocker.js:268:28
at FSReqWrap.readFileAfterClose as oncomplete
C:\Users\pauldeng>

Support Parse Server mocking.

Hi there.

Would be nice if this would also support Parse Server mocking.

The reason why it doesn't right now is that Parse Server avoids pre-flight requests by always sending a Content-Type of text/plain on the request headers.
Using that kind of Content-Type for requests that have the parameters inside the body as json makes the switch feature of apimocker useless - since that is not parsed in the current version with body-parser.
I would like to propose to add another middleware that will look something like this:

apiMocker.middlewares.push(bodyParser.json({
		strict: false,
		verify: saveBody,
		type: 'text/plain'
	}));

I will add it myself and make a PR but want to know how you feel about this.

Make `switch` option more useful

I suppose this is more of a general question about the usefulness of the switch option for a specific service configuration.

Let's take this example:

    "users/:userId": {
      "mockFile": "users/users.json",
      "verbs": ["get", "put"],
      "switch": "userId",
      "responses": {
        "put": {"httpStatus": 200, "mockFile": "users/updated.user.josn"}
      }
    }

Wouldn't it be great if what switch did was to look inside the specified mockFile of users/users.json, iterate the array to find where the value of the userId property matched the userId parameter sent in the request, then returned that single user object out of the array of users?

From what I can tell looking at apimocker's source, this is totally possible. If you think its a decent idea, I'd be more than willing to make a PR.

Thoughts?

Switch by json key

I have the following request structure (all requests POST to /):

AuthRequest:

{
  "Header": {...},
  "Body": {
    "AuthRequest": { <Parameters for Auth Request> }
  }
}

GetMailboxRequest:

{
  "Header": {...},
  "Body": {
    "GetMailboxRequest": { <Parameters for GetMailbox Request> }
  }
}

I'd have to deliver two mocks. One for the AuthRequest and one for the GetMailboxRequest.

So I need to switch by the first key of "Body"? Is this possible? I don't see how I can configure this. JsonPath doesn't seem to work for this specific task.

No License

This looks like a great project, but with no license information in the project I unfortunately can't use it in my environment.

Easy way to display images?

Hi Greg,

here is another interesting question:

As first! I like your api mocker very much. It is very easy to use and it makes fun! Great work!

But I've got a problem with simple files. I created a file structure with a folder called "images". The folder is full of '.jpgs' Images maybe more than 60. I don't want to define every single image with a mock-path. Is there a possibility to call them all like:

"images/events/*.jpg": {
      "mockFile": "images/events/*.jpg",
      "verbs": ["get"]
    },

So, that I can call them with their name (e.g 21442.jpg) and the path mentioned above?
Im looking forward for your help!

Kind regards,
Kevin

Should resolve ~ in path to home directory

If mockDirectory in config.json starts with '~', e.g. "mockDirectory": "~/some/path/", it should resolve the tilde to the current user's home directory.

E.g. if config.json looks like:

{
  "mockDirectory": "~/some/path/",
  "quiet": false,
  "port": "1234",
  "latency": 50,
  "allowedDomains": ["abc.com"],
  "allowedHeaders": ["Content-Type", "my-custom-header"],
  "webServices": {
    "a/b/c": {
      "mockFile": "some_file.json",
      "latency": 20,
      "verbs": ["get"]
    }
  }
}

And in ~/some/path/some_file.json you have:

{
  "this": "worked"
}

If you start apimocker and try to GET that provided service, it has an error, e.g.: Error: ENOENT, stat &#39;~/some/path/some_file.json&#39;.

A workaround is to modify the config prior to use to replace ~ in the mockDirectory value of config.json with the home directory path, e.g.:

mkdir -p tmp/apimock
sed 's#~#'$HOME'#g' config.json > tmp/apimock/config.json
apimocker -c tmp/apimock/config.json

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.