Giter VIP home page Giter VIP logo

canned's Introduction

Canned fake API server

Build Status Code Climate Gitter

View the docs on Docs, and join the chat at Gitter

Working with APIs, more often than not, during development you want to work with a fixed version of the responses provided. This is especially true if the API is still under development, and maybe even still needs input on how to output something. This is what Canned is for!

What does it do?

Canned maps a folder structure to API responses. Given the following directory structure:

/content/index.get.html
/comment/any.get.json
/comment/1/votes/index.get.json
/comment/any/votes/index.get.json

requests like

Accept: application/json
GET /comment/:id

are served from the file /comment/any.get.json as

Content-Type: application/json
{ "content": "I am a comment", "author": "sideshowcoder" }

requests like

Accept: text/html
GET /content/

are served from the file /content/index.get.html as

Content-Type: text/html
<html>
  <body>Some html in here</body>
</html>

requests like

Accept: application/json
GET /comment/1/votes

are served from the file /comment/1/index.get.json as

Content-Type: application/json
{ "content": "I am comment 1", "author": "sideshowcoder" }

requests like

Accept: application/json
GET /comment/123456789/votes

are served from the file /comment/any/index.get.json

Content-Type: application/json
{ "content": "I am a wildcard comment for any id", "author": "sideshowcoder" }

The matching works on the filename by treating it as PATH.VERB.CONTENT_TYPE so index.get.json has the path index the verb is get and the content-type json. Supported content types are

json   => application/json
html   => text/html
txt    => text/plain
js     => application/javascript
csv    => text/csv
// linked-data formats:
nt     => application/n-triples
jsonld => application/ld+json

So an example is for querying (with canned running on localhost:3000)

$ curl -H "Accept: text/javascript" http://localhost:3000/comment/1
> { "content": "I am a comment", "author": "sideshowcoder" }

Awesome! so what is supported?

Currently Canned supports the basic REST-API mapping, as well as custom method mapping with nested endpoints.

file                            | resquest
/index.get.json                 | GET /
/any.get.json                   | GET /:id
/_search.get.json               | GET /search
/comments/index.get.json        | GET /comments/
/comments/any.get.json          | GET /comments/:id
/comments/_search.get.json      | GET /comments/search
/comments/any/index.get.json    | GET /comments/:id/

You can even add query parameters to your filenames to return different responses on the same route. If the all query params in a filename match the incoming request, this file will be returned. It will fall back to returning the file with no query params if it exists.

Warning this will be deprecated in the future since canned now supports multiple response based on the request body or GET URL parameters in one file. This is the preferred way since files with ? in the name do not work on Windows

file                            | resquest
/index?name=Superman.get.json   | GET /?name=Superman&NotAllParams=NeedToMatch
/_search?q=hello.get.json       | GET /comments/search?q=hello
/_search.get.json               | GET /comments/search?iam=soignored

Same support is available for PUT, POST, etc.

/index.post.json            | POST serves /... + CORS Headers
/index.put.json             | PUT serves /... + CORS Headers

If CORS support is enabled additionally options will be available as a http verb and all requests will serve the CORS Headers as well

/                           | OPTIONS serve all the options needed for CORS
/index.get.json             | GET serves /... + CORS Headers

If you need some custom return codes, just add them to the file via adding a file header like so

//! statusCode: 201
<html>
  <body>Created something successfully! Happy!</body>
</html>

The header will be stripped before sending and the statusCode will be set.

You can also override the default content types by adding a custom content type to the file header:

//! contentType: "application/vnd.custom+xml"
<xml>
    <created>1</created>
</xml>

This will be returned with a Content-type: application/vnd.custom+xml header.

Multiple headers need to be written on one single line and comma-separated, like so:

//! statusCode: 201, contentType: "application/vnd.custom+xml"

If you need to send bind custom HTTP headers to the response you can add them as headers to the response file using the keyword customHeader:

//! customHeader: {"MyCustomHeaderName": "MyCustomHeaderValue"}

In case you need more then one custom header in the response, you can just use the same keyword multiple times:

//! customHeader: {"MyCustomHeaderName": "MyCustomHeaderValue"}
//! customHeader: {"SecondHeaderName": "SecondHeaderValue"}

Variable responses

You can get a different response by specifying request data in variant comments. If the request data matches the comment data the matching response is returned. If there is no match the first response is returned

Note: comments must be on a single line

