MOCK Service for testings http clients.
It work as service that allows to start/handle/stop the handlers for handling request to several different external services. Each handler works on its own port, has individual configuration and can:
- record forwarded requests&responses
- replay recorded responses
- passthrough some requests as just proxy (without recording it)
- work as an recorded responses re-player (all unknown requests will return HTTP 404 status code).
The configuration of handlers can be changed via http requests to management service port. Handlers also can be deactivated (stopped) and activated (started).
Each handler can handle simple requests (with compression of the response body when it allowed into to request header) and request with multiple response parts (with Transfer-Encoding: chunked
in the response header).
docker pull ghcr.io/slytomcat/http-mock:latest
Configuration of container can be done via environment variables MANAGEMENT_HOST
, MANAGEMENT_PORT
and MANAGEMENT_DATA
(see configuration for details).
You can also use dockerCompose.yml to start the configured container.
curl -sL https://github.com/slytomcat/http-mock/releases/latest/download/http-mock > http-mock
chmod a+x http-mock
or clone/download this repository source and build it by
./build.sh
executed from the repo folder. You need Golang v.1.20 or higher to build the binary. Also the build.sh
uses upx
utility to compact the binary but You may skip this step by commenting or removing the line with upc
call.
http-mock
It will start management service with default configuration on localhost:8080
and with _storage
as handlers config storage path.
Command line options can be used to set configuration values or to get help/version for http-mock
. It is help output:
http-mock is proxy/mock service v. master-xxxxxxxx
Usage:
http-mock [flags]
Examples:
http-mock --port 8080 --host localhost
Values for --port, --host, --data can be also set via environment variables MANAGEMENT_PORT, MANAGEMENT_HOST and MANAGEMENT_DATA.
Flags:
-d, --data string path for configs storage (default "_storage")
-h, --help help for http-mock
-s, --host string host to start service (default "localhost")
-p, --port int port to start service (default 8080)
-v, --version version for http-mock
- request
- Method:
GET
- URL:
/
- Method:
- request example
curl "http://localhost:8080"
- response
- Code 200: with the service version string
- request
- Method:
POST
- URL:
/new
- Body: json with the handler config
- Method:
- request example
curl "http://localhost:8080" -d '{"id":"my_handler","status":"active","port":8090}'
- response
- Code 200: json with a new handler id looking like:
{"id":"my_handler","status":"active","port":8090}
. When provided handler config contains"status":"active"
then handler will be started. - Code 400: means that the provided config couldn't be parsed, the body contain the config parsing error
- Code 200: json with a new handler id looking like:
- request
- Method:
GET
- URL:
/start?id=<handler id>
- Method:
- request example
curl "http://localhost:8080/start?id=my_handler"
- response
- Code 200: without body means that the handler was successfully started
- Code 420: means that provided handler id was not found, the body contain the error description
- Code 500: means that the starting of the handler have been failed, the body contain the error description
- request
- Method:
GET
- URL:
/stop?id=<handler id>
- Method:
- request example
curl "http://localhost:8080/stop?id=my_handler"
- response
- Code 200: without body means that the handler was successfully stopped
- Code 420: means that provided handler id was not found, the body contain the error description
- Code 500: means that the stopping of the handler have been failed, the body contain the error description
- request
- Method:
GET
- URL:
/list
- Method:
- request example
curl "http://localhost:8080/list"
- response
- Code 200: json list with handlers IDs and current statuses.
- request
- Method:
GET
- URL:
/config?id=<handler id>
- Method:
- request example
curl "http://localhost:8080/config?id=my_handler"
- response
- Code 200: with body containing the handler config
- Code 420: means that provided handler id was not found, the body contain the error description
- request
- Method:
POST
- URL:
/config?id=<handler id>
- Body: json with the handler config
- Method:
- request example
curl "http://localhost:8080/config?id=my_handler" -d '{"id":"my_handler","status":"active","port":8090}'
- response
- Code 200: without body means that the handler config was successfully stored
- Code 420: means that provided handler id was not found, the body contain the error description
- Code 400: means that the provided config couldn't be parsed, the body contain the error description
The changed value of host
and/or port
will restart active handler. The value of "status"
is also will affect the handler activity status: value "active"
will try to run or keep handler running, while value "inactive"
(or empty value) will stop or keep handler stopped.
- request
- Method:
DELETE
- URL:
/config?id=<handler id>
- Method:
- request example
curl -X DELETE "http://localhost:8080/config?id=my_handler"
- response
- Code 200: without body means that the handler config was successfully deleted
- Code 420: means that provided handler id was not found, the body contain the error description
If handler was active (started) then before deletion it will be stopped. Note that all handler data will be lost.
- request
- Method:
GET
- URL:
/response?id=<handler id>&resp-id=<response id>
- Method:
- request example
curl "http://localhost:8080/response?id=my_handler&resp-id=3A4CAD37B2985E4D47EC61D00A2241E3997C1AEAB9A37299217004892FEE7A3E"
- response
- Code 200: with body containing the requested response
- Code 400: means that provided response id was not found, the body contain the error description
- Code 420: means that provided handler id was not found, the body contain the error description
- request
- Method:
POST
- URL:
/response?id=<handler id>
- Body: json with the response to store in the handler config.
- Method:
- request example
curl "http://localhost:8080/response?id=my_handler" -d '{"url":"/some","code":200,"response":[{"data":"ok"}]}'
When fields url
and body
in the provided response are matching with fields url
and body
in the one of existing response, then that response will be overwritten.
If the provided response contains id
the response with the same id
will be deleted before storing new one. When there no response with id
in the provided response or when id
is not provided then the provided response will be written as new one.
- response
- Code 200: without body means that the response was successfully stored
- Code 400: means that provided response id was not found, the body contain the error description
- Code 420: means that provided handler id was not found, the body contain the error description
- request
- Method:
DELETE
- URL:
/response?id=<handler id>&resp-id=<response id>
- Method:
- response
- Code 200: without body means that the response was successfully deleted
- Code 400: means that provided response id was not found, the body contain the error description
- Code 420: means that provided handler id was not found, the body contain the error description
- request example
curl -X DELETE "http://localhost:8080/?id=my_handler&resp-id=3A4CAD37B2985E4D47EC61D00A2241E3997C1AEAB9A37299217004892FEE7A3E"
- request
- Method:
GET
- URL:
/dump-configs
- Method:
- response
- Code 200: without body means that all handler configs were successfully stored to local folder
- request example
curl "http://localhost:8080/dump-configs"
- request
- Method:
GET
- URL:
/load-configs
- Method:
- response
- Code 200: without body means that the handler configs were successfully loaded from local folder
- request example
curl "http://localhost:8080/load-configs"
The handler config is provided into JSON object with the following parameters (attributes):
mandatory parameters:
port
- port to start handler
optional parameters:
host
- host to start handler, by default it is "".id
- any unique ID that may be provided in handler creation or while updating config. If it is not provided it is automatically created as random 16 HEX symbols. Once handler id is set all the communication with handler is performed by thisid
.status
- current handler statusactive
- for handler that is started andinactive
when handler is not started. It is possible to start and stop handler by changing this config parameter via set handler config. When a new handler created with"status": "active"
then it will be automatically started.forward-url
- where to forward requests incoming requests. If it not provided the handler can only respond on known requests.passthrough-re
- regexp that used to pass through requests (without recording). This regexp have to match to the request url joined with the request body. By default it is regexp^$
that match only empty value. The passthrough mode requiresforward-url
to be set.url-re
- regexp that is applied to the request url. It can be used to specify the key part into the request url. By default it is^.*$
that match to whole URL with parameters.url-ex-re
- regexp for parts that have to be excluded form the request url that passed throughurl-re
regexp. All non-overlapping parts which match this regexp will be submitted to empty string. Default:^$
that match only empty value and it removes nothing from the request url.body-re
- the regexp for request body filtering. It can be used to specify the key part into the request body. By default it is"^.*$"
that match whole body.body-ex-re
- regexp for parts that have to be excluded form the request body that passed throughbody-re
regexp. All non-overlapping parts which match this regexp will be submitted on empty string. Default:^$
that match only empty value and it removes nothing from the request body.responses
- the array with recorded responses.
Each recorded response has following attributes:
id
- hex representation of SHA256 hash over the request's url and body (first passed throughurl-re
andbody-re
filters then filtered buurl-ex-re
andbody-ex-re
). When the response is changed (via set single response from handler config or set handler config) and the values ofurl
or/andbody
are changed it will change theid
. Previous id will be deleted in case of change in values ofurl
or/andbody
.url
- original request url with parameters.body
- original request body as string.code
- the HTTP status code of response.headers
- headers that have to be send with the response. By default the only very common heder items (likeDate
and e.t.c) will be sent.response
- list of response chunks. For simple response it contain one chunk. Several chunks mean that response is in chunked mode.
When response
contains more than one chunk the response header will contain Transfer-Encoding: chunked
even if it is non set into headers
. The Content-Length
will not be send into headed in this case.
If response
contains only one chunk and Transfer-Encoding: chunked
is set into headers
then it will be ignored (will not be send in response). The Content-Length
will be set into the response headers
with actual length of transferred data regardless of value set for this key into headers
in configuration of the response.
A good idea is: never use Transfer-Encoding: chunked
and Content-Length
into headers
.
Each element of response
list may contain:
data
- chunk data as stringdelay
- number of milliseconds to wait before sending the chunk data to requester. It is ignored for only one chunk (simple) response.
The chunk with data
and without delay
will be send immediately. Chunk without data
but with non-zero value of delay
will just add waiting before processing next chunk
without sending anything to requester. When delays into replayed response from http-mock
is not important then it can be removed from the stored response data.
Config example:
{
"ID":"my_handler",
"status":"active",
"host":"localhost",
"port":8090,
"responses":[
{
"id":"766C4650CB3E23432941DDCD3D663883BA3AF05C5DA44D79074657EB776B99C3",
"url":"/url",
"code":200,
"response":[{"data":"ok"}]
}
]
}
When the handler handles new request the url of request and its body is used to make the response id
. If that id
exists among the responses
then the recorded response is used as response on the request. When ID is not exists then that request is forwarded to the external service using forward-url
but if forward-url
is not set than HTTP 404 is returned.
When forward-url
is set then the request is forwarded and the received response will be replayed as request response and it will be stored into responses
.
When the request match the passthrough-re
then the forwarded request response is not stored.