Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
A tool for simple faking APIs of HTTP webservices.
Ruby CoffeeScript

This branch is 30 commits ahead, 3 commits behind jopek:master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
.bundle
bin
features
lib
spec
.gitignore
Gemfile
Gemfile.lock
LICENSE
README.rdoc
Rakefile
config.ru
holoserve.gemspec

README.rdoc

Holoserve - Simple faking of HTTP APIs

This tool can be used to fake HTTP web APIs. It's meant to be used in a testing environment, to make the test suite run faster and be independent from other API and network problems.

Concept

HoloServe runs a rack application server, that matches any incoming request to a list of request profiles. These profiles are defined in set of request/response-pairs. If a match is found, the defined static response is returned. The other half of the matched profile contains a set of responses. One for each situation the faked API can be possibily in. The response for the currently set situation will be merged with a default response and returned. The name of the matched request/response pair is saved in a request history. If no match is found, a 404 is returned and the request data is stored in the bucket for unhandeled requests. These informations can be used to extend the server layout with missing request handlers.

To avoid too much duplication in the definition of the request/response-pairs, it is possible upload some fixture data that is shared between all pair definitions. The pair can than refer to these fixtures.

The pairs, fixtures, situation, history and bucket can be accessed via control routes, which are described below.

Installation

Assuming that ruby and gem are installed, simply type…

gem install holoserve

Run from the command line

To start up an empty Holoserve instance, type…

holoserve

To load the server with a couple of pairs, fixtures and define a situation during start up, use these parameters.

holoserve -d path/to/pairs/*.yaml -f path/to/fixtures/*.yaml -s backend_without_users

Notice, that the files must have either the .yaml or the .json extension.

Control routes

If you're using Ruby, you can control Holoserve via the Holoserve Connector gem.

POST /_control/pairs

Adds a pair definition to Holoserve. It should receive a parameter named file that contains a file with exactly one pair. The format of the file should fit the specified format. The format can be yaml or json. See {Pair file format}[rdoc-label:Pair-file-format] below. The basename of the transmitted file will be taken as the pair id.

GET /_control/pairs/:id.:format

Returns the pair definition in the requested format.

DELETE /_control/pairs

Removes all pairs.

POST /_control/fixtures

Adds fixture data to Holoserve. The request is similar to POST /_control/pairs. The upload file can contain any yaml or json formatted data. The basename of the file will be taken as the fixture id.

GET /_control/fixtures/:id

Returns the requested fixture.

DELETE /_control/fixtures

Removes all fixtures.

PUT /_control/situation

Sets the current situation with the transmitted name parameter.

GET /_control/situation

Returns the name of the current situation.

Response example

backend_without_users

GET /_control/bucket

Returns a list of all requests that has been received, but couldn't be handled.

Response example

[
  {
    "method": "POST",
    "path": "test",
    "headers": {
      "REMOTE_ADDR": "127.0.0.1",
      "REQUEST_METHOD": "GET",
      "REQUEST_PATH": "/test",
      "PATH_INFO": "/test",
      "REQUEST_URI": "/test",
      "SERVER_PROTOCOL": "HTTP/1.1",
      "HTTP_VERSION": "HTTP/1.1",
      "HTTP_ACCEPT": "*/*",
      "HTTP_USER_AGENT": "Ruby",
      "HTTP_HOST": "localhost:8080",
      "SERVER_NAME": "localhost",
      "SERVER_PORT": "8080",
      "QUERY_STRING": "",
      "SCRIPT_NAME": "",
      "SERVER_SOFTWARE": "Unicorn 4.1.1"
    }
  }
]

GET /_control/history

Returns a list of all names of pairs that has been triggered.

Response example

[ "create_received", "update_received" ]

DELETE /_control/history

Removes all entries from the history.

Pair file format

The request/response pair file should have the following format.

- request:
    imports:
      - path: "test_fixture.users.0"
        as: "parameters"
        only: [ "username", "password" ]
    method: "POST"
    path: "/session"
    headers:
      HTTP_USER_AGENT: "Ruby"
    oauth:
      oauth_token: "12345"
  responses:
    default:
      status: 200
    user_exists:
      imports:
        - path: "test_fixture.users.0"
          as: "json.user"
    user_is_missing:
      json:
        message: "user not found"
- request:
    imports:
      - path: "test_fixture.users.0"
        as: "parameters"
        only: "username"
    method: "POST"
    path: "/session"
    headers:
      HTTP_USER_AGENT: "Ruby"
    parameters:
      password: "invalid"
    oauth:
      oauth_token: "12345"
  responses:
    user_exists:
      status: 401
      json:
        message: "invalid password"
    user_is_missing:
      status: 200
      json:
        message: "user not found"

The fixture data where this example pair definition relies on, could look like to following.

users:
  - email: "one@test.com"
    username: "one"
    password: "valid"

This example defines two request/response pairs and two situations. The two pairs differs only the parameters that they match against. The first one handles the case in which the parameters username=one and password=valid are posted and the second one reacts on the transmission of username=one and password=invalid.

If the situation is set to user_exists, the first situation would return the complete user object encoded as json, while the second one would reply the message “invalid password”. In the situation “user_is_missing”, both requests would be replied with the message “user not found”.

Something went wrong with that request. Please try again.