Custom headers:

//! header: {"authorization": "abc"}
{
    "response": "response for abc"
}

//! header: {"authorization": "123"}
{
    "response": "response for 123"
}

If you need different responses based on request body then you can specify the request you want matched via body comments:

//! body: {"email": "[email protected]"}
{
    "response": "response for [email protected]"
}

//! body: {"email": "[email protected]"}
{
    "response": "response for [email protected]"
}

If you need different responses based on request parameters then you can specify them via parameters comments:

//! params: {"foo": "bar"}
{
    "response": "response for bar"
}

//! params: {"foo": "baz"}
{
    "response": "response for baz"
}

this would match http://my.local.server/my_get_request_path?foo=bar or http://my.local.server/my_get_request_path?foo=baz respectively.

To use in conjunction with response headers and status codes, just add them on the line above.

//! statusCode: 201
//! header: {"authorization": "abc"}
{
    "response": "response for abc"
}

//! statusCode: 201, contentType: "application/my-personal-json"
//! header: {"authorization": "123"}
{
    "response": "response for 123"
}

Wildcard responses are also supported, very useful to have 'wildcard' directories, so that if for given a request like:

GET /api/users/1/profile/

you don't have a file in ./canned/api/users/1/profile/index.get.json then it would look for a file in ./canned/api/users/any/index.get.json or similar. Wildcards can be specified on the command line via

canned --wildcard myany

This would change the lookup to ./canned/api/users/myany/index.get.json

How about some docs inside for the responses?

