Compare commits

...

51 commits

Author SHA1 Message Date
55ee22c3a1
ci: secrets fix 2024-02-25 22:09:28 +01:00
65fba1eebc Merge pull request 'JDK 11 & Jakarta' (#1) from jakarta into dev
Reviewed-on: https://hattori.ztsh.eu/stawros/http-mock-server/pulls/1
2024-02-25 22:05:26 +01:00
2a11dd9b10
ci: fixed branches in reposilite deploy 2024-02-25 21:03:17 +01:00
ea16fa59d0
Jammy & multiplatform 2024-02-25 20:40:06 +01:00
1c5909cf8d
CI push tasks 2024-02-25 17:32:34 +01:00
0884505a18
CI 2024-02-23 23:32:02 +01:00
024bec4304
build: Surefire fixes 2024-02-23 00:04:20 +01:00
b2857d956b
chore: JRE in Dockerfile updated 2024-02-22 22:49:31 +01:00
5ddcb87179
feat!: Groovy 4 & JAXB 4 2024-02-22 22:48:45 +01:00
514064debc
feat!: Jakarta & JDK11 2024-02-22 22:48:02 +01:00
2fe3f2a67d
chore: Readme update 2024-02-22 22:44:02 +01:00
36bc5dd14b
Rebranding 2024-02-22 22:42:33 +01:00
Dominik Przybysz
afaab504da
Merge pull request #18 from TouK/dependabot/maven/ch.qos.logback-logback-core-1.3.12
Bump ch.qos.logback:logback-core from 1.2.9 to 1.3.12
2023-11-30 20:01:37 +01:00
dependabot[bot]
f9ae4a8003
Bump ch.qos.logback:logback-core from 1.2.9 to 1.3.12
Bumps [ch.qos.logback:logback-core](https://github.com/qos-ch/logback) from 1.2.9 to 1.3.12.
- [Commits](https://github.com/qos-ch/logback/compare/v_1.2.9...v_1.3.12)

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-29 22:06:34 +00:00
Łukasz Bigorajski
a3a7c4f8dc [maven-release-plugin] prepare for next development iteration 2023-06-01 17:51:38 +02:00
Łukasz Bigorajski
e44c1de1a2 [maven-release-plugin] prepare release http-mock-server-2.8.4 2023-06-01 17:51:30 +02:00
Łukasz Bigorajski
3413bfa0ad [maven-release-plugin] prepare for next development iteration 2023-06-01 11:11:57 +02:00
Łukasz Bigorajski
a825ad6fa2 [maven-release-plugin] prepare release http-mock-server-2.8.3 2023-06-01 11:11:53 +02:00
Piotr Fus
374947847d Handle any method as mock request method 2023-05-28 19:46:37 +02:00
Piotr Fus
8ba339b8a0 Setup github actions 2023-05-28 19:31:25 +02:00
Piotr Fus
ab6345234f Setup maven wrapper 2023-05-28 19:19:11 +02:00
Dominik Przybysz
763f303a65
Merge pull request #13 from TouK/dependabot/maven/ch.qos.logback-logback-core-1.2.9
Bump logback-core from 1.2.3 to 1.2.9
2023-04-17 08:21:51 +02:00
dependabot[bot]
23bba7e713
Bump logback-core from 1.2.3 to 1.2.9
Bumps logback-core from 1.2.3 to 1.2.9.

---
updated-dependencies:
- dependency-name: ch.qos.logback:logback-core
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-16 12:31:25 +00:00
Dominik Przybysz
82b22565d8
Merge pull request #12 from TouK/mockserver
Update httpclient
2021-06-08 07:58:37 +02:00
Piotr Fus
1a422fefca Update httpclient 2021-06-08 07:21:32 +02:00
Dominik Przybysz
b314332228
Merge pull request #11 from TouK/logback
Update logback
2021-06-08 06:35:20 +02:00
Piotr Fus
f8f2cfb125 Update logback 2021-06-07 20:39:08 +02:00
Piotr Fus
db93a99b9a [maven-release-plugin] prepare for next development iteration 2020-10-07 14:48:56 +02:00
Piotr Fus
8824634652 [maven-release-plugin] prepare release http-mock-server-2.8.2 2020-10-07 14:48:48 +02:00
Piotr Fus
6d52f8bceb [maven-release-plugin] prepare for next development iteration 2020-10-07 14:44:38 +02:00
Dominik Przybysz
c5a9450e00
Merge pull request #7 from lukasz-bigorajski/bump.groovy.version
Bump groovy version
2020-10-07 13:43:58 +02:00
Łukasz Bigorajski
170fb58c99 Bump groovy version 2020-10-07 13:25:07 +02:00
Piotr Fus
6438c661da [maven-release-plugin] prepare for next development iteration 2020-08-12 07:30:23 +02:00
Piotr Fus
531daa0fbe [maven-release-plugin] prepare release http-mock-server-2.8.0 2020-08-12 07:30:14 +02:00
Piotr Fus
c0188689f2
Merge pull request #6 from TouK/max.uses.history
Do not remove mock from history after max uses
2020-08-11 13:34:23 +02:00
Piotr Fus
fe9ef89970 Do not remove mock from history after max uses 2020-08-11 13:25:33 +02:00
Piotr Fus
769199f5d4 [maven-release-plugin] prepare for next development iteration 2020-08-10 12:27:17 +02:00
Piotr Fus
aa3919dbd2 [maven-release-plugin] prepare release http-mock-server-2.7.0 2020-08-10 12:27:09 +02:00
Piotr Fus
080516733a
Merge pull request #5 from TouK/dependabot/maven/org.apache.httpcomponents-httpclient-4.3.6
Bump httpclient from 4.3.5 to 4.3.6
2020-08-10 12:00:02 +02:00
dependabot[bot]
2cd84e3052
Bump httpclient from 4.3.5 to 4.3.6
Bumps httpclient from 4.3.5 to 4.3.6.

Signed-off-by: dependabot[bot] <support@github.com>
2020-08-10 09:53:13 +00:00
Piotr Fus
6044b3a275
Merge pull request #4 from TouK/max.uses.cyclic
Add limited mock uses
2020-08-10 11:52:48 +02:00
Piotr Fus
79622a4177 Add limited mock uses 2020-08-10 09:52:41 +02:00
Dominik Adam Przybysz
fcd99cf61f Build assembly by default 2019-04-04 19:42:37 +02:00
Dominik Przybysz
c118365bbe [maven-release-plugin] prepare for next development iteration 2018-09-04 13:07:27 +02:00
Dominik Przybysz
4128b8b49d [maven-release-plugin] prepare release http-mock-server-2.6.1 2018-09-04 13:07:18 +02:00
Anna Czajka
9c6afd599f Change schema resource fetching (#3) 2018-09-03 12:30:40 +02:00
Dominik Przybysz
579dd08d2f [maven-release-plugin] prepare for next development iteration 2018-02-28 14:30:32 +01:00
Dominik Przybysz
181f9dbcd9 [maven-release-plugin] prepare release http-mock-server-2.6.0 2018-02-28 14:30:22 +01:00
Piotr Fus
0727ced422 Add https support 2018-02-26 17:48:11 +01:00
piotrekfus91
f8e0cc44f9 Handle leading slash (#1)
* Handle leading slash
2018-01-28 18:30:50 +01:00
Dominik Przybysz
6036bd2c3b [maven-release-plugin] prepare for next development iteration 2017-06-02 08:32:23 +02:00
43 changed files with 1792 additions and 443 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
*.iml
target/
.idea
.mvn/wrapper/maven-wrapper.jar

18
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View file

@ -0,0 +1,18 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

View file

@ -1,5 +0,0 @@
language: groovy
jdk:
- oraclejdk8

59
.woodpecker.yaml Normal file
View file

@ -0,0 +1,59 @@
variables:
&maven_image maven:3.9.6-eclipse-temurin-11-alpine
when:
evaluate: 'not (CI_COMMIT_MESSAGE contains "Release")'
steps:
- name: build
image: *maven_image
commands:
- mvn -B clean install -DskipTests -Dmaven.test.skip
- name: test
image: *maven_image
commands:
- mvn -B -pl :mockserver-tests verify
- name: deploy to public
image: *maven_image
commands:
- mvn -B jar:jar deploy:deploy
secrets: [reposilite_user, reposilite_token]
when:
branch: [dev, master]
- name: deploy to releases
image: woodpeckerci/plugin-gitea-release
settings:
base-url: https://git.ztsh.eu
files:
- "mockserver-client/target/mockserver-client*.jar"
- "mockserver/target/mockserver-full.jar"
api_key:
from_secret: git_pat
when:
- event: tag
- name: tag docker image
image: woodpeckerci/plugin-docker-buildx
settings:
platforms: linux/amd64,linux/arm64/v8,linux/ppc64le,linux/s390x
repo: ztsheu/http-mock-server
registry: docker.io
tags: ${CI_COMMIT_TAG}
username: ztsheu
password:
from_secret: docker_pat
when:
- event: tag
- name: build docker image
image: woodpeckerci/plugin-docker-buildx
settings:
platforms: linux/amd64,linux/arm64/v8,linux/ppc64le,linux/s390x
repo: ztsheu/http-mock-server
registry: docker.io
tags: latest
username: ztsheu
password:
from_secret: docker_pat
when:
- event: tag
- event: push
branch: dev

View file

@ -1,4 +1,4 @@
FROM java:8 FROM eclipse-temurin:11.0.22_7-jre-jammy
ADD mockserver/target/mockserver-full.jar /mockserver.jar ADD mockserver/target/mockserver-full.jar /mockserver.jar
@ -8,4 +8,4 @@ RUN mkdir /externalSchema
VOLUME /externalSchema VOLUME /externalSchema
CMD java -cp /mockserver.jar:/externalSchema pl.touk.mockserver.server.Main CMD java -cp /mockserver.jar:/externalSchema eu.ztsh.mockserver.server.Main

View file

@ -54,6 +54,8 @@ testRest6 {
port=9999 port=9999
path='testEndpoint2' path='testEndpoint2'
name='testRest6' name='testRest6'
maxUses=1
cyclic=true
} }
testRest { testRest {
imports { imports {
@ -64,6 +66,21 @@ testRest {
path='testEndpoint' path='testEndpoint'
name='testRest' name='testRest'
} }
testHttps {
soap=false
port=10443
path='testHttps'
name='testHttps'
method='GET'
https={
keystorePath='/tmp/keystore.jks'
keystorePassword='keystorePass'
keyPassword='keyPass'
truststorePath='/tmp/truststore.jks'
truststorePassword='truststorePass'
requireClientAuth=true
}
}
``` ```
### Build with docker ### Build with docker
@ -77,7 +94,7 @@ docker-compose up -d
### Docker repoository ### Docker repoository
Built image is available at https://hub.docker.com/r/alien11689/mockserver/ Currently unavailable
Create mock on server Create mock on server
--------------------- ---------------------
@ -96,7 +113,17 @@ remoteMockServer.addMock(new AddMock(
statusCode: ..., statusCode: ...,
method: ..., method: ...,
responseHeaders: ..., responseHeaders: ...,
schema: ... schema: ...,
maxUses: ...,
cyclic: ...,
https: new Https(
keystorePath: '/tmp/keystore.jks',
keystorePassword: 'keystorePass',
keyPassword: 'keyPass',
truststorePath: '/tmp/truststore.jks',
truststorePassword: 'truststorePass',
requireClientAuth: true
)
)) ))
``` ```
@ -105,7 +132,7 @@ remoteMockServer.addMock(new AddMock(
Send POST request to localhost:<PORT>/serverControl Send POST request to localhost:<PORT>/serverControl
```xml ```xml
<addMock xmlns="http://touk.pl/mockserver/api/request"> <addMock xmlns="http://ztsh.eu/mockserver/api/request">
<name>...</name> <name>...</name>
<path>...</path> <path>...</path>
<port>...</port> <port>...</port>
@ -117,6 +144,16 @@ Send POST request to localhost:<PORT>/serverControl
<responseHeaders>...</responseHeaders> <responseHeaders>...</responseHeaders>
<schema>...</schema> <schema>...</schema>
<imports alias="..." fullClassName="..."/> <imports alias="..." fullClassName="..."/>
<maxUses>...</maxUses>
<cyclic>...</cyclic>
<https>
<keystorePath>/tmp/keystore.jks</keystorePath>
<keystorePassword>keystorePass</keystorePassword>
<keyPassword>keyPass</keyPassword>
<truststorePath>/tmp/truststore.jks</truststorePath>
<truststorePassword>truststorePass</truststorePassword>
<requireClientAuth>true</requireClientAuth>
</https>
</addMock> </addMock>
``` ```
@ -129,10 +166,24 @@ Send POST request to localhost:<PORT>/serverControl
- response - groovy closure as string which must evaluate to string which will be response of mock when predicate is satisfied, optional, default { _ -> '' } - response - groovy closure as string which must evaluate to string which will be response of mock when predicate is satisfied, optional, default { _ -> '' }
- soap - true or false, is request and response should be wrapped in soap Envelope and Body elements, default false - soap - true or false, is request and response should be wrapped in soap Envelope and Body elements, default false
- statusCode - integer, status code of response when predicate is satisfied, default 200 - statusCode - integer, status code of response when predicate is satisfied, default 200
- method - POST|PUT|DELETE|GET|TRACE|OPTION|HEAD, expected http method of request, default POST - method - POST|PUT|DELETE|GET|TRACE|OPTION|HEAD|ANY_METHOD, expected http method of request, default `POST`, `ANY_METHOD` matches all HTTP methods
- responseHeaders - groovyClosure as string which must evaluate to Map which will be added to response headers, default { _ -> \[:] } - responseHeaders - groovyClosure as string which must evaluate to Map which will be added to response headers, default { _ -> \[:] }
- schema - path to xsd schema file on mockserver classpath; default empty, so no vallidation of request is performed; if validation fails then response has got status 400 and response is raw message from validator - schema - path to xsd schema file on mockserver classpath; default empty, so no vallidation of request is performed; if validation fails then response has got status 400 and response is raw message from validator
- imports - list of imports for closures (each import is separate tag); `alias` is the name of `fullClassName` available in closure; `fullClassName` must be available on classpath of mock server - imports - list of imports for closures (each import is separate tag); `alias` is the name of `fullClassName` available in closure; `fullClassName` must be available on classpath of mock server
- https - HTTPS configuration
- maxUses - limit uses of mock to the specific number, after that mock is marked as ignored (any negative number means unlimited - default, cannot set value to 0), after this number of invocation mock history is still available, but mock does not apply to any request
- cyclic - should mock be added after `maxUses` uses at the end of the mock list (by default false)
#### HTTPS configuration
- keystorePath - path to keystore in JKS format, keystore should contains only one privateKeyEntry
- keystorePassword - keystore password
- keyPassword - key password
- truststorePath - path to truststore in JKS format
- truststorePassword - truststore password
- requireClientAuth - whether client auth is required (two-way SSL)
**HTTP** and **HTTPS** should be started on separated ports.
### Closures request properties ### Closures request properties
@ -149,13 +200,13 @@ In closures input parameter (called req) contains properties:
Response if success: Response if success:
```xml ```xml
<mockAdded xmlns="http://touk.pl/mockserver/api/response"/> <mockAdded xmlns="http://ztsh.eu/mockserver/api/response"/>
``` ```
Response with error message if failure: Response with error message if failure:
```xml ```xml
<exceptionOccured xmlns="http://touk.pl/mockserver/api/response">...</exceptionOccured> <exceptionOccured xmlns="http://ztsh.eu/mockserver/api/response">...</exceptionOccured>
``` ```
Peek mock Peek mock
@ -174,7 +225,7 @@ List<MockEvent> mockEvents = remoteMockServer.peekMock('...')
Send POST request to localhost:<PORT>/serverControl Send POST request to localhost:<PORT>/serverControl
```xml ```xml
<peekMock xmlns="http://touk.pl/mockserver/api/request"> <peekMock xmlns="http://ztsh.eu/mockserver/api/request">
<name>...</name> <name>...</name>
</peekMock> </peekMock>
``` ```
@ -182,7 +233,7 @@ Send POST request to localhost:<PORT>/serverControl
Response if success: Response if success:
```xml ```xml
<mockPeeked xmlns="http://touk.pl/mockserver/api/response"> <mockPeeked xmlns="http://ztsh.eu/mockserver/api/response">
<mockEvent> <mockEvent>
<request> <request>
<text>...</text> <text>...</text>
@ -214,7 +265,7 @@ Response if success:
Response with error message if failure: Response with error message if failure:
```xml ```xml
<exceptionOccured xmlns="http://touk.pl/mockserver/api/response">...</exceptionOccured> <exceptionOccured xmlns="http://ztsh.eu/mockserver/api/response">...</exceptionOccured>
``` ```
Remove mock Remove mock
@ -233,7 +284,7 @@ List<MockEvent> mockEvents = remoteMockServer.removeMock('...', ...)
Send POST request to localhost:<PORT>/serverControl Send POST request to localhost:<PORT>/serverControl
```xml ```xml
<removeMock xmlns="http://touk.pl/mockserver/api/request"> <removeMock xmlns="http://ztsh.eu/mockserver/api/request">
<name>...</name> <name>...</name>
<skipReport>...</skipReport> <skipReport>...</skipReport>
</removeMock> </removeMock>
@ -242,7 +293,7 @@ Send POST request to localhost:<PORT>/serverControl
Response if success (and skipReport not given or equal false): Response if success (and skipReport not given or equal false):
```xml ```xml
<mockRemoved xmlns="http://touk.pl/mockserver/api/response"> <mockRemoved xmlns="http://ztsh.eu/mockserver/api/response">
<mockEvent> <mockEvent>
<request> <request>
<text>...</text> <text>...</text>
@ -274,13 +325,13 @@ Response if success (and skipReport not given or equal false):
If skipReport is set to true then response will be: If skipReport is set to true then response will be:
```xml ```xml
<mockRemoved xmlns="http://touk.pl/mockserver/api/response"/> <mockRemoved xmlns="http://ztsh.eu/mockserver/api/response"/>
``` ```
Response with error message if failure: Response with error message if failure:
```xml ```xml
<exceptionOccured xmlns="http://touk.pl/mockserver/api/response">...</exceptionOccured> <exceptionOccured xmlns="http://ztsh.eu/mockserver/api/response">...</exceptionOccured>
``` ```
List mocks definitions List mocks definitions
@ -374,7 +425,7 @@ This response could be saved to file and passed as it is during mock server crea
Remote repository Remote repository
----------------- -----------------
Mockserver is available at `philanthropist.touk.pl`. Mockserver is available at `philanthropist.ztsh.eu`.
Just add repository to maven pom: Just add repository to maven pom:
@ -385,10 +436,16 @@ Just add repository to maven pom:
... ...
<repository> <repository>
<id>touk</id> <id>touk</id>
<url>https://philanthropist.touk.pl/nexus/content/repositories/releases</url> <url>https://philanthropist.ztsh.eu/nexus/content/repositories/releases</url>
</repository> </repository>
... ...
</repositories> </repositories>
... ...
</project> </project>
``` ```
FAQ
---
Q: *Can I have two mocks returning responses interchangeably for the same request?*
A: Yes, you can. Just set two mocks with `maxUses: 1` and `cyclic: true`.

View file

@ -1,15 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<parent> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>http-mock-server</artifactId>
<groupId>pl.touk.mockserver</groupId>
<version>2.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>http-mock-server</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>mockserver-api</artifactId> <artifactId>mockserver-api</artifactId>
<dependencies> <dependencies>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
@ -18,19 +24,9 @@
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin> <plugin>
<groupId>org.codehaus.mojo</groupId> <groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId> <artifactId>jaxb2-maven-plugin</artifactId>
<version>2.2</version>
<executions> <executions>
<execution> <execution>
<id>xjc</id> <id>xjc</id>

View file

@ -1,10 +1,9 @@
<?xml version="1.0"?> <bindings version="3.0"
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns="https://jakarta.ee/xml/ns/jaxb"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc">
jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings> <globalBindings>
<jxb:globalBindings>
<xjc:simple/> <xjc:simple/>
</jxb:globalBindings> </globalBindings>
</jxb:bindings>
</jxb:bindings> </bindings>

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://touk.pl/mockserver/api/common" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xs:schema version="1.0" targetNamespace="http://ztsh.eu/mockserver/api/common" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:simpleType name="method"> <xs:simpleType name="method">
<xs:restriction base="xs:string"> <xs:restriction base="xs:string">
@ -11,6 +11,7 @@
<xs:enumeration value="HEAD"/> <xs:enumeration value="HEAD"/>
<xs:enumeration value="OPTIONS"/> <xs:enumeration value="OPTIONS"/>
<xs:enumeration value="PATCH"/> <xs:enumeration value="PATCH"/>
<xs:enumeration value="ANY_METHOD" />
</xs:restriction> </xs:restriction>
</xs:simpleType> </xs:simpleType>
@ -18,5 +19,16 @@
<xs:attribute name="alias" type="xs:string"/> <xs:attribute name="alias" type="xs:string"/>
<xs:attribute name="fullClassName" type="xs:string"/> <xs:attribute name="fullClassName" type="xs:string"/>
</xs:complexType> </xs:complexType>
<xs:complexType name="https">
<xs:sequence>
<xs:element name="keystorePath" type="xs:string" />
<xs:element name="keystorePassword" type="xs:string" />
<xs:element name="keyPassword" type="xs:string" />
<xs:element name="truststorePath" type="xs:string" />
<xs:element name="truststorePassword" type="xs:string" />
<xs:element name="requireClientAuth" type="xs:boolean" />
</xs:sequence>
</xs:complexType>
</xs:schema> </xs:schema>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://touk.pl/mockserver/api/request" xmlns:tns="http://touk.pl/mockserver/api/request" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:common="http://touk.pl/mockserver/api/common"> <xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://ztsh.eu/mockserver/api/request" xmlns:tns="http://ztsh.eu/mockserver/api/request" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:common="http://ztsh.eu/mockserver/api/common">
<xs:import namespace="http://touk.pl/mockserver/api/common" schemaLocation="common.xsd"/> <xs:import namespace="http://ztsh.eu/mockserver/api/common" schemaLocation="common.xsd"/>
<xs:element name="addMock" type="tns:AddMock"/> <xs:element name="addMock" type="tns:AddMock"/>
@ -20,10 +20,13 @@
<xs:element name="soap" type="xs:boolean" minOccurs="0"/> <xs:element name="soap" type="xs:boolean" minOccurs="0"/>
<xs:element name="statusCode" type="xs:int" minOccurs="0"/> <xs:element name="statusCode" type="xs:int" minOccurs="0"/>
<xs:element name="method" type="common:method" minOccurs="0"/> <xs:element name="method" type="common:method" minOccurs="0"/>
<xs:element name="https" type="common:https" minOccurs="0" />
<xs:element name="responseHeaders" type="xs:string" minOccurs="0"/> <xs:element name="responseHeaders" type="xs:string" minOccurs="0"/>
<xs:element name="schema" type="xs:string" minOccurs="0"/> <xs:element name="schema" type="xs:string" minOccurs="0"/>
<xs:element name="imports" type="common:importAlias" minOccurs="0" maxOccurs="unbounded"/> <xs:element name="imports" type="common:importAlias" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="preserveHistory" type="xs:boolean" minOccurs="0"/> <xs:element name="preserveHistory" type="xs:boolean" minOccurs="0"/>
<xs:element name="maxUses" type="xs:int" minOccurs="0" />
<xs:element name="cyclic" type="xs:boolean" minOccurs="0" default="false" />
</xs:sequence> </xs:sequence>
</xs:extension> </xs:extension>
</xs:complexContent> </xs:complexContent>

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://touk.pl/mockserver/api/response" xmlns:tns="http://touk.pl/mockserver/api/response" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:common="http://touk.pl/mockserver/api/common"> <xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://ztsh.eu/mockserver/api/response" xmlns:tns="http://ztsh.eu/mockserver/api/response" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:common="http://ztsh.eu/mockserver/api/common">
<xs:import namespace="http://touk.pl/mockserver/api/common" schemaLocation="common.xsd"/> <xs:import namespace="http://ztsh.eu/mockserver/api/common" schemaLocation="common.xsd"/>
<xs:element name="exceptionOccured" type="tns:exceptionOccured"/> <xs:element name="exceptionOccured" type="tns:exceptionOccured"/>

View file

@ -1,22 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<parent> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>http-mock-server</artifactId>
<groupId>pl.touk.mockserver</groupId>
<version>2.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>http-mock-server</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>mockserver-client</artifactId> <artifactId>mockserver-client</artifactId>
<build>
<defaultGoal>clean install</defaultGoal>
</build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>groovy-all</artifactId> <artifactId>mockserver-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-json</artifactId>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-xml</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId> <artifactId>httpclient</artifactId>
@ -25,9 +47,15 @@
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<dependency>
<groupId>pl.touk.mockserver</groupId>
<artifactId>mockserver-api</artifactId>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
</plugin>
</plugins>
</build>
</project> </project>

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import groovy.transform.TypeChecked import groovy.transform.TypeChecked

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import groovy.transform.TypeChecked import groovy.transform.TypeChecked

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import groovy.transform.TypeChecked import groovy.transform.TypeChecked

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import groovy.transform.TypeChecked import groovy.transform.TypeChecked

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.HttpGet
@ -7,17 +7,17 @@ import org.apache.http.entity.ContentType
import org.apache.http.entity.StringEntity import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients import org.apache.http.impl.client.HttpClients
import pl.touk.mockserver.api.request.AddMock import eu.ztsh.mockserver.api.request.AddMock
import pl.touk.mockserver.api.request.MockServerRequest import eu.ztsh.mockserver.api.request.MockServerRequest
import pl.touk.mockserver.api.request.PeekMock import eu.ztsh.mockserver.api.request.PeekMock
import pl.touk.mockserver.api.request.RemoveMock import eu.ztsh.mockserver.api.request.RemoveMock
import pl.touk.mockserver.api.response.MockEventReport import eu.ztsh.mockserver.api.response.MockEventReport
import pl.touk.mockserver.api.response.MockPeeked import eu.ztsh.mockserver.api.response.MockPeeked
import pl.touk.mockserver.api.response.MockRemoved import eu.ztsh.mockserver.api.response.MockRemoved
import pl.touk.mockserver.api.response.MockReport import eu.ztsh.mockserver.api.response.MockReport
import pl.touk.mockserver.api.response.Mocks import eu.ztsh.mockserver.api.response.Mocks
import javax.xml.bind.JAXBContext import jakarta.xml.bind.JAXBContext
class RemoteMockServer { class RemoteMockServer {
private final String address private final String address

View file

@ -1,17 +1,18 @@
package pl.touk.mockserver.client package eu.ztsh.mockserver.client
import groovy.json.JsonSlurper import groovy.json.JsonSlurper
import groovy.transform.CompileStatic import groovy.transform.CompileStatic
import groovy.transform.TypeChecked import groovy.transform.TypeChecked
import groovy.util.slurpersupport.GPathResult import groovy.xml.XmlSlurper
import groovy.xml.slurpersupport.GPathResult
import org.apache.http.HttpEntity import org.apache.http.HttpEntity
import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.util.EntityUtils import org.apache.http.util.EntityUtils
import pl.touk.mockserver.api.response.ExceptionOccured import eu.ztsh.mockserver.api.response.ExceptionOccured
import pl.touk.mockserver.api.response.MockAdded import eu.ztsh.mockserver.api.response.MockAdded
import pl.touk.mockserver.api.response.MockServerResponse import eu.ztsh.mockserver.api.response.MockServerResponse
import javax.xml.bind.JAXBContext import jakarta.xml.bind.JAXBContext
@CompileStatic @CompileStatic
@TypeChecked @TypeChecked

View file

@ -1,49 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent> <parent>
<artifactId>http-mock-server</artifactId> <artifactId>http-mock-server</artifactId>
<groupId>pl.touk.mockserver</groupId> <groupId>eu.ztsh.mockserver</groupId>
<version>2.5.1</version> <version>3.0.0-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>mockserver-tests</artifactId> <artifactId>mockserver-tests</artifactId>
<build>
<defaultGoal>clean install</defaultGoal>
</build>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>groovy-all</artifactId> <artifactId>mockserver</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.spockframework</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>spock-core</artifactId> <artifactId>mockserver-client</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.spockframework</groupId>
<artifactId>httpclient</artifactId> <artifactId>spock-core</artifactId>
</dependency>
<dependency>
<groupId>pl.touk.mockserver</groupId>
<artifactId>mockserver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>pl.touk.mockserver</groupId>
<artifactId>mockserver-client</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.2.5</version>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View file

@ -0,0 +1,156 @@
package eu.ztsh.mockserver.tests
import eu.ztsh.mockserver.api.common.Https
import eu.ztsh.mockserver.api.request.AddMock
import eu.ztsh.mockserver.client.RemoteMockServer
import eu.ztsh.mockserver.client.Util
import eu.ztsh.mockserver.server.HttpMockServer
import groovy.xml.slurpersupport.GPathResult
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.conn.ssl.SSLConnectionSocketFactory
import org.apache.http.conn.ssl.SSLContexts
import org.apache.http.entity.ContentType
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import spock.lang.AutoCleanup
import spock.lang.Ignore
import spock.lang.Shared
import spock.lang.Specification
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLHandshakeException
import java.security.KeyStore
@Ignore
class MockServerHttpsTest extends Specification {
RemoteMockServer remoteMockServer = new RemoteMockServer('localhost', 19000)
@AutoCleanup('stop')
HttpMockServer httpMockServer = new HttpMockServer(19000)
@Shared
SSLContext noClientAuthSslContext = SSLContexts.custom()
.loadTrustMaterial(trustStore())
.build()
@Shared
SSLContext trustedCertificateSslContext = SSLContexts.custom()
.loadKeyMaterial(trustedCertificateKeystore(), 'changeit'.toCharArray())
.loadTrustMaterial(trustStore())
.build()
@Shared
SSLContext untrustedCertificateSslContext = SSLContexts.custom()
.loadKeyMaterial(untrustedCertificateKeystore(), 'changeit'.toCharArray())
.loadTrustMaterial(trustStore())
.build()
@Ignore("TODO: SSL peer shut down incorrectly")
def 'should handle HTTPS server' () {
given:
remoteMockServer.addMock(new AddMock(
name: 'testHttps',
path: 'testEndpoint',
port: 10443,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> "<goodResponse-${req.xml.name()}/>"}''',
https: new Https(
keyPassword: 'changeit',
keystorePassword: 'changeit',
keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path
),
soap: false
))
when:
HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client(noClientAuthSslContext).execute(restPost)
then:
GPathResult restPostResponse = Util.extractXmlResponse(response)
restPostResponse.name() == 'goodResponse-request'
}
@Ignore("TODO: SSL peer shut down incorrectly")
def 'should handle HTTPS server with client auth' () {
given:
remoteMockServer.addMock(new AddMock(
name: 'testHttps',
path: 'testEndpoint',
port: 10443,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> "<goodResponse-${req.xml.name()}/>"}''',
https: new Https(
keyPassword: 'changeit',
keystorePassword: 'changeit',
keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path,
truststorePath: MockServerHttpsTest.classLoader.getResource('truststore.jks').path,
truststorePassword: 'changeit',
requireClientAuth: true
),
soap: false
))
when:
HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client(trustedCertificateSslContext).execute(restPost)
then:
GPathResult restPostResponse = Util.extractXmlResponse(response)
restPostResponse.name() == 'goodResponse-request'
}
def 'should handle HTTPS server with wrong client auth' () {
given:
remoteMockServer.addMock(new AddMock(
name: 'testHttps',
path: 'testEndpoint',
port: 10443,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> "<goodResponse-${req.xml.name()}/>"}''',
https: new Https(
keyPassword: 'changeit',
keystorePassword: 'changeit',
keystorePath: MockServerHttpsTest.classLoader.getResource('keystore.jks').path,
truststorePath: MockServerHttpsTest.classLoader.getResource('truststore.jks').path,
truststorePassword: 'changeit',
requireClientAuth: true
),
soap: false
))
when:
HttpPost restPost = new HttpPost('https://localhost:10443/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
client(sslContext).execute(restPost)
then:
thrown(SSLHandshakeException)
where:
sslContext << [noClientAuthSslContext, untrustedCertificateSslContext]
}
private CloseableHttpClient client(SSLContext sslContext) {
return HttpClients.custom()
.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
.setSslcontext(sslContext)
.build()
}
private KeyStore trustedCertificateKeystore() {
return loadKeystore('trusted.jks')
}
private KeyStore untrustedCertificateKeystore() {
return loadKeystore('untrusted.jks')
}
private KeyStore trustStore() {
return loadKeystore('truststore.jks')
}
private KeyStore loadKeystore(String fileName) {
KeyStore truststore = KeyStore.getInstance(KeyStore.defaultType)
truststore.load(new FileInputStream(MockServerHttpsTest.classLoader.getResource(fileName).path), "changeit".toCharArray());
return truststore
}
}

View file

@ -1,6 +1,6 @@
package pl.touk.mockserver.tests package eu.ztsh.mockserver.tests
import groovy.util.slurpersupport.GPathResult import groovy.xml.slurpersupport.GPathResult
import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpDelete import org.apache.http.client.methods.HttpDelete
import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.HttpGet
@ -15,29 +15,29 @@ import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils import org.apache.http.util.EntityUtils
import pl.touk.mockserver.api.common.ImportAlias import eu.ztsh.mockserver.api.common.ImportAlias
import pl.touk.mockserver.api.common.Method import eu.ztsh.mockserver.api.common.Method
import pl.touk.mockserver.api.request.AddMock import eu.ztsh.mockserver.api.request.AddMock
import pl.touk.mockserver.api.response.MockEventReport import eu.ztsh.mockserver.api.response.MockEventReport
import pl.touk.mockserver.api.response.MockReport import eu.ztsh.mockserver.api.response.MockReport
import pl.touk.mockserver.client.InvalidMockDefinition import eu.ztsh.mockserver.client.InvalidMockDefinition
import pl.touk.mockserver.client.InvalidMockRequestSchema import eu.ztsh.mockserver.client.InvalidMockRequestSchema
import pl.touk.mockserver.client.MockAlreadyExists import eu.ztsh.mockserver.client.MockAlreadyExists
import pl.touk.mockserver.client.MockDoesNotExist import eu.ztsh.mockserver.client.MockDoesNotExist
import pl.touk.mockserver.client.RemoteMockServer import eu.ztsh.mockserver.client.RemoteMockServer
import pl.touk.mockserver.client.Util import eu.ztsh.mockserver.client.Util
import pl.touk.mockserver.server.HttpMockServer import eu.ztsh.mockserver.server.HttpMockServer
import spock.lang.Shared import spock.lang.AutoCleanup
import spock.lang.Ignore
import spock.lang.Specification import spock.lang.Specification
import spock.lang.Unroll
class MockServerIntegrationTest extends Specification { class MockServerIntegrationTest extends Specification {
RemoteMockServer remoteMockServer RemoteMockServer remoteMockServer
@AutoCleanup('stop')
HttpMockServer httpMockServer HttpMockServer httpMockServer
@Shared
CloseableHttpClient client = HttpClients.createDefault() CloseableHttpClient client = HttpClients.createDefault()
def setup() { def setup() {
@ -45,10 +45,6 @@ class MockServerIntegrationTest extends Specification {
remoteMockServer = new RemoteMockServer('localhost', 9000) remoteMockServer = new RemoteMockServer('localhost', 9000)
} }
def cleanup() {
httpMockServer.stop()
}
def "should add working rest mock on endpoint"() { def "should add working rest mock on endpoint"() {
expect: expect:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -70,6 +66,7 @@ class MockServerIntegrationTest extends Specification {
remoteMockServer.removeMock('testRest')?.size() == 1 remoteMockServer.removeMock('testRest')?.size() == 1
} }
@Ignore("TODO: restPostResponse.name()")
def "should add working rest mock on endpoint with utf"() { def "should add working rest mock on endpoint with utf"() {
expect: expect:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -244,7 +241,6 @@ class MockServerIntegrationTest extends Specification {
soapPostResponse.Body.'goodResponseSoap-request'.size() == 1 soapPostResponse.Body.'goodResponseSoap-request'.size() == 1
} }
@Unroll
def "should dispatch rest mocks when second on #name"() { def "should dispatch rest mocks when second on #name"() {
given: given:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -283,7 +279,6 @@ class MockServerIntegrationTest extends Specification {
9998 | 'test2' | 'another port and path' 9998 | 'test2' | 'another port and path'
} }
@Unroll
def "should dispatch rest mock with response code"() { def "should dispatch rest mock with response code"() {
given: given:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -857,7 +852,6 @@ class MockServerIntegrationTest extends Specification {
mockEvents2[0].response.statusCode == 202 mockEvents2[0].response.statusCode == 202
} }
@Unroll
def "should return mock report with #mockEvents events when deleting mock with flag skip mock = #skipReport"() { def "should return mock report with #mockEvents events when deleting mock with flag skip mock = #skipReport"() {
expect: expect:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -885,7 +879,6 @@ class MockServerIntegrationTest extends Specification {
true | 0 true | 0
} }
@Unroll
def "should reject mock when it has System.exit in closure"() { def "should reject mock when it has System.exit in closure"() {
when: when:
remoteMockServer.addMock(new AddMock( remoteMockServer.addMock(new AddMock(
@ -1133,4 +1126,58 @@ class MockServerIntegrationTest extends Specification {
remoteMockServer.removeMock('testRest')?.size() == 1 remoteMockServer.removeMock('testRest')?.size() == 1
} }
def 'should handle leading slash'() {
given:
String name = "testRest-${UUID.randomUUID().toString()}"
expect:
remoteMockServer.addMock(new AddMock(
name: name,
path: mockPath,
port: 9999,
statusCode: 201,
soap: false
))
when:
HttpPost restPost = new HttpPost("http://localhost:9999/$urlPath")
CloseableHttpResponse response = client.execute(restPost)
then:
response.statusLine.statusCode == 201
Util.consumeResponse(response)
expect:
remoteMockServer.removeMock(name)?.size() == 1
where:
mockPath | urlPath
'' | ''
'/' | ''
'test' | 'test'
'/test' | 'test'
'test/other' | 'test/other'
'/test/other' | 'test/other'
}
def 'should match any method'() {
given:
String name = "testRest-${UUID.randomUUID().toString()}"
remoteMockServer.addMock(new AddMock(
name: name,
path: 'any-method',
port: 9999,
statusCode: 201,
soap: false,
method: Method.ANY_METHOD
))
when:
CloseableHttpResponse response = client.execute(req)
then:
response.statusLine.statusCode == 201
Util.consumeResponse(response)
cleanup:
remoteMockServer.removeMock(name)
where:
req << [
new HttpGet('http://localhost:9999/any-method'),
new HttpPost('http://localhost:9999/any-method'),
new HttpPatch('http://localhost:9999/any-method')
]
}
} }

View file

@ -0,0 +1,239 @@
package eu.ztsh.mockserver.tests
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.impl.client.HttpClients
import eu.ztsh.mockserver.api.request.AddMock
import eu.ztsh.mockserver.client.RemoteMockServer
import eu.ztsh.mockserver.server.HttpMockServer
import spock.lang.AutoCleanup
import spock.lang.Specification
class MockServerMaxUsesTest extends Specification {
RemoteMockServer remoteMockServer
@AutoCleanup('stop')
HttpMockServer httpMockServer
CloseableHttpClient client = HttpClients.createDefault()
def setup() {
httpMockServer = new HttpMockServer(9000)
remoteMockServer = new RemoteMockServer('localhost', 9000)
}
def 'should return two mocks in order'() {
given:'mock with predicate is given but for only one use'
remoteMockServer.addMock(new AddMock(
name: 'mock1',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock1'}''',
maxUses: 1
))
and:'mock with the same predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'mock2',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock2'}''',
))
when:'we call the first time'
HttpPost restPost = new HttpPost('http://localhost:9999/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client.execute(restPost)
then:'first mock should be returned and expired'
response.entity.content.text == 'mock1'
when:'we call the second time using the same request'
CloseableHttpResponse response2 = client.execute(restPost)
then:'second mock should be returned'
response2.entity.content.text == 'mock2'
when:'we call the third time using the same request'
CloseableHttpResponse response3 = client.execute(restPost)
then:'second mock should be returned, because it has unlimited uses'
response3.entity.content.text == 'mock2'
}
def 'should return two mocks in order but only once'() {
given:'mock with predicate is given but for only one use'
remoteMockServer.addMock(new AddMock(
name: 'mock1',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock1'}''',
maxUses: 1
))
and:'mock with the same predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'mock2',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock2'}''',
maxUses: 1,
))
when:'we call the first time'
HttpPost restPost = new HttpPost('http://localhost:9999/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client.execute(restPost)
then:'first mock should be returned and expired'
response.entity.content.text == 'mock1'
when:'we call the second time using the same request'
CloseableHttpResponse response2 = client.execute(restPost)
then:'second mock should be returned'
response2.entity.content.text == 'mock2'
when:'we call the third time using the same request'
CloseableHttpResponse response3 = client.execute(restPost)
then:'no mock should be found'
response3.statusLine.statusCode == 404
and:'mock should exist'
remoteMockServer.listMocks().find { it.name == 'mock1' } != null
}
def 'should return two mocks in cyclic order'() {
given:'mock with predicate is given but for only one use'
remoteMockServer.addMock(new AddMock(
name: 'mock1',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock1'}''',
maxUses: 1,
cyclic: true,
preserveHistory: true
))
and:'mock with the same predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'mock2',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock2'}''',
maxUses: 1,
cyclic: true
))
when:'we call the first time'
HttpPost restPost = new HttpPost('http://localhost:9999/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client.execute(restPost)
then:'first mock should be returned and expired'
response.entity.content.text == 'mock1'
when:'we call the second time using the same request'
CloseableHttpResponse response2 = client.execute(restPost)
then:'second mock should be returned and expired'
response2.entity.content.text == 'mock2'
when:'we call the third time using the same request'
CloseableHttpResponse response3 = client.execute(restPost)
then:'first mock should be returned, because these mocks are cyclic'
response3.entity.content.text == 'mock1'
when:'we call the fourth time using the same request'
CloseableHttpResponse response4 = client.execute(restPost)
then:'second mock should be returned, because these mocks are cyclic'
response4.entity.content.text == 'mock2'
and:
remoteMockServer.peekMock('mock1').size() == 2
}
def 'should return two mocks with the same request interjected by another'() {
given:'mock with predicate is given but for only one use'
remoteMockServer.addMock(new AddMock(
name: 'mock1',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock1'}''',
maxUses: 1,
cyclic: true
))
and:'mock with the same predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'mock2',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock2'}''',
maxUses: 1,
cyclic: true
))
and:'mock with other predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'otherMock',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'otherRequest'}''',
response: '''{req -> 'otherMock'}'''
))
when:'we call the first time'
HttpPost restPost = new HttpPost('http://localhost:9999/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client.execute(restPost)
then:'first mock should be returned and expired'
response.entity.content.text == 'mock1'
when:'we call other request'
HttpPost otherRestPost = new HttpPost('http://localhost:9999/testEndpoint')
otherRestPost.entity = new StringEntity('<otherRequest/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse otherResponse = client.execute(otherRestPost)
then:'other mock should be called'
otherResponse.entity.content.text == 'otherMock'
when:'we call the second time using the same request'
CloseableHttpResponse response2 = client.execute(restPost)
then:'second mock should be returned and expired'
response2.entity.content.text == 'mock2'
when:'we call the third time using the same request'
CloseableHttpResponse response3 = client.execute(restPost)
then:'first mock should be returned, because these mocks are cyclic'
response3.entity.content.text == 'mock1'
}
def 'should return first mock twice'() {
given:'mock with predicate is given but for only one use'
remoteMockServer.addMock(new AddMock(
name: 'mock1',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock1'}''',
maxUses: 2
))
and:'mock with the same predicate is given'
remoteMockServer.addMock(new AddMock(
name: 'mock2',
path: 'testEndpoint',
port: 9999,
predicate: '''{req -> req.xml.name() == 'request'}''',
response: '''{req -> 'mock2'}''',
))
when:'we call the first time'
HttpPost restPost = new HttpPost('http://localhost:9999/testEndpoint')
restPost.entity = new StringEntity('<request/>', ContentType.create("text/xml", "UTF-8"))
CloseableHttpResponse response = client.execute(restPost)
then:'first mock should be returned and expired'
response.entity.content.text == 'mock1'
when:'we call the second time using the same request'
CloseableHttpResponse response2 = client.execute(restPost)
then:'again first mock should be returned'
response2.entity.content.text == 'mock1'
when:'we call the third time using the same request'
CloseableHttpResponse response3 = client.execute(restPost)
then:'second mock should be returned'
response3.entity.content.text == 'mock2'
}
def 'should throw exception if adding mock with incorrect maxUses'() {
when:
remoteMockServer.addMock(new AddMock(
name: 'mock1',
maxUses: 0
))
then:
thrown(RuntimeException)
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,46 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
<parent> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<artifactId>http-mock-server</artifactId>
<groupId>pl.touk.mockserver</groupId>
<version>2.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>http-mock-server</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>mockserver</artifactId> <artifactId>mockserver</artifactId>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>groovy-all</artifactId> <artifactId>mockserver-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-json</artifactId>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-xml</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-core</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>pl.touk.mockserver</groupId>
<artifactId>mockserver-api</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<defaultGoal>clean package assembly:single install</defaultGoal> <defaultGoal>clean package assembly:single install</defaultGoal>
<plugins> <plugins>
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
</plugin>
<plugin> <plugin>
<artifactId>maven-assembly-plugin</artifactId> <artifactId>maven-assembly-plugin</artifactId>
<configuration> <configuration>
<archive> <archive>
<manifest> <manifest>
<mainClass>pl.touk.mockserver.server.Main</mainClass> <mainClass>eu.ztsh.mockserver.server.Main</mainClass>
</manifest> </manifest>
</archive> </archive>
<descriptorRefs> <descriptorRefs>
@ -49,7 +79,17 @@
<finalName>mockserver-full</finalName> <finalName>mockserver-full</finalName>
<appendAssemblyId>false</appendAssemblyId> <appendAssemblyId>false</appendAssemblyId>
</configuration> </configuration>
<executions>
<execution>
<id>create-archive</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

View file

@ -1,24 +1,24 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpExchange
import groovy.transform.PackageScope import groovy.transform.PackageScope
import groovy.util.logging.Slf4j import groovy.util.logging.Slf4j
import pl.touk.mockserver.api.common.Method import eu.ztsh.mockserver.api.common.Method
import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.CopyOnWriteArrayList
@Slf4j @Slf4j
@PackageScope @PackageScope
class ContextExecutor { class ContextExecutor {
private final HttpServerWraper httpServerWraper private final HttpServerWrapper httpServerWrapper
final String path final String path
private final List<Mock> mocks private final List<Mock> mocks
ContextExecutor(HttpServerWraper httpServerWraper, Mock initialMock) { ContextExecutor(HttpServerWrapper httpServerWrapper, Mock initialMock) {
this.httpServerWraper = httpServerWraper this.httpServerWrapper = httpServerWrapper
this.path = "/${initialMock.path}" this.path = "/${initialMock.path}"
this.mocks = new CopyOnWriteArrayList<>([initialMock]) this.mocks = new CopyOnWriteArrayList<>([initialMock])
httpServerWraper.createContext(path) { httpServerWrapper.createContext(path) {
HttpExchange ex -> HttpExchange ex ->
try { try {
applyMocks(ex) applyMocks(ex)
@ -39,6 +39,7 @@ class ContextExecutor {
try { try {
if (mock.match(Method.valueOf(ex.requestMethod), request)) { if (mock.match(Method.valueOf(ex.requestMethod), request)) {
log.debug("Mock ${mock.name} match request ${request.text}") log.debug("Mock ${mock.name} match request ${request.text}")
handleMaxUses(mock)
MockResponse httpResponse = mock.apply(request) MockResponse httpResponse = mock.apply(request)
fillExchange(ex, httpResponse) fillExchange(ex, httpResponse)
log.trace("Mock ${mock.name} response with body ${httpResponse.text}") log.trace("Mock ${mock.name} response with body ${httpResponse.text}")
@ -92,4 +93,20 @@ class ContextExecutor {
List<Mock> getMocks() { List<Mock> getMocks() {
return mocks return mocks
} }
private synchronized void handleMaxUses(Mock mock) {
if (mock.hasLimitedUses()) {
mock.decrementUses()
resetIfNeeded(mock)
log.debug("Uses left ${mock.usesLeft} of ${mock.maxUses} (is cyclic: ${mock.cyclic})")
}
}
private void resetIfNeeded(Mock mock) {
if (mock.shouldUsesBeReset()) {
mock.resetUses()
mocks.remove(mock)
mocks.add(mock)
}
}
} }

View file

@ -1,37 +1,38 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpExchange
import groovy.util.logging.Slf4j import groovy.util.logging.Slf4j
import pl.touk.mockserver.api.common.ImportAlias import eu.ztsh.mockserver.api.common.Https
import pl.touk.mockserver.api.common.Method import eu.ztsh.mockserver.api.common.ImportAlias
import pl.touk.mockserver.api.request.AddMock import eu.ztsh.mockserver.api.common.Method
import pl.touk.mockserver.api.request.MockServerRequest import eu.ztsh.mockserver.api.request.AddMock
import pl.touk.mockserver.api.request.PeekMock import eu.ztsh.mockserver.api.request.MockServerRequest
import pl.touk.mockserver.api.request.RemoveMock import eu.ztsh.mockserver.api.request.PeekMock
import pl.touk.mockserver.api.response.ExceptionOccured import eu.ztsh.mockserver.api.request.RemoveMock
import pl.touk.mockserver.api.response.MockAdded import eu.ztsh.mockserver.api.response.ExceptionOccured
import pl.touk.mockserver.api.response.MockEventReport import eu.ztsh.mockserver.api.response.MockAdded
import pl.touk.mockserver.api.response.MockPeeked import eu.ztsh.mockserver.api.response.MockEventReport
import pl.touk.mockserver.api.response.MockRemoved import eu.ztsh.mockserver.api.response.MockPeeked
import pl.touk.mockserver.api.response.MockReport import eu.ztsh.mockserver.api.response.MockRemoved
import pl.touk.mockserver.api.response.MockRequestReport import eu.ztsh.mockserver.api.response.MockReport
import pl.touk.mockserver.api.response.MockResponseReport import eu.ztsh.mockserver.api.response.MockRequestReport
import pl.touk.mockserver.api.response.Mocks import eu.ztsh.mockserver.api.response.MockResponseReport
import pl.touk.mockserver.api.response.Parameter import eu.ztsh.mockserver.api.response.Mocks
import eu.ztsh.mockserver.api.response.Parameter
import javax.xml.bind.JAXBContext import jakarta.xml.bind.JAXBContext
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet import java.util.concurrent.CopyOnWriteArraySet
import java.util.concurrent.Executor import java.util.concurrent.Executor
import java.util.concurrent.Executors import java.util.concurrent.Executors
import static pl.touk.mockserver.server.Util.createResponse import static eu.ztsh.mockserver.server.Util.createResponse
@Slf4j @Slf4j
class HttpMockServer { class HttpMockServer {
private final HttpServerWraper httpServerWraper private final HttpServerWrapper httpServerWrapper
private final Map<Integer, HttpServerWraper> childServers = new ConcurrentHashMap<>() private final Map<Integer, HttpServerWrapper> childServers = new ConcurrentHashMap<>()
private final Set<String> mockNames = new CopyOnWriteArraySet<>() private final Set<String> mockNames = new CopyOnWriteArraySet<>()
private final ConfigObject configuration = new ConfigObject() private final ConfigObject configuration = new ConfigObject()
private final Executor executor private final Executor executor
@ -41,13 +42,13 @@ class HttpMockServer {
HttpMockServer(int port = 9999, ConfigObject initialConfiguration = new ConfigObject(), int threads = 10) { HttpMockServer(int port = 9999, ConfigObject initialConfiguration = new ConfigObject(), int threads = 10) {
executor = Executors.newFixedThreadPool(threads) executor = Executors.newFixedThreadPool(threads)
httpServerWraper = new HttpServerWraper(port, executor) httpServerWrapper = new HttpServerWrapper(port, executor)
initialConfiguration.values()?.each { ConfigObject co -> initialConfiguration.values()?.each { ConfigObject co ->
addMock(co) addMock(co)
} }
httpServerWraper.createContext('/serverControl', { httpServerWrapper.createContext('/serverControl', {
HttpExchange ex -> HttpExchange ex ->
try { try {
if (ex.requestMethod == 'GET') { if (ex.requestMethod == 'GET') {
@ -107,8 +108,11 @@ class HttpMockServer {
if (name in mockNames) { if (name in mockNames) {
throw new RuntimeException('mock already registered') throw new RuntimeException('mock already registered')
} }
if (request.maxUses == 0) {
throw new RuntimeException('cannot set maxUses to 0')
}
Mock mock = mockFromRequest(request) Mock mock = mockFromRequest(request)
HttpServerWraper child = getOrCreateChildServer(mock.port) HttpServerWrapper child = getOrCreateChildServer(mock.port, mock.https)
child.addMock(mock) child.addMock(mock)
saveConfiguration(request) saveConfiguration(request)
mockNames << name mockNames << name
@ -120,8 +124,11 @@ class HttpMockServer {
if (name in mockNames) { if (name in mockNames) {
throw new RuntimeException('mock already registered') throw new RuntimeException('mock already registered')
} }
if (co.maxUses == 0) {
throw new RuntimeException('cannot set maxUses to 0')
}
Mock mock = mockFromConfig(co) Mock mock = mockFromConfig(co)
HttpServerWraper child = getOrCreateChildServer(mock.port) HttpServerWrapper child = getOrCreateChildServer(mock.port, mock.https)
child.addMock(mock) child.addMock(mock)
configuration.put(name, co) configuration.put(name, co)
mockNames << name mockNames << name
@ -156,6 +163,9 @@ class HttpMockServer {
mock.responseHeaders = request.responseHeaders mock.responseHeaders = request.responseHeaders
mock.schema = request.schema mock.schema = request.schema
mock.preserveHistory = request.preserveHistory != false mock.preserveHistory = request.preserveHistory != false
mock.https = request.https
mock.maxUses = request.maxUses
mock.cyclic = request.cyclic
return mock return mock
} }
@ -170,13 +180,25 @@ class HttpMockServer {
mock.responseHeaders = co.responseHeaders ?: null mock.responseHeaders = co.responseHeaders ?: null
mock.schema = co.schema ?: null mock.schema = co.schema ?: null
mock.preserveHistory = co.preserveHistory != false mock.preserveHistory = co.preserveHistory != false
if (co.https) {
mock.https = new Https(
keystorePath: co.https.keystorePath ?: null,
keystorePassword: co.https.keystorePassword,
keyPassword: co.https.keyPassword,
truststorePath: co.https.truststorePath,
truststorePassword: co.https.truststorePassword,
requireClientAuth: co.https?.requireClientAuth?.asBoolean() ?: false
)
}
mock.maxUses = co.maxUses ?: null
mock.cyclic = co.cyclic ?: null
return mock return mock
} }
private HttpServerWraper getOrCreateChildServer(int mockPort) { private HttpServerWrapper getOrCreateChildServer(int mockPort, Https https) {
HttpServerWraper child = childServers[mockPort] HttpServerWrapper child = childServers[mockPort]
if (!child) { if (!child) {
child = new HttpServerWraper(mockPort, executor) child = new HttpServerWrapper(mockPort, executor, https)
childServers.put(mockPort, child) childServers.put(mockPort, child)
} }
return child return child
@ -244,6 +266,6 @@ class HttpMockServer {
void stop() { void stop() {
childServers.values().each { it.stop() } childServers.values().each { it.stop() }
httpServerWraper.stop() httpServerWrapper.stop()
} }
} }

View file

@ -0,0 +1,106 @@
package eu.ztsh.mockserver.server
import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer
import com.sun.net.httpserver.HttpsServer
import groovy.transform.PackageScope
import groovy.util.logging.Slf4j
import eu.ztsh.mockserver.api.common.Https
import javax.net.ssl.KeyManager
import javax.net.ssl.KeyManagerFactory
import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManager
import javax.net.ssl.TrustManagerFactory
import java.security.KeyStore
import java.security.SecureRandom
import java.util.concurrent.Executor
@Slf4j
@PackageScope
class HttpServerWrapper {
private final HttpServer httpServer
final int port
private List<ContextExecutor> executors = []
HttpServerWrapper(int port, Executor executor, Https https = null) {
this.port = port
InetSocketAddress addr = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port)
httpServer = buildServer(addr, https)
httpServer.executor = executor
log.info("Http server starting on port $port...")
httpServer.start()
log.info('Http server is started')
}
private HttpServer buildServer(InetSocketAddress addr, Https https) {
if (https) {
HttpsServer httpsServer = HttpsServer.create(addr, 0)
httpsServer.httpsConfigurator = new HttpsConfig(buildSslContext(https), https)
return httpsServer
} else {
return HttpServer.create(addr, 0)
}
}
private SSLContext buildSslContext(Https https) {
KeyManager[] keyManagers = buildKeyManager(https)
TrustManager[] trustManagers = buildTrustManager(https)
SSLContext ssl = SSLContext.getInstance('TLSv1')
ssl.init(keyManagers, trustManagers, new SecureRandom())
return ssl
}
private KeyManager[] buildKeyManager(Https https) {
KeyStore keyStore = KeyStore.getInstance('jks')
keyStore.load(new FileInputStream(https.keystorePath), https.keystorePassword.toCharArray())
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.defaultAlgorithm)
kmf.init(keyStore, https.keyPassword.toCharArray())
return kmf.keyManagers
}
private TrustManager[] buildTrustManager(Https https) {
if (https.requireClientAuth) {
KeyStore trustStore = KeyStore.getInstance('jks')
trustStore.load(new FileInputStream(https.truststorePath), https.truststorePassword.toCharArray())
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.defaultAlgorithm)
tmf.init(trustStore)
return tmf.trustManagers
} else {
return []
}
}
void createContext(String context, HttpHandler handler) {
httpServer.createContext(context, handler)
}
void addMock(Mock mock) {
ContextExecutor executor = executors.find { it.path == mock.path }
if (executor) {
executor.addMock(mock)
} else {
executors << new ContextExecutor(this, mock)
}
log.info("Added mock ${mock.name}")
}
void stop() {
executors.each { httpServer.removeContext(it.contextPath) }
httpServer.stop(0)
}
List<MockEvent> removeMock(String name) {
return executors.collect { it.removeMock(name) }.flatten() as List<MockEvent>
}
List<MockEvent> peekMock(String name) {
return executors.collect { it.peekMock(name) }.flatten() as List<MockEvent>
}
List<Mock> getMocks() {
return executors.collect { it.mocks }.flatten() as List<Mock>
}
}

View file

@ -0,0 +1,28 @@
package eu.ztsh.mockserver.server
import com.sun.net.httpserver.HttpsConfigurator
import com.sun.net.httpserver.HttpsParameters
import groovy.transform.CompileStatic
import eu.ztsh.mockserver.api.common.Https
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLParameters
@CompileStatic
class HttpsConfig extends HttpsConfigurator {
private final Https https
HttpsConfig(SSLContext sslContext, Https https) {
super(sslContext)
this.https = https
}
@Override
void configure(HttpsParameters httpsParameters) {
SSLContext sslContext = getSSLContext()
SSLParameters sslParameters = sslContext.defaultSSLParameters
sslParameters.needClientAuth = https.requireClientAuth
httpsParameters.needClientAuth = https.requireClientAuth
httpsParameters.SSLParameters = sslParameters
}
}

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import groovy.util.logging.Slf4j import groovy.util.logging.Slf4j

View file

@ -1,11 +1,12 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import groovy.transform.EqualsAndHashCode import groovy.transform.EqualsAndHashCode
import groovy.transform.PackageScope import groovy.transform.PackageScope
import groovy.util.logging.Slf4j import groovy.util.logging.Slf4j
import org.codehaus.groovy.control.CompilerConfiguration import org.codehaus.groovy.control.CompilerConfiguration
import org.codehaus.groovy.control.customizers.ImportCustomizer import org.codehaus.groovy.control.customizers.ImportCustomizer
import pl.touk.mockserver.api.common.Method import eu.ztsh.mockserver.api.common.Https
import eu.ztsh.mockserver.api.common.Method
import javax.xml.XMLConstants import javax.xml.XMLConstants
import javax.xml.transform.stream.StreamSource import javax.xml.transform.stream.StreamSource
@ -35,18 +36,31 @@ class Mock implements Comparable<Mock> {
private Validator validator private Validator validator
Map<String, String> imports = [:] Map<String, String> imports = [:]
boolean preserveHistory = true boolean preserveHistory = true
Https https
int maxUses = -1
int usesLeft
boolean cyclic
Mock(String name, String path, int port) { Mock(String name, String path, int port) {
if (!(name)) { if (!(name)) {
throw new RuntimeException("Mock name must be given") throw new RuntimeException("Mock name must be given")
} }
this.name = name this.name = name
this.path = path this.path = stripLeadingSlash(path)
this.port = port this.port = port
} }
private static String stripLeadingSlash(String path) {
if (path?.startsWith('/')) {
return path - '/'
} else {
return path
}
}
boolean match(Method method, MockRequest request) { boolean match(Method method, MockRequest request) {
return this.method == method && predicate(request) boolean usesCondition = hasLimitedUses() ? usesLeft > 0 : true
return usesCondition && (this.method == method || this.method == Method.ANY_METHOD) && predicate(request)
} }
MockResponse apply(MockRequest request) { MockResponse apply(MockRequest request) {
@ -138,6 +152,17 @@ class Mock implements Comparable<Mock> {
} }
} }
void setMaxUses(Integer maxUses) {
if (maxUses > 0) {
this.maxUses = maxUses
this.usesLeft = maxUses
}
}
void setCyclic(Boolean cyclic) {
this.cyclic = cyclic ?: false
}
@Override @Override
int compareTo(Mock o) { int compareTo(Mock o) {
return name.compareTo(o.name) return name.compareTo(o.name)
@ -148,11 +173,27 @@ class Mock implements Comparable<Mock> {
if (schema) { if (schema) {
try { try {
validator = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI) validator = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI)
.newSchema(new File(this.class.getResource("/$schema").path)) .newSchema(this.class.getResource("/$schema"))
.newValidator() .newValidator()
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException('mock request schema is invalid schema', e) throw new RuntimeException('mock request schema is invalid schema', e)
} }
} }
} }
boolean hasLimitedUses() {
return maxUses > 0
}
void decrementUses() {
usesLeft--
}
boolean shouldUsesBeReset() {
return hasLimitedUses() && usesLeft <= 0 && cyclic
}
void resetUses() {
setMaxUses(maxUses)
}
} }

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import groovy.transform.PackageScope import groovy.transform.PackageScope

View file

@ -1,9 +1,10 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import com.sun.net.httpserver.Headers import com.sun.net.httpserver.Headers
import groovy.json.JsonSlurper import groovy.json.JsonSlurper
import groovy.transform.PackageScope import groovy.transform.PackageScope
import groovy.util.slurpersupport.GPathResult import groovy.xml.XmlSlurper
import groovy.xml.slurpersupport.GPathResult
import groovy.xml.XmlUtil import groovy.xml.XmlUtil
@PackageScope @PackageScope

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import groovy.transform.PackageScope import groovy.transform.PackageScope

View file

@ -1,9 +1,9 @@
package pl.touk.mockserver.server package eu.ztsh.mockserver.server
import com.sun.net.httpserver.HttpExchange import com.sun.net.httpserver.HttpExchange
import pl.touk.mockserver.api.response.MockAdded import eu.ztsh.mockserver.api.response.MockAdded
import javax.xml.bind.JAXBContext import jakarta.xml.bind.JAXBContext
class Util { class Util {

View file

@ -1,58 +0,0 @@
package pl.touk.mockserver.server
import com.sun.net.httpserver.HttpHandler
import com.sun.net.httpserver.HttpServer
import groovy.transform.PackageScope
import groovy.util.logging.Slf4j
import java.util.concurrent.Executor
@Slf4j
@PackageScope
class HttpServerWraper {
private final HttpServer httpServer
final int port
private List<ContextExecutor> executors = []
HttpServerWraper(int port, Executor executor) {
this.port = port
InetSocketAddress addr = new InetSocketAddress(Inet4Address.getByName("0.0.0.0"), port)
httpServer = HttpServer.create(addr, 0)
httpServer.executor = executor
log.info("Http server starting on port $port...")
httpServer.start()
log.info('Http server is started')
}
void createContext(String context, HttpHandler handler) {
httpServer.createContext(context, handler)
}
void addMock(Mock mock) {
ContextExecutor executor = executors.find { it.path == mock.path }
if (executor) {
executor.addMock(mock)
} else {
executors << new ContextExecutor(this, mock)
}
log.info("Added mock ${mock.name}")
}
void stop() {
executors.each { httpServer.removeContext(it.contextPath) }
httpServer.stop(0)
}
List<MockEvent> removeMock(String name) {
return executors.collect { it.removeMock(name) }.flatten() as List<MockEvent>
}
List<MockEvent> peekMock(String name) {
return executors.collect { it.peekMock(name) }.flatten() as List<MockEvent>
}
List<Mock> getMocks() {
return executors.collect { it.mocks }.flatten() as List<Mock>
}
}

308
mvnw vendored Executable file
View file

@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd vendored Normal file
View file

@ -0,0 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

View file

@ -1,25 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>http-mock-server</artifactId>
<groupId>pl.touk.mockserver</groupId>
<version>2.5.1</version>
</parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>http-mock-server</artifactId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>mockserver-performance-tests</artifactId> <artifactId>mockserver-performance-tests</artifactId>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>pl.touk.mockserver</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>mockserver</artifactId> <artifactId>mockserver</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>pl.touk.mockserver</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>mockserver-client</artifactId> <artifactId>mockserver-client</artifactId>
<version>${project.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjdk.jmh</groupId> <groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId> <artifactId>jmh-core</artifactId>

View file

@ -1,4 +1,4 @@
package pl.touk.mockserver.client; package eu.ztsh.mockserver.client;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.CloseableHttpResponse;
@ -18,8 +18,8 @@ import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole; import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.infra.ThreadParams; import org.openjdk.jmh.infra.ThreadParams;
import pl.touk.mockserver.api.request.AddMock; import eu.ztsh.mockserver.api.request.AddMock;
import pl.touk.mockserver.server.HttpMockServer; import eu.ztsh.mockserver.server.HttpMockServer;
import java.io.IOException; import java.io.IOException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;

141
pom.xml
View file

@ -1,17 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<parent> <groupId>eu.ztsh.mockserver</groupId>
<groupId>pl.touk</groupId>
<artifactId>top</artifactId>
<version>1.0.7</version>
</parent>
<groupId>pl.touk.mockserver</groupId>
<artifactId>http-mock-server</artifactId> <artifactId>http-mock-server</artifactId>
<packaging>pom</packaging> <packaging>pom</packaging>
<version>2.5.1</version> <version>3.0.0-SNAPSHOT</version>
<modules> <modules>
<module>mockserver-client</module> <module>mockserver-client</module>
<module>mockserver</module> <module>mockserver</module>
@ -21,47 +17,74 @@
</modules> </modules>
<properties> <properties>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version> <groovy.version>4.0.12</groovy.version>
<groovy.version>2.4.11</groovy.version> <httpclient.version>4.5.13</httpclient.version>
<httpclient.version>4.3.5</httpclient.version> <spock-core.version>2.2-groovy-4.0</spock-core.version>
<spock-core.version>1.0-groovy-2.4</spock-core.version>
<commons-lang3.version>3.3.2</commons-lang3.version> <commons-lang3.version>3.3.2</commons-lang3.version>
<slf4j-api.version>1.7.7</slf4j-api.version> <slf4j-api.version>1.7.30</slf4j-api.version>
<logback-classic.version>1.0.13</logback-classic.version> <logback.version>1.3.12</logback.version>
<lombok.version>1.16.6</lombok.version> <lombok.version>1.18.26</lombok.version>
<jaxb.version>4.0.4</jaxb.version>
<autoVersionSubmodules>true</autoVersionSubmodules> <autoVersionSubmodules>true</autoVersionSubmodules>
<jmh.version>1.11.2</jmh.version> <jmh.version>1.37</jmh.version>
<maven-release-plugin.version>2.5.2</maven-release-plugin.version> <gmavenplus-plugin.version>3.0.2</gmavenplus-plugin.version>
<gmavenplus-plugin.version>1.4</gmavenplus-plugin.version> <jaxb2-maven-plugin.version>3.1.0</jaxb2-maven-plugin.version>
</properties> </properties>
<scm>
<connection>scm:git:git@github.com:TouK/http-mock-server.git</connection>
<developerConnection>scm:git:git@github.com:TouK/http-mock-server.git</developerConnection>
<tag>http-mock-server-2.5.1</tag>
</scm>
<dependencyManagement> <dependencyManagement>
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.codehaus.groovy</groupId> <groupId>eu.ztsh.mockserver</groupId>
<artifactId>groovy-all</artifactId> <artifactId>mockserver-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>mockserver</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>eu.ztsh.mockserver</groupId>
<artifactId>mockserver-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-bom</artifactId>
<version>${jaxb.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version> <version>${groovy.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-json</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency>
<groupId>org.apache.groovy</groupId>
<artifactId>groovy-xml</artifactId>
<version>${groovy.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId> <artifactId>httpclient</artifactId>
<version>${httpclient.version}</version> <version>${httpclient.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
<version>${spock-core.version}</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
@ -72,20 +95,27 @@
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>${slf4j-api.version}</version> <version>${slf4j-api.version}</version>
</dependency> </dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency> <dependency>
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>
<version>${logback-classic.version}</version> <version>${logback.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
<version>${lombok.version}</version> <version>${lombok.version}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>pl.touk.mockserver</groupId> <groupId>org.spockframework</groupId>
<artifactId>mockserver-api</artifactId> <artifactId>spock-core</artifactId>
<version>${project.version}</version> <version>${spock-core.version}</version>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.openjdk.jmh</groupId> <groupId>org.openjdk.jmh</groupId>
@ -103,15 +133,12 @@
</dependencyManagement> </dependencyManagement>
<build> <build>
<defaultGoal>clean install</defaultGoal> <pluginManagement>
<plugins> <plugins>
<plugin> <plugin>
<artifactId>maven-compiler-plugin</artifactId> <groupId>org.codehaus.mojo</groupId>
<version>${maven-compiler-plugin.version}</version> <artifactId>jaxb2-maven-plugin</artifactId>
<configuration> <version>${jaxb2-maven-plugin.version}</version>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.codehaus.gmavenplus</groupId> <groupId>org.codehaus.gmavenplus</groupId>
@ -121,35 +148,13 @@
<execution> <execution>
<goals> <goals>
<goal>compile</goal> <goal>compile</goal>
<goal>testCompile</goal> <goal>compileTests</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>${maven-release-plugin.version}</version>
<configuration>
<autoversionsubmodules>true</autoversionsubmodules>
</configuration>
</plugin>
</plugins> </plugins>
</pluginManagement>
</build> </build>
<contributors>
<contributor>
<name>Dominik Przybysz</name>
<email>alien11689@gmail.com</email>
</contributor>
</contributors>
<repositories>
<repository>
<id>touk</id>
<name>TouK Open source repository</name>
<url>https://philanthropist.touk.pl/nexus/content/repositories/releases</url>
</repository>
</repositories>
</project> </project>