This is a HTTP stub server for integration test with external APIs.
Key features:
- Single JAR
- Declarative API definition using YAML
- Template rendering and pattern matching using Groovy
- File watcher
- Gradle plugin (fork feature)
- Reverse proxy (fork feature)
- Request recording aka vhs (fork feature)
Please see fork features details
Download the latest release.
Java 11 or later is required.
At the moment the fork has no releases, you must download project and build it manually.
Or just use docker image from ghcr.io
Define a route as follows:
mkdir -p data
vim data/users.get.yaml
# data/users.get.yaml
- response:
headers:
content-type: application/json
body:
- id: 1
name: Foo
- id: 2
name: Bar
Or even simpler, with an old declaration
# data/users.get.yaml
- response:
headers:
content-type: application/json
body:
- id: 1
name: Foo
- id: 2
name: Bar
Run the application:
java -jar httpstub.jar
Call the API:
curl -v http://localhost:8080/users
> GET /users HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Thu, 16 Nov 2017 06:50:13 GMT
< Content-Type: application/json
< Transfer-Encoding: chunked
<
[{"name":"Foo","id":1},{"name":"Bar","id":2}]
The stub will reload YAML files if they have been changed or new one has been created.
Docker image is available on ghcr.io/gleb619/httpstub
.
docker run -v $PWD/data:/app/data:ro -p 8080:8080 ghcr.io/gleb619/httpstub
The fork is not yet available to download via docker, please download and build it locally
You can write log to a file.
By following option, the stub writes log to logs/spring.log
, rotates when it reaches 10MB and keeps up to 8 files.
See Spring Boot features: Logging for more.
# Command line option
java -jar httpstub.jar --logging.path=logs
# Environment variable
export LOGGING_PATH=logs
java -jar httpstub.jar
The stub shows following log for each request.
2017-12-05 10:44:20.042 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : > GET /users
2017-12-05 10:44:20.043 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : > Host: localhost:8080
2017-12-05 10:44:20.044 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : > User-Agent: curl/7.54.0
2017-12-05 10:44:20.044 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : > Accept: */*
2017-12-05 10:44:20.044 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : >
2017-12-05 10:44:20.047 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : < 200 OK
2017-12-05 10:44:20.048 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : < content-type: application/json
2017-12-05 10:44:20.049 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : < x-uuid: 1992cb3d-7bbf-4c2e-aa65-a19fa656f77e
2017-12-05 10:44:20.050 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : <
2017-12-05 10:44:20.050 INFO 19694 --- [ctor-http-nio-2] o.h.stubyaml.app.RequestResponseLogger : < [{"name":"Foo","id":1},{"name":"Bar","id":2}]
You can turn off logging by creating data/config.yaml
:
logging:
headers: false
body: false
Specify HTTP method in the extension part of filename.
For example, create a route file data/users.post.yaml
for handling POST method.
Following methods are supported.
- GET
- HEAD
- POST
- PUT
- PATCH
- DELETE
- OPTIONS
- TRACE
A braced string in the file path is treated as a path variable.
For example, create /users/{userId}.get.yaml
for handling /users/1
, /users/2
and so on.
You can set pairs of key and value to the headers. The value must be a string and is parsed as a template (see also the later section).
- response:
headers:
content-type: text/plain
x-uuid: "1234567890"
You can set multiple values.
- response:
headers:
set-cookie:
- sessionId=38afes7a8
- id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT
You can serve a text body as follows:
- response:
headers:
content-type: application/xml
body: |
<?xml version="1.0" encoding="UTF-8"?>
<users>
<user>
<id>1</id>
<name>Foo</name>
</user>
</users>
You can serve a JSON body as follows:
- response:
headers:
content-type: application/json
body:
id: 1
name: Alice
If a character set is specified in the content-type
header, the response body is encoded to the character set.
- response:
headers:
content-type: text/plain;charset=Shift_JIS
body: あいうえお
You can serve a file content as follows:
- response:
headers:
content-type: image/jpeg
file: photo.jpg
That means that you can store the larger response bodies in a separate file.
- response:
headers:
content-type: application/json
file: big-file.json
#big-file.json
{
"id": "123123",
"name": "Oliver",
...
"account": "YU89RE00"
}
Following values are parsed as a Groovy template:
- Response header value
- Response body (
body
) - Response filename (
file
) - Table key (
key
oftables
)
Following variables are available in a script block ${}
.
Variable | Object |
---|---|
path |
Path variables |
headers |
Request headers |
params |
Query parameters |
query |
Query parameters (alternative name) |
body |
Request body |
requestBody |
Request body (alternative name) |
Type of the request body may be one of following:
Content type of request | Type of request body |
---|---|
application/x-www-form-urlencoded |
Map<String, String> |
multipart/form-data |
Map<String, Part> |
application/json and subset |
Map<String, Object> |
application/xml and subset, text/xml and subset |
Map<String, Object> |
text/* |
String |
Otherwise | null |
For example, create /users/{userId}.get.yaml
as following:
- response:
headers:
content-type: application/json
body:
id: ${path.userId},
name: User${path.userId}
The stub will return the following response on the request GET /users/100
:
{
"id": 100,
"name": "User100"
}
A YAML file has one or more rules.
The stub evaluates each when
of all rules and returns the first matched response
.
Here is the example of /numbers.get.yaml
as follows:
- when: params.order == 'desc'
response:
headers:
content-type: application/json
body: [3, 2, 1]
- when: params.order == 'asc'
response:
headers:
content-type: application/json
body: [1, 2, 3]
#default response should be at the end of the list
- response:
headers:
content-type: application/json
body: [0]
The stub will return the following response on the request GET /numbers?order=asc
:
[1, 2, 3]
And on the request GET /numbers?order=desc
:
[3, 2, 1]
And on the request GET /numbers
:
[0]
If the last resort is not defined, the stub will return 404.
Define constants in data/config.yaml
:
constants:
today: "2017-12-01"
You can use constants in a route YAML:
- response:
headers:
content-type: application/json
body:
- id: 1
name: Foo
registeredDate: ${constants.today}
Tables are usuful for data variation testing.
Let's see the example.
Request condition: path.userId |
Response variable: tables.userName |
Response variable: tables.age |
---|---|---|
1 | Foo | 35 |
2 | Bar | 100 |
3 | Baz | 3 |
Create /users/{userId}.get.yaml
with following rule.
- response:
headers:
content-type: application/json
body:
id: ${path.userId}
name: ${tables.userName}
age: ${tables.age}
tables:
- name: userName
key: path.userId
values:
1: Foo
2: Bar
3: Baz
- name: age
key: path.userId
values:
1: 35
2: 100
3: 3
The stub will return the following response on the request GET /users/1
:
{
"id": 1,
"name": "Foo",
"age": 35
}
And on the request GET /users/2
:
{
"id": 2,
"name": "Bar",
"age": 100
}
Use delay
attribute in milliseconds to simulate network latency.
For example, create /users.post.yaml
as following:
- response:
delay: 500
headers:
content-type: application/json
body:
id: 1
Send the request POST /users
and the stub will return a response after 500 ms.
If you see in logs next exception java.io.IOException: User limit of inotify watches reached
don't afraid
just execute echo 16384 | sudo tee /proc/sys/fs/inotify/max_user_watches
on your linux machine
After 12.2019 for backward compatibilities added version to manifest files. Config files introduction of a versioning system for further development and addition of new features.
Variable | Object |
---|---|
v1.0 |
Old version of project |
v1.1 |
Added RuleContainer |
v1.2 |
Added Reverse proxy, Recorder, Printer, Writer |
v1.3 |
Container's logic refactor |
Please see fork features details
This is an open source software. Feel free to open issues and pull requests.