Most content types support comments natively, like html or javascript. Sadly the probably most used type (JSON) does not :(. So canned actually extends the JSON syntax a little so it can include comments with // or /**/. In case you use the JSON files directly on the backend side as test cases make sure you strip those out as well!

Ok I need this!

Just install via npm

$ npm install canned

which will install it locally in node_modules, if you want to have it available from anywhere just install globally

$ npm install -g canned

How do I use it

There are 2 ways here, either you embed it somewhere programmatically

var canned = require('canned')
,   http = require('http')
,   opts = { logger: process.stdout }

can = canned('/path/to/canned/response/folder', opts)

http.createServer(can).listen(3000)

Or just run the provided canned server script

$ canned

Which serves the current folder with canned responses on port 3000

$ canned -p 5000 ./my/responses/

will serve the relative folder via port 5000

If you need canned to respond with some delay, pass delay in ms to response_delay arg

$ canned --response_delay=1000 ./my/reponses/

If you want canned to iterate through all accepted content types in the Accept header, use

$ canned --relaxed_accept=true ./my/reponses/

If for whatever reason you want to turn of CORS support do so via

$ canned --cors=false ./my/responses/

Also if you need additional headers to be served alongside the CORS headers these can be added like this (thanks to runemadsen)

$ canned --headers "Authorization, Another-Header"

To enable CORS programmatically, you can use the following options:

var canned = require('canned')
,   http = require('http')
,   opts = {
        cors: true,
        cors_headers: ["Content-Type", "Location"]
    }

Optionally, the cors_headers value can be a comma-separated string, as per the CLI option.

Other optional options include:

var opts = {
        sanitize: false, // get responses as is without any sanitization
        response_delay: 2000, // delay the response for 2 seconds
        relaxed_accept: true // iterate through all accepted content types in the `Accept` header
        wildcard: 'myany', // specify 'wildcard' directory, e.g. ./canned/api/users/myany/index.get.json
    }

For more information checkout the pull request

Already using grunt? Great there is a plugin for that, thanks to jkjustjoshing.

It does not work :(

canned not found

make sure you either install globally or put ./node_modules/.bin in your PATH

it is still not found, and I installed globally

make sure /usr/local/share/npm/bin is in your path, this should be true for every install since you won't be able to run any global module bins if not. (like express, and such)

the encoding looks wrong

make sure you run a version of node which is 0.10.3 or higher, because it fixes a problem for the encoding handling when reading files

My JSON request body is not matching any responses

Set the "Content-Type" header to contain "application/json".

How to Contribute

  • Checkout the repository
  • Run the tests and jshint $ make
  • Create a topic branch $ git checkout -b my-new-feature
  • Code test and make jshint happy! $ make test $ make hint
  • Push the branch and create a Pull-Request

I try to review the pull requests as quickly as possible, should it take to long feel free to bug me on twitter

Release History

next

  • adding PATCH to default Access-Control-Allow-Method Cors header #113 (@william-mcmillian)
  • adding support for delayed responses #114 (@Onatolich)
  • adding support to make sanatize optional #115 (@YuliyaMarholina)

0.3.10

  • Windows line ending support #102 (@antxxxx)
  • cleanup and documentation #95 (@wadtech)
  • customHeader handling #110 (@mazoni)

0.3.9

  • relaxed handling for accept headers, meaning select the first result that can be served even if it is not the first accepted content type. option --relaxed-accept #100 (@CheungJ)

0.3.8

  • fix improper handling of carriage return in windows #79 (@git-jiby-me)
  • fix handling for urls in request body #90 (@wadtech)
  • documentation and test cases for cors headers #91 (@wadtech)
  • enable matching raw request body rather than property-based #96 (@ftes)
  • fix query string param handling #97 (@wadtech @targoo)

0.3.7

  • The regex for matching request, was not considering arrays in the request JSON #82
  • For request with a request body, canned was checking content type to exactly match application/json, which is not good as browsers may sent charset as well with the content type. #82
  • For matching request and filters with more accuracy, we were converting the values of all keys in request to string before comparing, but this was being done wrong as it was creating string of Objects and arrays as well, which it shouldn’t #82

0.3.6

  • support checking the ACCEPT HEADER for the response type (thanks git-jiby-me) #81

0.3.5

  • support for custom HTTP headers in responses
  • fix for matching multiple parameters in response #73 thanks xdemocle
  • fix any wildcard in the middle of the path #66 thanks msurdi

0.3.4

  • update dependencies and dev-dependencies
  • wildcard parameters thanks to msurdi see #64

0.3.3

  • fix support for special characters in the header / params / body matches (@simonprickett, @kevinschumacher, @sideshowcoder)
  • support differet statusCodes and content types in multiple response files (@sideshowcoder)

0.3.2

  • support for XML headers to support SOAP (@vikalp)
  • fix relative path again... (@sideshowcoder)

0.3.1

  • fixes for variable responses with JSON body (@bibounde)
  • fixes for relative paths on start (@sideshowcoder)
  • complex get parameters causing regexp match on file to fail (@sideshowcoder)

0.3

  • support for multiple responses per file (@hungrydavid)
  • support for GET responses without the need for special characters in the filename (@sideshowcoder based on the work by @hungrydavid)

0.2.3

  • added support for empty response with 204 for no content (@jkjustjoshing)

everything before

  • sorry haven't kept a version history, yet. Will now!

Contributors

License

MIT 2013 Philipp Fehre alias @sideshowcoder, or @ischi on twitter

canned's People

Contributors

antxxxx avatar bibounde avatar bill-bishop avatar bitdeli-chef avatar brendan-rius avatar cheungj avatar creynders avatar dadams-sessiondigital avatar dependabot[bot] avatar ftes avatar git-jiby-me avatar jacobpretorius avatar jkjustjoshing avatar kevinschumacher avatar leifg avatar mulderp avatar onatolich avatar runemadsen avatar sideshowcoder avatar simonprickett avatar targoo avatar vikalp avatar wadtech avatar xdemocle avatar yuliyamarholina 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

canned's Issues

Canned server crashed when I try to run a Python script using subprocess module

Hi Phil:

I have 2 scenarios here:

Scenario #1 (Works fine).

When I start canned API server on Python >> (Python CLI prompt)

>>> subprocess.Popen(["./startAPIServer"],stdout=subprocess.PIPE)                               
<subprocess.Popen object at 0x7f48c5825b10>

and run the "python add.py" (which does a curl POST) on regular $ prompt, everything works fine and dandy as expected.

$ python add.py
IP is 192.168.1.15
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   165  100   132  100    33   1848    462 --:--:-- --:--:-- --:--:--  1859

Values of Controller IDs and Controller Names that were successfully added.


Scenario #2.(Canned Server crashes and js error)

When I run both startServer script and add.py from python interactive mode,

>>> subprocess.Popen(["./startAPIServer"],stdout=subprocess.PIPE)
<subprocess.Popen object at 0x7f48c5825b10>
>>> subprocess.call("python add.py", shell=True,stderr=subprocess.PIPE)
IP is 192.168.1.15

Values of Controller IDs and Controller Names that were successfully added.

>>> 
events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: write EPIPE
    at errnoException (net.js:901:11)
    at Object.afterWrite (net.js:718:19)

As you have seen, Scenario #2 also works but after 4-5 seconds, I get the error message (which I presume if from Canned) and the Canned server crashes. Would you know why it would crash??

Just to clarify, the "add.py" does this :

proc = subprocess.Popen(["curl -X POST -i -H \"Content-type: application/json\" -X POST http://localhost:8080/v1/controllers -d '{\"url\": \"http://%s:%d\"}'" % (ip, i)], stdout=subprocess.PIPE, shell=True)
(out, error) = proc.communicate()

Option to proxy requests for unknown paths

If canned is used to stub out requests for a server it can be useful to proxy requests for unknown routes. The idea is to instead of serving a 404 forward the request to specified server and serve the result.

$ canned ./example --proxy=http://example.com 

when querying for a path that is not present in canned like

$ curl http://localhost:3000/i_dont_exist_in_canned

it shoudl issue a query to http://example.com/i_dont_exist_in_canned and serve
whatever the result of this query is.

Wildcards not working for _someFile.get.json

I have a file called _userAccount.get.json living in some/path/any/another/path/_userAccount.get.json

I want this file to be returned as a JSON response when my client accesses http://localhost:3000/some/path/12345/another/path/userAccount but with canned 0.3.7 this doesn't work. Canned logs: request: get /some/path/12345/another/path/userAccount not found

If I move the file to some/path/any/another/path/userAccount/index.get.json and access http://localhost:3000/some/path/12345/another/path/userAccount/ from the client the expected JSON is returned.

So it seems like the any wildcard is working for index.get.json files, but not for _anyFileName.get.json files.

Apostrophes in JSON response break the comment parser // !params etc

I've noticed that if I use the:

// !params: { "name": "value"}

notation to use a single JSON file to return different responses according to URL parameter value, this will break if the JSON response contains an apostrophe (and maybe some other "special" characters).

Here's an example showing that using the parameter in the filename works, but using the special comment notation does not work.

_test?param=a.get.json

File contains:

{
    "value": "This is value a's response."
}

http://localhost:3000/demo/test?param=a

{
value: "This is value a's response."
}

Works as expected.

_test?param=b.get.json

File contains:

{
    "value": "This is value b's response."
}

http://localhost:3000/demo/test?param=b

{
value: "This is value b's response."
}

Works as expected.

test2.get.json

File contains:

//! params: {"param": "a"}
{
    "value": "This is value a response."
}
//! params: {"param": "b"}
{
    "value": "This is value b response."
}

http://localhost:3000/demo/test2?param=a

{
value: "This is value a response."
}

Works as expected but note I removed the apostrophe from the file.

http://localhost:3000/demo/test2?param=b

{
value: "This is value b response."
}

Works as expected but note I removed the apostrophe from the file.

_test3.get.json

File contains:

//! params: {"param": "a"}
{
    "value": "This is value a's response."
}
//! params: {"param": "b"}
{
    "value": "This is value b's response."
}

http://localhost:3000/demo/test3?param=a

Internal Server error invalid input file

Logs:

request: get /demo/test3?param=aproblem sanatizing content for _test3.get.json SyntaxError: Unexpected end of input served via: ./demo/_test3.get.json

Broken because of ' in response?

http://localhost:3000/demo/test3?param=b

Internal Server error invalid input file

Logs:

request: get /demo/test3?param=bproblem sanatizing content for _test3.get.json SyntaxError: Unexpected end of input served via: ./demo/_test3.get.json

Broken because of ' in response?

I am using node v0.12.0 on Mac OS X 10.10.2. I think this is a problem in the JSON "comment parser", happy to take a look at addressing this, just wanted to see if this is a problem or something in my environment.

List all routes available

Currently canned resolves the routes on request, which is great since they can be modified while canned is running without any problems, adding new files/folders/etc. One thing missing so is the option to actually list what is available, currently this is mostly done by using tree to show the folder structure of the example folder, which prints something like this:

screen shot 2014-12-16 at 09 55 18

Sadly this does not take into account the rules canned has to resolve the paths, it would be awesome to get something like this:

example(master*)$ canned routes
verb   path
GET  /search
PUT  /comment/1
...

This means crawling the current file tree and resolving the routes and print.

Add some command line parsing

It would be nice to specify the directory as well as the port via the command line, so we should add some command line parsing here

Canned crashes when using query string parameters

node version: v6.1.0
Whenever you try to use query string parameters canned crashed with the following message

if(source.hasOwnProperty(prop)){
TypeError: source.hasOwnProperty is not a function

Wrong log output for files with query params

When I start canned in the spec/test_responses folder and I request a file with query params I get the correct file served but the output in the log shows the wrong file. This is not that bad but really confusing when mocking services which rely heavily on query params.

wrong_log

JSON is not found

I have the following file-structure:

/api
/api/index.get.html
/api/customer/index.get.json

I start canned via $ canned -p 5000 ./api

localhost:5000/ works.
localhost:5000/customer is not working -> request: get /customer/ not found

When I replace /api/customer/index.get.json with /api/customer/index.get.html it works as HTML-file.
I also tested all other possibilities from the docs, but I cannot get json-files to work :/

canned: 0.3.8
node: 5.11.0

Very long filename for regexmatchbug endpoint causes failed install

I'm using ecryptfs on Ubuntu and when I install canned, the _regexmatchbug file pushes the filename length over the limit.

Since this file is there to cover a regression I'm loathe to get rid of it but I don't know what other approach I can take to mitigate the problem.

I've appended the npm error output for clarity.

Currently I've been installing it into /tmp with npm install canned then removing the regexmatchbug file and then moving the directory to my project node_modules.

npm ERR! tar.unpack untar error /home/peter/.npm/canned/0.3.7/package.tgz
npm WARN enoent ENOENT: no such file or directory, open '/home/peter/projects/package.json'
npm WARN projects No description
npm WARN projects No repository field.
npm WARN projects No README data
npm WARN projects No license field.
npm ERR! Linux 4.2.0-25-generic
npm ERR! argv "/home/peter/.nvm/versions/node/v4.2.4/bin/node" "/home/peter/.nvm/versions/node/v4.2.4/bin/npm" "install" "canned"
npm ERR! node v4.2.4
npm ERR! npm  v3.5.3
npm ERR! path /home/peter/projects/node_modules/.staging/canned-55c23294/spec/test_responses/_regexmatchbug?u=root&p=root&q=select+mean(value)+from+%22Coraid.1Controller.ZFS.VOps-3008.gauge.wlat%22+where+time+%3E++now()+-+86400000000u+and+time+%3C+now()+-+0u+group+by+time(240000000u)+fill(null).get.json
npm ERR! code ENAMETOOLONG
npm ERR! errno -36
npm ERR! syscall open

npm ERR! ENAMETOOLONG: name too long, open '/home/peter/projects/node_modules/.staging/canned-55c23294/spec/test_responses/_regexmatchbug?u=root&p=root&q=select+mean(value)+from+%22Coraid.1Controller.ZFS.VOps-3008.gauge.wlat%22+where+time+%3E++now()+-+86400000000u+and+time+%3C+now()+-+0u+group+by+time(240000000u)+fill(null).get.json'
npm ERR! 
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     /home/peter/projects/npm-debug.log

Ability to log request headers and body

This could come in handy when troubleshooting within a dev/test environment.
The feature could be configurable, preferably via argument.

If I can get time, I'll see if I can submit a PR.

Status code combined with other options is not working

discovered while working on #58 combining statusCode and headers on seperate lines with //! does not work

//! statusCode: 201
//! body: { "foo": "bar" }

This should be handled by extractOptions which is only handling the status code right now.

Improve Error Message for invalid syntax

I observe the following:

pmu:tmp pmu$ mkdir api
pmu:tmp pmu$ cat > api/posts.json
[ "123" ]
pmu:tmp pmu$ canned
starting canned on port 3000 for ./
request: get /api/posts.json
/usr/local/share/npm/lib/node_modules/canned/lib/response.js:17
  this.cors_enabled = !!options.cors_enabled
                               ^
TypeError: Cannot read property 'cors_enabled' of undefined
    at new Response (/usr/local/share/npm/lib/node_modules/canned/lib/response.js:17:32)
    at /usr/local/share/npm/lib/node_modules/canned/canned.js:194:48
    at Object.oncomplete (fs.js:107:15)

Maybe I am missing something?

Starting the Canned API server works only with relative path not absolute path

Suppose I have a dir called "Abc" and I have 10 sub-directories in it "1" through "10". I want to start the canned API server for each of those - it works only with relative path ../../xxx/x/xx and not with absolute path (./canned -p 3000 ../zy/tz/ex) -> this works because it is relative. Why is that? Can it not work with absolute path?

Ability to specify a delayed response

Hi there,

This looks like a great mocking framework and exactly what I need for testing, so thanks for putting in all the hard work and sharing this! However I am looking to be able to simulate quite slow services with latency etc. So it would be a really great feature to be able to add a comment to set a delay

i.e. for 2000ms delay
//! delay: 2000

I know the obvious answer is to have a look myself and submit a pull request. So I will try if I get a chance, but I am new to node, so not sure if in reality I will or not. So just thought I would raise the suggestion.

Any tips on a starting point to implement this would also be great! :)

Cheers,
Rob

Bug: ENOENT No such file or directory when installing with Yarn 1.0.1 on Windows

Had this issue when installing canned with yarn 1.0.1 on Windows. I raised an issue over on Yarn and the issue was closed as being to fault with the canned package name.

What is the current behavior?
error An unexpected error occurred: "https://registry.yarnpkg.com/canned/-/canned-0.3.9.tgz: ENOENT: no such file or directory, open 'C:\Users\samjo\AppData\Local\Yarn\cache\v1\npm-canned-0.3.9-b0bfdeffdc595dd5c0055730b808d5c26b4caa02\spec\test_responses\_a?name=Batman&age=30.get.html'".

Steps to reproduce.
Running yarn add or in fact any yarn invocation after adding "canned": "^0.3.10" as a dev dependency to my package.json results in the error. Amending to use other versions of canned, e.g. 0.3.9 produce the same error.

Cause

this is noy Yarn's fault but a problem with the package itself. That file has ? in its name and that character is not allowed in file or folder names on Windows: https://support.microsoft.com/en-us/help/905231/information-about-the-characters-that-you-cannot-use-in-site-names--fo

All of this cited from the issue raised on the yarn github:
yarnpkg/yarn#4427

Automate update documentation Webpage

Currently the process of updating the documentation page involves

git checkout gh-pages
git checkout master -- README.md
echo "---\nlayout: index\n---" | cat - README.md > index.md
git add -A
git commit -m "update docs"
git push origin gh-pages

this is an error prone process, so It would be nice if we could do

make docs

File name is interpreted as regular expression

Canned is working great for simple file names such as v1/info/index.get.json. But when we have complicated names that we are testing from influxdb, it's giving an error saying that can't interpret as regular expression. Please suggest!

curl -sLGw "\n%{http_code} %{url_effective}\n" "http://localhost:17022/db/EtherCloudStats/series?u=root&p=root&q=select+mean(value)+from+%22Coraid.1Controller.ZFS.VOps-3008.gauge.wlat%22+where+time+%3E++now()+-+86400000000u+and+time+%3C+now()+-+0u+group+by+time(240000000u)+fill(null)"

Message from canned:
request: get /db/EtherCloudStats/series?u=root&p=root&q=select+mean(value)+from+%22Coraid.1Controller.ZFS.VOps-3008.gauge.wlat%22+where+time+%3E++now()+-+86400000000u+and+time+%3C+now()+-+0u+group+by+time(240000000u)+fill(null)
/home/msuri/ec/testeng/data/mock/canned/canned.js:29
new RegExp(fname + "(?=." + queryString.split("&").join(")(?=.") + ").+"
^
SyntaxError: Invalid regular expression: /(?=._u=root)(?=._p=root)(?=.*q=select+mean(value)+from+%22Coraid.1Controller.ZFS.VOps-3008.gauge.wlat%22+where+time+%3E++now()+-+86400000000u+and+time+%3C+now()+-+0u+group+by+time(240000000u)+fill(null)).+get/: Nothing to repeat
at new RegExp ()
at matchFileWithExactQuery (/home/msuri/ec/testeng/data/mock/canned/canned.js:29:5)
at getFileFromRequest (/home/msuri/ec/testeng/data/mock/canned/canned.js:51:13)
at Canned._responseForFile (/home/msuri/ec/testeng/data/mock/canned/canned.js:123:20)
at /home/msuri/ec/testeng/data/mock/canned/canned.js:168:10
at Object.oncomplete (fs.js:107:15)

Provide comment syntax for responses

The files don't provide a way to comment the fields or even the whole file, this would ease development and documentation.

something like

// this is a comment
{
  "key":"value",
  // another comment
  "keyTwo":"oneMoreValue"
}

should result in

{ "key":"value", "keyTwo":"oneMoreValue" } 

Serve custom HTTP headers on responses

I would like to be able to add custom HTTP headers on responses so I can fake - for example - the login process (which returns a Authorization header)

Crash if you rename folder

If you rename/delete a folder and make a request to the old location, the following error appears:

/usr/local/share/npm/lib/node_modules/canned/canned.js:19
  for (i = 0, e = files[i]; e != null; e = files[++i]) {
                   ^
TypeError: Cannot read property '0' of undefined
    at scanFileListForName (/usr/local/share/npm/lib/node_modules/canned/canned.js:19:24)
    at responseForFile (/usr/local/share/npm/lib/node_modules/canned/canned.js:54:10)
    at /usr/local/share/npm/lib/node_modules/canned/canned.js:103:9    at Object.oncomplete (fs.js:107:15)

Windows cannot deal with & and ? in filenames

When on windows checking out a repository which contains files with ? or & in their names will fail, since they are not valid chars for windows filenames. This is trouble when using get parameters encoded in the filename.

One way to solve this would be to add the parameters like a special comment as StatusCode already is. In this case their is the need to provide a way to have multiple files for the same path then. This could be solved by prefixing the filename with a number 1_search.get.xml would map to /search then.

Maybe this can be extended to be used for post and put body as well.

npm package not up to date?

Hey there. Thanks for canned - it's awesome!
I went to use the response_delay feature locally, but it looks like the latest package on npm doesn't have that code. Guessing that publishing to npm was just forgotten after that change.

Integrate with express

Not sure what we need todo here but it would be nice if it could be easily integrated with express during testing / development. Something like

var app = express()
app.configure("development", function() {
  express.use(canned("./"))
})

Would be awesome.

Full rewrite

Hiya,

here we go: canned.js and parser.js

So in a nutshell, what I did:
I turned canned into an express app and exposed a serve method which allows it to be used in express with app.use(canned.serve(myDir)) (obviously in the latter case it won't set up an express server of its own)
Then, parser.js reads the contents of the to-be-serverd directory, strips the extension of the filename and maps the result to the full file path in a hash. Then when a request is made it uses the hash to look up what file it needs to read.
If the file is .js it's required and the exposed function is called. In all other cases the file is read and it's contents are searched for headers:

/*headers
{
    "Content-Type": "application/vnd.custom+json",
    "Content-Disposition": "attachment"
}
*/

Headers must be declared as a json object, it has a number of benefits, but the main one is: you can create a .js file which reads a json file (depending on the route for instance, or the number of times the route is hit) and dumps it as a header in the output.
If the Content-type header is not set, mime is used to determine the content type by file extension.

Routes are resolved as follows: it will always try to find the file that closest matches the entire url first. E.g: GET /foo/bar/baz?qux=something will match the files, in the following order: (the file name is code-formatted below)

  • /foo/bar/baz?qux=something/GET.*
  • /foo/bar/baz?qux=something.*
  • /foo/bar/baz/GET.*
  • /foo/bar/baz.*
  • /foo/bar/GET.*
  • /foo/bar.*
  • /foo/GET.*
  • /foo.*
  • /GET.*

I know it's not backwards compatible, but IMO this is a cleaner and more flexible approach. And, there's not a large user base (yet), so I think we could get away with it. + migration is pretty easy.

It's quite a different approach, just let me know what you think!!

I haven't updated the bin nor the documentation or tests yet, I wanted to hear your opinion first...

Consider moving the documentation somewhere better

Currently the documentation lives in the readme, which is not ideal, maybe consider moving it to something like readthedocs.org for better viewablity and access.

What would be involved in doing this?

How does this work?

Get different response thank to params in json files doesn't works

I set my json file for multiple responses like below

//! params: {"limit": 40, "offset": 0}
{
  "name": "value1"
}

//! params: {"limit": 40, "offset": 40}
{
  "name": "value2"
}

But canned continue to deliver only the first response, despite I use a different query_list.
Any idea?

Ability to give different responses for a same polling request

I have a RestAPI which I poll from UI to get status of an operation. The API returns inprogress/success/failure for the same request.
I need to mock this API to first show inprogress and then succeeded.

Is there any way I can do this with canned?

Using more than one custom header does not work

Having multiple custom headers, such as the one from the readme:

//! customHeaders: [{"MyCustomHeaderName": "MyCustomHeaderValue"}, {"SecondHeaderName": "SecondHeaderValue"}] 

returns the error:

Invalid file header format try //! statusCode: 201

I believe this is due to the code on line 130 of canned.js:

var content = line.split(',').map(function (s) {

which splits the line on commas but should not actually be splitting on the comma located in the JSON string for the custom headers.

Json not appearing in browser

I have a simple file with a single Json object.

filename: index.get.json

    //! statusCode: 200
    { "content": "I am a wildcard comment for any id", "author": "sideshowcoder" }

After starting canned I open my browser and type http://localhost:3000/test into the address bar.
I see no output in chrome, safari, or firefox, and I get this response from canned:

  request: get /test not found

Chrome shows this error in the developer tools console:

  Failed to load resource: the server responded with a status of 404 (Not Found)

From the terminal I type:

   $ curl http://localhost:3000/test

and get this response:

   {"content":"I am a wildcard comment for any id","author":"sideshowcoder"}

and this output from canned:

  request: get /test served via: ./index.get.json

Create an API documentation page based on the files

Scanning through the directory to explore the API is nice but it would be great if it would be possible to output a simple HTML page which just lists the available endpoints with their requests.

Something like seen in the readme for showing what canned can do.

Default error message

Most API's have a default error message like this:

{"message":"404 Not found"}

It would be awesome if we could create a 404.json or something, and have a default error response from canned. Any thoughts on name and other functionality? I might take a stab at this soon.

CR/LF causing "Unexpected token" with variable responses.

On Windows 7. Having a file as follows with CR/LFs at the end of each line causes an "Unexpected token". Converting the EOL to LF works as expected.

Node version is 0.12.2 (x64) on Windows 7

//! params: {"serialkey": "abc"}
{
"errorCode": "ERROR1"
}

//! params: {"serialkey": "12121"}
{
"errorCode": "ERROR2"
}

Allow empty response body

When I have a DELETE endpoint I want to have an empty response body. Currently, canned assumes an empty response body is an error and returns a 500 status code. If the file is read properly I think an empty file should return a 204 status by default.

Doesn't consider Accepts Header to decide to return HTML or JSON

If i have one GET endpoint, returning HTML and JSON based on Accepts header, it always delivers the HTML content whatever be the Accepts Header.

As far as i see, if there is HTML and JSON responses for a endpoint, canned should check the Accepts Header to decide which content to sent

any as a directory name

I'm trying to figure out how to use the following example from the docs:

/comment/any/votes/index.get.json

it seems to me like requests such as
GET /comment/1/votes/
GET /comment/asdfasdf/votes/
or even
GET /comment/2/votes

should all map to this file.

However, that doesn't appear to be the behavior I'm seeing. Instead, I get 404 errors. Is this the designed behavior or is it a bug?

How are sym linked folders (with data) handled?

So when I have the Canned API server running and I make changes to a an "index.get.json" file, I do not have to restart my server (verified that and it works fine). I can continue sending requests and get responses (including the updated data from index.get.json). My question is if I have all the data in a folder called "Abc" and I sym link it "Def" in such a way that any requests that I send to "Abc" should be re-directed to "Def", that does not seem to work unless I re-start the canned API server. How is that handled/supposed to be handled in the source code?

Problem with relative path resolving

Version from about 2 weeks ago is working. So not sure if some configuration has changed, or if I need to start/configure it differently. These are the steps that I followed:

  1. Download version canned-0.3.1.zip, and unzipped it
  2. Ran canned for a particular directory
  3. Using curl for a response is giving 404
    starting canned on port 17022 for mockInflux/mockInfluxDB2
    request: get /db/EtherCloudStats/series not found
    request: get /db/EtherCloudStats/series?u=root&p=root&q=select+mean.get.json not foundHere is corresponding gist:

https://gist.github.com/mamtasuri-coraid/36d25df8e0c376b9fd91

Craft a new release and push to NPM

With the just merged PR #39 canned gained some functions worth pushing up to npm, and creating a new release... DO IT!

  • update version
  • update changelog
  • push to npm (with tag)
  • update docs page

improve getting started docs

@mulderp pointed out rightfully that the getting started is located rather awkward at the middle if the docs. I think to move it to the top would be great as long as their is a small example in there which explains more then just how to start canned but includes a simple one file setup maybe?

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.