diff --git a/.buildkite/buildkite.md b/.buildkite/buildkite.md
new file mode 100644
index 0000000000..00114e89f4
--- /dev/null
+++ b/.buildkite/buildkite.md
@@ -0,0 +1,39 @@
+BuildKite Notes
+===============
+
+to trigger build using REST API:
+
+ curl -u "jamesdbloom@gmail.com" https://api.buildkite.com/v2/organizations/mockserver/pipelines/mockserver/builds \
+ -X POST \
+ -F "commit=HEAD" \
+ -F "branch=master" \
+ -F "message=First build :rocket:"
+
+build step (as docker command):
+
+ # run as interactive container (for debugging)
+ docker run -v /var/lib/buildkite-agent/builds/$BUILDKITE_AGENT_NAME:/build -i -t jamesdbloom/mockserver:build /bin/bash
+
+ # check files in build folder (for debugging)
+ docker run -v /var/lib/buildkite-agent/builds/$BUILDKITE_AGENT_NAME/mockserver:/build -w /build/mockserver -a stdout -a stderr jamesdbloom/mockserver:build ls -lrt
+
+ # actually run the build
+ docker run -v /var/lib/buildkite-agent/builds/$BUILDKITE_AGENT_NAME/mockserver:/build -w /build/mockserver -a stdout -a stderr jamesdbloom/mockserver:build /build/mockserver/scripts/local_quick_build.sh
+
+determine killed reason:
+
+ dmesg | grep -E -i -B100 'killed process'
+
+connecting to AWS EC2 instance:
+
+ # check instance running
+ aws ec2 get-console-output --instance-id i-04bc2edc8b4187ca8 --region us-east-1
+
+ # ensure keypair has correct permissions
+ chmod 400 ~/Downloads/mockserver-buildkite.pem
+
+ # connect to EC2 linux instance using keypair and domain name
+ ssh -i ~/Downloads/mockserver-buildkite.pem ec2-user@ec2-34-204-42-237.compute-1.amazonaws.com
+
+ # connect to EC2 linux instance using keypair and ip address
+ ssh -i ~/Downloads/mockserver-buildkite.pem ec2-user@52.91.13.160
\ No newline at end of file
diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml
new file mode 100644
index 0000000000..40cdf8da6f
--- /dev/null
+++ b/.buildkite/pipeline.yml
@@ -0,0 +1,10 @@
+steps:
+ - label: "update docker image"
+ command: "docker pull jamesdbloom/mockserver:maven"
+
+ - wait
+
+ - label: "build"
+ command: "docker run -v /var/lib/buildkite-agent/builds/$BUILDKITE_AGENT_NAME/mockserver:/build -w /build/mockserver -a stdout -a stderr -e BUILDKITE_BRANCH=$BUILDKITE_BRANCH jamesdbloom/mockserver:maven /build/mockserver/scripts/buildkite_quick_build.sh"
+ artifact_paths:
+ - "**/*.log"
diff --git a/.drone.yml b/.drone.yml
deleted file mode 100644
index da1a1731dc..0000000000
--- a/.drone.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-image: jamesdbloom/mockserver:build
-
-script:
- - mvn install -q -Dmaven.test.skip=true -DskipTests -DskipITs -DskipRubyBuild=true
- - mvn install
-
-notify:
- email:
- recipients:
- - jamesdbloom@gmail.com
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000000..f431331b9e
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+
+[*.java]
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
diff --git a/.gitignore b/.gitignore
index a087a638c4..b132bee1f7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,13 +8,12 @@
# Packages #
############
-# it's better to unpack these files and commit the raw source
-# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
+!maven-wrapper.jar
*.rar
*.tar
*.zip
@@ -23,13 +22,15 @@ mods
# Logs and databases #
######################
*.log
-test.csv
*.sql
*.sqlite
+test.csv
+TODO.md
# Runtime artifacts #
#####################
-keystore.jks
+mockserver_keystore.jks
+mockserver.properties
# OS generated files #
######################
@@ -50,6 +51,8 @@ Thumbs.db
# Eclipse config files #
########################
.project
+.classpath
+.settings
# Maven build artifacts files #
###############################
@@ -59,6 +62,10 @@ release.properties
google
.extract
+# rbenv config #
+################
+.ruby-version
+
# Gradle build artifacts files #
################################
.gradle
@@ -71,3 +78,19 @@ node_modules
npm-debug.log
tmp
custom_tmp
+.bundle
+
+# vagrant #
+###########
+.vagrant
+
+# drone.io build testing #
+##########################
+drone.io
+
+# tomcat working directories #
+##############################
+mockserver-proxy-war/tomcat/
+mockserver-proxy-war/tomcat_proxy/
+mockserver-war/tomcat/
+mockserver-war/tomcat_mockserver/
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000000..c32394f140
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007-present the original author or authors.
+ *
+ * Licensed 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.
+ */
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ private static final String WRAPPER_VERSION = "0.5.5";
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
+ + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
+ String username = System.getenv("MVNW_USERNAME");
+ char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
+ Authenticator.setDefault(new Authenticator() {
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(username, password);
+ }
+ });
+ }
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar
new file mode 100644
index 0000000000..0d5e649888
Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000..fa87ad7ddf
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,2 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.1/apache-maven-3.6.1-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.5/maven-wrapper-0.5.5.jar
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 0fd7a0fd6a..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-language: java
-
-before_install:
- - "travis_retry mvn test-compile -T2C"
-
-script:
- - "./scripts/travis_build.sh"
-
-jdk:
- - openjdk6
-
-rvm:
- - "2.0.0"
-
-# whitelist
-branches:
- only:
- - master
-
-env:
- global:
- - secure: PyWvj9186/GCqQXC+rYK9YlEB8wyZf0tsT9b2jkGXmLK99DZ7pK0BAU6OxdgO9XrQvdjvCzqnvG2+CxzyiqsvRFMk1uNkZ3toxwIWvIVUNTi2NBSlILA2z/dsGV89rilno/ldqMB9c9Bp49GPrh3xSC64x4iFzfDkLPyROGq7Rc=
- - secure: JCKXr6PTQ+WZ9bHe3lCPT/ib42ZvPKf+MrE3CR3dPjG/bFwONxG23WCpO71zed7SrUdZWnk3UCZJeSIpeeQXC70mmxx2qgDnEWVkpsQCDvqLJCEVEBBJc6z3kKzW/twNlF7V6O92LUz64uqCh6lZrOT1VdSn5Ne8cM7PpgyhsMc=
-
-notifications:
- email:
- - jamesdbloom@gmail.com
- - nayyara.samuel@gmail.com
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000000..8dada3edaf
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed 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.
diff --git a/README.md b/README.md
index 3486ce8358..08717b3edd 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,13 @@
-MockServer
-==========
+MockServer [](https://twitter.com/intent/tweet?text=Easily%20mock%20any%20system%20you%20integrate%20with%20via%20HTTP%20or%20HTTPS%2C%20or%20analysis%20and%20debug%20systems%20via%20HTTP%20or%20HTTPS%20by%20simple%20transparent%20proxying%20that%20allows%20easy%20inspection%20or%20modification%20of%20in%20flight%20requests&url=http://mock-server.com&hashtags=mock,proxy,http,testing,debug,developers) [](https://buildkite.com/mockserver/mockserver)
+[](https://github.com/jamesdbloom/mockserver/blob/master/LICENSE.md)
+[](https://github.com/jamesdbloom/mockserver/stargazers)
+=====
-**Build Status:**
+# Documentation
-[](https://travis-ci.org/jamesdbloom/mockserver)
+For usage guide please see: [www.mock-server.com](http://www.mock-server.com/)
-**Backlog:**
-
-[](http://stillmaintained.com/jamesdbloom/mockserver) [](https://waffle.io/jamesdbloom/mockserver) [](https://waffle.io/jamesdbloom/mockserver) [](https://waffle.io/jamesdbloom/mockserver)
-
-
-### For usage guide please see: [www.mock-server.com](http://www.mock-server.com/)
-
+For chat room: [](https://gitter.im/jamesdbloom/mockserver?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
# Versions
@@ -19,43 +15,73 @@ MockServer
Maven Central contains the following MockServer artifacts:
-* [mockserver-maven-plugin](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-maven-plugin) - a set of maven plugins to start, stop and fork MockServer using maven
-* [mockserver-vertx](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-vertx) - a Vert.X module that mocks HTTP and HTTPS requests
-* [mockserver-netty](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-netty) - an NIO web server that mocks HTTP and HTTPS requests (using Netty)
-* [mockserver-netty:jar-with-dependencies](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-netty) - a fully stand alone NIO web server embedded with all dependencies that mocks HTTP and HTTPS requests (using Netty)
-* [mockserver-jetty](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-jetty) - a web server that mocks HTTP and HTTPS requests (using Embedded Jetty)
-* [mockserver-jetty:jar-with-dependencies](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-jetty) - a fully stand alone web server embedded with all dependencies that mocks HTTP and HTTPS requests (using Embedded Jetty)
-* [mockserver-war](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-war) - a deployable WAR for mocking HTTP and HTTP requests (that runs on any JEE web server)
-* [mockserver-proxy](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-proxy) - an HTTP / HTTPS proxy that allows the recording and querying of requests and response
+* [mockserver-netty](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-netty) - an HTTP(S) web server that mocks and records requests and responses
+* [mockserver-netty:jar-with-dependencies](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-netty) - mockserver-netty (as above) with all dependencies embedded
+* [mockserver-war](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-war) - a deployable WAR for mocking HTTP(S) responses (for any JEE web server)
+* [mockserver-proxy-war](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-proxy-war) - a deployable WAR that records requests and responses (for any JEE web server)
+* [mockserver-maven-plugin](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-maven-plugin) - a maven plugin to start, stop and fork MockServer using maven
* [mockserver-client-java](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-client-java) - a Java client to communicate with both the server and the proxy
-* [mockserver-client-javascript](https://maven-badges.herokuapp.com/maven-central/org.mock-server/mockserver-client-javascript) - a Java client to communicate with both the server and the proxy
-In addition MockServer SNAPSHOT artifacts can also be found on [Sonatype](https://oss.sonatype.org/index.html#nexus-search;quick~mockserver).
+In addition MockServer SNAPSHOT artifacts can also be found on [Sonatype](https://oss.sonatype.org/index.html#nexus-search;quick~org.mock-server).
### Node Module & Grunt Plugin
NPM Registry contains the following module:
-* [MockServer Grunt Plugin ](https://www.npmjs.org/package/mockserver-grunt) - a Node.js module and Grunt plugin to start and stop MockServer
+* [mockserver-node](https://www.npmjs.org/package/mockserver-node) - a Node.js module and Grunt plugin to start and stop MockServer
+ [](https://www.npmjs.org/package/mockserver-node)
+* [mockserver-client-node](https://www.npmjs.org/package/mockserver-client) - a Node.js client for both the MockServer and the proxy
+ [](https://www.npmjs.org/package/mockserver-client)
-### Docker Index
+### Docker Hub
-Docker Index contains the following artifacts:
+Docker Hub contains the following artifacts:
-* [MockServer Docker Container](https://registry.hub.docker.com/u/jamesdbloom/mockserver) - a Docker container containing the Netty MockServer and proxy
+* [MockServer Docker Container](https://hub.docker.com/r/jamesdbloom/mockserver/) - a Docker container containing the Netty MockServer and proxy
-### Vert.X Module Registry
+### Helm Chart
-Vert.X Module Registry contains the following artifacts:
-
-* [org.mock-server~mockserver-vertx~2.9](http://modulereg.vertx.io/) - a Vert.X module that mocks HTTP and HTTPS requests
+* [MockServer Helm Chart](helm/mockserver/README.md) - a Helm Chart that installs MockServer to a Kubernetes cluster, available versions:
+ * [5.6.1](http://www.mock-server.com/mockserver-5.6.1.tgz)
+ * [5.6.0](http://www.mock-server.com/mockserver-5.6.0.tgz)
+ * [5.5.4](http://www.mock-server.com/mockserver-5.5.4.tgz)
+ * [5.5.1](http://www.mock-server.com/mockserver-5.5.1.tgz)
+ * [5.5.0](http://www.mock-server.com/mockserver-5.5.0.tgz)
+ * [5.4.1](http://www.mock-server.com/mockserver-5.4.1.tgz)
+ * [5.3.0](http://www.mock-server.com/mockserver-5.3.0.tgz)
### MockServer Clients
* [mockserver-client-ruby ](https://rubygems.org/gems/mockserver-client) - Ruby client for both the MockServer and the proxy
* [mockserver-client-java](http://search.maven.org/#search%7Cga%7C1%7Cmockserver-client-java) - a Java client for both the MockServer and the proxy
-* [mockserver-client-javascript](https://rubygems.org/gems/mockserver-client-javascript) - a JavaScript client for both the MockServer and the proxy
-* [mockserver-client-node ](https://www.npmjs.org/package/mockserver-client) - a Node.js client for both the MockServer and the proxy
+* [mockserver-client-node](https://www.npmjs.org/package/mockserver-client) - a Node.js and [browser](https://rawgit.com/jamesdbloom/mockserver-client-node/mockserver-5.6.1/mockServerClient.js) client for both the MockServer and the proxy
+
+### Document
+Version | Date | Git & Docker Tag / Git Hash | Documentation | Java API | REST API
+:-------|:------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:--------------------------------------------------------------------- |:--------------------------------------------------------------------- |:---------------------------------------------------------------------------------
+5.6.1 | 26 Jul 2019 | [mockserver-5.6.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.6.1) / [aec1fb](https://github.com/jamesdbloom/mockserver/commit/aec1fbf1e826dc59fe4a19c3331ab6802ec4c3c7) | [Documentation](http://mock-server.com) | [Java API](http://mock-server.com/versions/5.6.0/apidocs/index.html) | [5.6.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.6.x)
+5.6.0 | 26 Apr 2019 | [mockserver-5.6.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.6.0) / [8f82dc](https://github.com/jamesdbloom/mockserver/commit/8f82dc4d37271c3cbfe0b3a1963e91ec3a4ef7a7) | [Documentation](http://mock-server.com) | [Java API](http://mock-server.com/versions/5.6.0/apidocs/index.html) | [5.6.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.6.x)
+5.5.4 | 22 Jun 2019 | [mockserver-5.5.4](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.5.4) / [4ffd31](https://github.com/jamesdbloom/mockserver/commit/4ffd3162a3250f18d343901b30c3ee71a75b1982) | [Documentation](https://5-5.mock-server.com) | [Java API](http://mock-server.com/versions/5.5.4/apidocs/index.html) | [5.5.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.5.x)
+5.5.1 | 28 Dec 2018 | [mockserver-5.5.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.5.1) / [11d8a9](https://github.com/jamesdbloom/mockserver/commit/11d8a96b0eaf07b7fffd29444203503b1cdca653) | [Documentation](https://5-5.mock-server.com) | [Java API](http://mock-server.com/versions/5.5.1/apidocs/index.html) | [5.5.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.5.x)
+5.5.0 | 15 Nov 2018 | [mockserver-5.5.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.5.0) / [06e6fd](https://github.com/jamesdbloom/mockserver/commit/06e6fdc4757f13fb5943fc281d5e55dc1c30919d) | [Documentation](https://5-5.mock-server.com) | [Java API](http://mock-server.com/versions/5.5.0/apidocs/index.html) | [5.5.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.5.x)
+5.4.1 | 20 Jun 2018 | [mockserver-5.4.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.4.1) / [7cd5de](https://github.com/jamesdbloom/mockserver/commit/7cd5defc7463e8773d011467147a8a0f7e7b4af8) | [Documentation](https://5-4.mock-server.com) | [Java API](http://mock-server.com/versions/5.4.1/apidocs/index.html) | [5.4.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.4.x)
+5.3.0 | 25 Dec 2017 | [mockserver-5.3.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.3.0) / [ad62bb](https://github.com/jamesdbloom/mockserver/commit/ad62bbc4fdc1470818ffab14630623dc591ead74) | [Documentation](https://5-3.mock-server.com) | [Java API](http://mock-server.com/versions/5.3.0/apidocs/index.html) | [5.2.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.2.x)
+5.2.3 | 17 Dec 2017 | [mockserver-5.2.3](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.2.3) / [e81c53](https://github.com/jamesdbloom/mockserver/commit/e81c53852b763f88b2399090ef414f074b3e3d81) | [Documentation](https://5-2.mock-server.com) | [Java API](http://mock-server.com/versions/5.2.3/apidocs/index.html) | [5.2.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.2.x)
+5.2.2 | 12 Dec 2017 | [mockserver-5.2.2](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.2.2) / [b47090](https://github.com/jamesdbloom/mockserver/commit/b47090b579d35c7136b84378402ff466db0bfb60) | [Documentation](https://5-2.mock-server.com) | [Java API](http://mock-server.com/versions/5.2.2/apidocs/index.html) | [5.2.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.2.x)
+5.2.1 | 11 Dec 2017 | [mockserver-5.2.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.2.1) / [834ec8](https://github.com/jamesdbloom/mockserver/commit/834ec8fcac335b10d09183cecfe6dae358a4080c) | [Documentation](https://5-2.mock-server.com) | [Java API](http://mock-server.com/versions/5.2.1/apidocs/index.html) | [5.2.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.2.x)
+5.2.0 | 10 Dec 2017 | [mockserver-5.2.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.2.0) / [ccb4d2](https://github.com/jamesdbloom/mockserver/commit/ccb4d241b55dcebc9f8abfb3722cadad143f3acf) | [Documentation](https://5-2.mock-server.com) | [Java API](http://mock-server.com/versions/5.2.0/apidocs/index.html) | [5.2.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.2.x)
+5.1.1 | 06 Dec 2017 | [mockserver-5.1.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.1.1) / [664afb](https://github.com/jamesdbloom/mockserver/commit/664afb2c539333ce89559fb3153e56bc48ba9cb5) | [Documentation](https://5-1.mock-server.com) | [Java API](http://mock-server.com/versions/5.1.1/apidocs/index.html) | [5.1.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.1.x)
+5.1.0 | 05 Dec 2017 | [mockserver-5.1.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.1.0) / [bbdda1](https://github.com/jamesdbloom/mockserver/commit/bbdda1898eb3f396d56f7268faa6c2a644449ae3) | [Documentation](https://5-1.mock-server.com) | [Java API](http://mock-server.com/versions/5.1.0/apidocs/index.html) | [5.1.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.1.x)
+5.0.1 | 05 Dec 2017 | [mockserver-5.0.1](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.0.1) / [975fb8](https://github.com/jamesdbloom/mockserver/commit/975fb8971da1cd32891201733a2bc6aa4080d7ae) | [Documentation](https://5-0.mock-server.com) | [Java API](http://mock-server.com/versions/5.0.1/apidocs/index.html) | [5.0.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.0.x)
+5.0.0 | 04 Dec 2017 | [mockserver-5.0.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-5.0.0) / [ed5d13](https://github.com/jamesdbloom/mockserver/commit/ed5d13e863a25e00ab404735e183df2ce4afe635) | [Documentation](https://5-0.mock-server.com) | [Java API](http://mock-server.com/versions/5.0.0/apidocs/index.html) | [5.0.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/5.0.x)
+4.1.0 | 30 Nov 2017 | [mockserver-4.1.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-4.1.0) / [4e37b2](https://github.com/jamesdbloom/mockserver/commit/4e37b27b9b1bc786d0b5f53d5f1a39dd457f5d34) | [Documentation](https://4-1.mock-server.com) | [Java API](http://mock-server.com/versions/4.1.0/apidocs/index.html) | [4.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/4.x.x)
+4.0.0 | 28 Nov 2017 | [mockserver-4.0.0](https://github.com/jamesdbloom/mockserver/tree/mockserver-4.0.0) / [8b2455](https://github.com/jamesdbloom/mockserver/commit/8b24553c6b7aabbe4ef5e99b37449330f5b908d7) | [Documentation](https://4-0.mock-server.com) | [Java API](http://mock-server.com/versions/4.0.0/apidocs/index.html) | [4.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server-openapi/4.x.x)
+3.12 | 16 Nov 2017 | [mockserver-3.12](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.12) / [d2a2b1](https://github.com/jamesdbloom/mockserver/commit/d2a2b1b7399e8405f2d19bc105c99a0a26327c61) | | [Java API](http://mock-server.com/versions/3.12/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
+3.11 | 10 Sep 2017 | [mockserver-3.11](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.11) / [fdcb11](https://github.com/jamesdbloom/mockserver/commit/fdcb1113ecd075ec7d9b1d065ed778dadebb1772) | | [Java API](http://mock-server.com/versions/3.11/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
+3.10.8 | 22 Jun 2017 | [mockserver-3.10.8](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.10.8) / [0e6e12](https://github.com/jamesdbloom/mockserver/commit/0e6e1227f5e3d5d9faa68434d3ed708edee7b9ee) | | [Java API](http://mock-server.com/versions/3.10.8/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
+3.10.7 | 02 May 2017 | [mockserver-3.10.7](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.10.7) / [99abb2](https://github.com/jamesdbloom/mockserver/commit/99abb290e31e9a65706e64a360f4ad318723f0ba) | | [Java API](http://mock-server.com/versions/3.10.7/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
+3.10.6 | 27 Apr 2017 | [mockserver-3.10.6](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.10.6) / [219897](https://github.com/jamesdbloom/mockserver/commit/2198972a3911efcf0fa116f4cdd0851ab31699c1) | | [Java API](http://mock-server.com/versions/3.10.6/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
+3.10.5 | 25 Apr 2017 | [mockserver-3.10.5](https://github.com/jamesdbloom/mockserver/tree/mockserver-3.10.5) / [a59e75](https://github.com/jamesdbloom/mockserver/commit/a59e750432f9d9431c1c6352953e1309d53178fc) | | [Java API](http://mock-server.com/versions/3.10.5/apidocs/index.html) | [3.x.x REST API](https://app.swaggerhub.com/apis/jamesdbloom/mock-server_api/3.x.x)
# Issues
@@ -63,7 +89,9 @@ If you have any problems, please [check the project issues](https://github.com/j
# Contributions
-Pull requests are, of course, very welcome! Please read our [contributing to the project](https://github.com/jamesdbloom/mockserver/wiki/Contributing-to-the-project) guide first. Then head over to the [open issues](https://github.com/jamesdbloom/mockserver/issues?state=open) to see what we need help with. Make sure you let us know if you intend to work on something. Also, check out the [milestones](https://github.com/jamesdbloom/mockserver/issues/milestones) to see what is planned for future releases.
+Pull requests are, of course, very welcome! Please read our [contributing to the project](https://github.com/jamesdbloom/mockserver/wiki/Contributing-to-the-project) guide first. Then head over to the [open issues](https://github.com/jamesdbloom/mockserver/issues?state=open) to see what we need help with. Make sure you let us know if you intend to work on something. Also, check out the [milestones](https://github.com/jamesdbloom/mockserver/milestones) to see what is planned for future releases.
# Maintainers
* [James D Bloom](http://blog.jamesdbloom.com)
+
+[](https://github.com/igrigorik/ga-beacon)
diff --git a/deploy.md b/deploy.md
deleted file mode 100644
index d8136b5f81..0000000000
--- a/deploy.md
+++ /dev/null
@@ -1,40 +0,0 @@
-Release Process
-===============
-
-# Setting Maven Central Deployments
-
-See:
-
-https://docs.sonatype.org/display/Repository/Sonatype+OSS+Maven+Repository+Usage+Guide
-https://oss.sonatype.org/index.html#nexus-search;quick~mockserver
-http://oss.sonatype.org/content/repositories/snapshots/org/mock-server/mockserver/
-https://docs.sonatype.org/display/Repository/How+To+Generate+PGP+Signatures+With+Maven
-
-Add to maven settings.xml:
-
-
- ...
-
-
- sonatype-nexus-snapshots
- your-jira-id
- your-jira-pwd
-
-
- sonatype-nexus-staging
- your-jira-id
- your-jira-pwd
-
-
- ...
-
-
-2]^J3ha9KX;QU8~
-
-Run commands:
-
- gpg --gen-key
- gpg --list-keys
- gpg --keyserver hkp://pool.sks-keyservers.net --send-keys A6BAB25C
- mvn clean deploy -> deploy SNAPSHOT
- mv .git/hooks .git/mooks && mvn release:clean && mvn release:prepare && mvn release:perform && mv .git/mooks .git/hooks
diff --git a/docker/Dockerfile b/docker/Dockerfile
index d9ea631835..63c677b061 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -6,21 +6,31 @@
#
# pull base image
-FROM dockerfile/java
+FROM openjdk:8-jdk-alpine
# maintainer details
MAINTAINER James Bloom "jamesdbloom@gmail.com"
+# obtain MockServer jar and script
+RUN apk add --update openssl ca-certificates bash wget
+ADD run_mockserver.sh /opt/mockserver/run_mockserver.sh
+ARG VERSION=5.6.1
+ARG REPOSITORY_URL=https://oss.sonatype.org/content/repositories/releases/org/mock-server/mockserver-netty/$VERSION/mockserver-netty-$VERSION-jar-with-dependencies.jar
+RUN echo "using mockserver version $REPOSITORY_URL"
+RUN wget --max-redirect=5 -O /opt/mockserver/mockserver-netty-jar-with-dependencies.jar $REPOSITORY_URL
+
# set working directory
-RUN mkdir -p /opt/mockserver
WORKDIR /opt/mockserver
-# download MockServer
-RUN (cd /opt/mockserver && wget -O mockserver-netty-3.8.2-jar-with-dependencies.jar http://search.maven.org/remotecontent?filepath=org/mock-server/mockserver-netty/3.8.2/mockserver-netty-3.8.2-jar-with-dependencies.jar)
-RUN (cd /opt/mockserver && wget https://raw.github.com/jamesdbloom/mockserver/master/docker/run_mockserver.sh && chmod +x /opt/mockserver/run_mockserver.sh)
-
# expose ports.
-EXPOSE 8080 9090
+EXPOSE 1080
+
+# don't run MockServer as root
+RUN addgroup -g 1000 mockserver && \
+ adduser -H -D -u 1000 -G mockserver mockserver
+RUN chown -R mockserver:mockserver /opt/mockserver
+USER mockserver
+
+ENTRYPOINT ["/opt/mockserver/run_mockserver.sh"]
-# define default command.
-CMD ["/opt/mockserver/run_mockserver.sh", "-serverPort", "8080", "-proxyPort", "9090"]
\ No newline at end of file
+CMD ["-logLevel", "INFO", "-serverPort", "1080"]
diff --git a/docker/README.md b/docker/README.md
index b342aba7da..be4eed3c65 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -3,7 +3,7 @@
### Dependencies
-* [dockerfile/java](http://dockerfile.github.io/#/java)
+* [java](https://registry.hub.docker.com/u/library/java/)
### Installation
@@ -13,7 +13,92 @@
### Usage
- docker run -d jamesdbloom/mockserver
+* **FIRST** ensure you have the latest version
+
+```bash
+docker pull jamesdbloom/mockserver
+```
+
+* **EITHER** run the container with no log output (i.e. in daemon mode)
+
+```bash
+docker run -d --name mockserver -p :1080 jamesdbloom/mockserver
+```
+
+* **OR** run the container with log output to console (i.e. in the foreground)
+
+```bash
+docker run --name mockserver -p :1080 jamesdbloom/mockserver
+```
+
+* **THEN** when your finished stop the container
+
+```bash
+docker stop mockserver && docker rm mockserver
+```
+
+* **DEBUG** any issues or change the command line options you can run the container with a shell prompt
+
+```bash
+docker run -i -t --name mockserver -p 1080:1080 jamesdbloom/mockserver /bin/bash
+```
+
+The default command executed when the container runs is:
+
+```bash
+/opt/mockserver/run_mockserver.sh -serverPort 1080 -logLevel INFO
+```
+
+This can be modified to change the command line options passed to the `/opt/mockserver/run_mockserver.sh` script, which supports the following options:
+
+```
+run_mockserver.sh -serverPort [-proxyRemotePort ] [-proxyRemoteHost ] [-logLevel ]
+
+ valid options are:
+
+ -serverPort The HTTP, HTTPS, SOCKS and HTTP CONNECT
+ port(s) for both mocking and proxying
+ requests. Port unification is used to
+ support all protocols for proxying and
+ mocking on the same port(s). Supports
+ comma separated list for binding to
+ multiple ports.
+
+ -proxyRemotePort Optionally enables port forwarding mode.
+ When specified all requests received will
+ be forwarded to the specified port, unless
+ they match an expectation.
+
+ -proxyRemoteHost Specified the host to forward all proxy
+ requests to when port forwarding mode has
+ been enabled using the proxyRemotePort
+ option. This setting is ignored unless
+ proxyRemotePort has been specified. If no
+ value is provided for proxyRemoteHost when
+ proxyRemotePort has been specified,
+ proxyRemoteHost will default to \"localhost\".
+
+ -logLevel Optionally specify log level using SLF4J levels:
+ TRACE, DEBUG, INFO, WARN, ERROR, OFF or Java
+ Logger levels: FINEST, FINE, INFO, WARNING,
+ SEVERE or OFF. If not specified default is INFO
+
+i.e. run_mockserver.sh -logLevel INFO -serverPort 1080,1081 -proxyRemotePort 80 -proxyRemoteHost www.mock-server.com
+```
+
+The `logLevel` can also be modified by passing environment variable through docker-compose.yml file. The following is a sample docker-compose.yml file for changing logLevel:
+
+ ```
+ mockServer:
+ image: jamesdbloom/mockserver:latest
+ ports:
+ - 1080:1080
+ environment:
+ - LOG_LEVEL=WARN
+ ```
+
+If no `LOG_LEVEL` value is passed in docker-compose, the default value will be `INFO` unless you run the container with other logLevel value on command line.
+
### What is MockServer
@@ -21,14 +106,13 @@ MockServer is for mocking of any system you integrate with via HTTP or HTTPS (i.
MockServer supports:
-* mocking of any HTTP / HTTPS response when any request is matched ([learn more](http://www.mock-server.com/#mocking))
-* recording requests and responses to analyse how a system behaves ([learn more](http://www.mock-server.com/#proxying))
-* verifying which requests and responses have been sent as part of a test ([learn more](http://www.mock-server.com/#proxying))
+* mocking of any HTTP / HTTPS response when any request is matched ([learn more](http://www.mock-server.com/#what-is-mockserver))
+* recording requests and responses to analyse how a system behaves ([learn more](http://www.mock-server.com/#what-is-mockserver))
+* verifying which requests and responses have been sent as part of a test ([learn more](http://www.mock-server.com/#what-is-mockserver))
-This docker container will run an instance of the MockServer on the following ports:
+This docker container will run an instance of the MockServer on the following port:
-* serverPort **8080**
-* proxyPort **9090**
+* serverPort **1080**
For information on how to use the MockServer please see http://www.mock-server.com
@@ -42,4 +126,3 @@ Pull requests are, of course, very welcome! Please read our [contributing to the
### Maintainers
* [James D Bloom](http://blog.jamesdbloom.com)
-* [Samira Bloom](https://github.com/samirabloom)
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
new file mode 100644
index 0000000000..7da1259216
--- /dev/null
+++ b/docker/docker-compose.yml
@@ -0,0 +1,6 @@
+ mockServer:
+ image: jamesdbloom/mockserver:mockserver-5.6.1
+ ports:
+ - 1080:1080
+ environment:
+ - LOG_LEVEL=INFO
diff --git a/docker/run_mockserver.sh b/docker/run_mockserver.sh
index d253bcb3f2..00298fa46c 100755
--- a/docker/run_mockserver.sh
+++ b/docker/run_mockserver.sh
@@ -1,50 +1,160 @@
#!/usr/bin/env bash
+set -e
+#set -o xtrace
+
+function showUsage {
+ echo >&2 " run_mockserver.sh -serverPort [-proxyRemotePort ] [-proxyRemoteHost ] [-logLevel ] [-jvmOptions ]"
+ echo >&2 " "
+ echo >&2 " valid options are: "
+ echo >&2 " -serverPort The HTTP, HTTPS, SOCKS and HTTP CONNECT"
+ echo >&2 " port(s) for both mocking and proxying"
+ echo >&2 " requests. Port unification is used to"
+ echo >&2 " support all protocols for proxying and"
+ echo >&2 " mocking on the same port(s). Supports"
+ echo >&2 " comma separated list for binding to"
+ echo >&2 " multiple ports."
+ echo >&2 " "
+ echo >&2 " -proxyRemotePort Optionally enables port forwarding mode."
+ echo >&2 " When specified all requests received will"
+ echo >&2 " be forwarded to the specified port, unless"
+ echo >&2 " they match an expectation."
+ echo >&2 " "
+ echo >&2 " -proxyRemoteHost Specified the host to forward all proxy"
+ echo >&2 " requests to when port forwarding mode has"
+ echo >&2 " been enabled using the proxyRemotePort"
+ echo >&2 " option. This setting is ignored unless"
+ echo >&2 " proxyRemotePort has been specified. If no"
+ echo >&2 " value is provided for proxyRemoteHost when"
+ echo >&2 " proxyRemotePort has been specified,"
+ echo >&2 " proxyRemoteHost will default to \"localhost\"."
+ echo >&2 " "
+ echo >&2 " -logLevel Optionally specify log level using SLF4J levels:"
+ echo >&2 " TRACE, DEBUG, INFO, WARN, ERROR, OFF or Java"
+ echo >&2 " Logger levels: FINEST, FINE, INFO, WARNING,"
+ echo >&2 " SEVERE or OFF. If not specified default is INFO"
+ echo >&2 " "
+ echo >&2 " -jvmOptions Specified generic JVM options or system properties."
+ echo >&2 " "
+ echo >&2 " i.e. /opt/mockserver/run_mockserver.sh -serverPort 1080,1081 -proxyRemotePort 80 -proxyRemoteHost www.mock-server.com -logLevel DEBUG -jvmOptions \"-Dmockserver.enableCORSForAllResponses=true -Dmockserver.sslSubjectAlternativeNameDomains='org.mock-server.com,mock-server.com'\""
+ echo >&2 " "
+ exit 1
+}
+
+function runCommand {
+ echo
+ echo "$1"
+ echo
+ eval $1
+}
+
+function prep_term {
+ unset term_child_pid
+ unset term_kill_needed
+ trap 'handle_term' TERM INT
+}
+
+function handle_term {
+ if [ "${term_child_pid}" ]; then
+ kill -TERM "${term_child_pid}" 2>/dev/null
+ else
+ term_kill_needed="yes"
+ fi
+}
+
+function wait_term {
+ term_child_pid=$!
+ if [ "${term_kill_needed}" ]; then
+ kill -TERM "${term_child_pid}" 2>/dev/null
+ fi
+ wait ${term_child_pid}
+ trap - TERM INT
+ wait ${term_child_pid}
+}
+
while [ $# -gt 0 ]
do
case "$1" in
-serverPort) serverPort="$2"; shift;;
- -proxyPort) proxyPort="$2"; shift;;
- -*)
- notset="true"
- break;;
-*)
- break;; # terminate while loop
+ -proxyRemotePort) proxyRemotePort="$2"; shift;;
+ -proxyRemoteHost) proxyRemoteHost="$2"; shift;;
+ -logLevel) logLevel="$2"; shift;;
+ -jvmOptions) jvmOptions="$2"; shift;;
+ -*) notset="true"; break;;
+ *) break;;
esac
shift
done
-if [ -z $serverPort ] && [ -z $proxyPort ]
+COMMAND_LINE_OPTS=""
+
+# serverPort
+if [ -z "$SERVER_PORT" ]
then
- echo >&2 " java -jar [-serverPort ] [-proxyPort ]"
- echo >&2 ""
- echo >&2 " valid options are:"
- echo >&2 " -serverPort specifies the HTTP and HTTPS port for the "
- echo >&2 " MockServer port unification is used to "
- echo >&2 " support HTTP and HTTPS on the same port "
- echo >&2 " "
- echo >&2 " -proxyPort specifies the HTTP, HTTPS, SOCKS and HTTP "
- echo >&2 " CONNECT port for proxy, port unification "
- echo >&2 " supports for all protocols on the same port ";
- exit 1
+ if [ -n "$serverPort" ]
+ then
+ SERVER_PORT="$serverPort"
+ fi
+fi
+if [ -n "$SERVER_PORT" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -serverPort $SERVER_PORT"
+else
+ echo
+ echo " Error: At least 'serverPort' must be provided"
+ echo
+ showUsage
fi
-COMMAND_LINE_OPTS=""
+# proxyRemotePort
+if [ -z "$PROXY_REMOTE_PORT" ]
+then
+ if [ -n "$proxyRemotePort" ]
+ then
+ PROXY_REMOTE_PORT="$proxyRemotePort"
+ fi
+fi
+if [ -n "$PROXY_REMOTE_PORT" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -proxyRemotePort $PROXY_REMOTE_PORT"
+fi
-if [ -n "$serverPort" ]
+# proxyRemoteHost
+if [ -z "$PROXY_REMOTE_HOST" ]
then
- COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -serverPort $serverPort"
+ if [ -n "$proxyRemoteHost" ]
+ then
+ PROXY_REMOTE_HOST="$proxyRemoteHost"
+ fi
fi
-if [ -n "$proxyPort" ]
+if [ -n "$PROXY_REMOTE_HOST" ]
then
- COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -proxyPort $proxyPort"
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -proxyRemoteHost $PROXY_REMOTE_HOST"
fi
-if [ -z "$MOCKSERVER_HOME" ]
+# logLevel
+if [ -z "$LOG_LEVEL" ]
+then
+ if [ -n "$logLevel" ]
+ then
+ LOG_LEVEL="$logLevel"
+ else
+ LOG_LEVEL="INFO"
+ fi
+fi
+if [ -n "$LOG_LEVEL" ]
then
- MOCKSERVER_HOME="/opt/mockserver"
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -logLevel $LOG_LEVEL"
fi
+if [ -z "$JVM_OPTIONS" ]
+then
+ if [ -n "$jvmOptions" ]
+ then
+ JVM_OPTIONS="$jvmOptions"
+ fi
+fi
-echo "java -Dfile.encoding=UTF-8 -Dmockserver.logLevel=WARN -jar $MOCKSERVER_HOME/mockserver-netty-3.8.2-jar-with-dependencies.jar $COMMAND_LINE_OPTS"
-java -Dfile.encoding=UTF-8 -Dmockserver.logLevel=WARN -jar $MOCKSERVER_HOME/mockserver-netty-3.8.2-jar-with-dependencies.jar $COMMAND_LINE_OPTS
+prep_term
+runCommand "java ${JVM_OPTIONS} -Dfile.encoding=UTF-8 -jar /opt/mockserver/mockserver-netty-jar-with-dependencies.jar ${COMMAND_LINE_OPTS} &"
+wait_term
diff --git a/docker/snapshot/Dockerfile b/docker/snapshot/Dockerfile
new file mode 100644
index 0000000000..e51c7cd30e
--- /dev/null
+++ b/docker/snapshot/Dockerfile
@@ -0,0 +1,26 @@
+#
+# MockServer Dockerfile
+#
+# https://github.com/jamesdbloom/mockserver
+# http://www.mock-server.com
+#
+
+# pull base image
+FROM openjdk:8u151-jre-alpine3.7
+
+# maintainer details
+MAINTAINER James Bloom "jamesdbloom@gmail.com"
+
+# obtain MockServer jar and script
+RUN apk add --update openssl ca-certificates bash wget
+ADD run_mockserver.sh /opt/mockserver/run_mockserver.sh
+RUN wget --max-redirect=1 -O /opt/mockserver/mockserver-netty-jar-with-dependencies.jar "https://oss.sonatype.org/service/local/artifact/maven/redirect?r=snapshots&g=org.mock-server&a=mockserver-netty&c=jar-with-dependencies&e=jar&v=LATEST"
+
+# set working directory
+WORKDIR /opt/mockserver
+
+# expose ports.
+EXPOSE 1080
+
+# define default command.
+CMD ["/opt/mockserver/run_mockserver.sh", "-logLevel", "INFO", "-serverPort", "1080"]
diff --git a/docker/snapshot/run_mockserver.sh b/docker/snapshot/run_mockserver.sh
new file mode 100755
index 0000000000..00298fa46c
--- /dev/null
+++ b/docker/snapshot/run_mockserver.sh
@@ -0,0 +1,160 @@
+#!/usr/bin/env bash
+
+set -e
+#set -o xtrace
+
+function showUsage {
+ echo >&2 " run_mockserver.sh -serverPort [-proxyRemotePort ] [-proxyRemoteHost ] [-logLevel ] [-jvmOptions ]"
+ echo >&2 " "
+ echo >&2 " valid options are: "
+ echo >&2 " -serverPort The HTTP, HTTPS, SOCKS and HTTP CONNECT"
+ echo >&2 " port(s) for both mocking and proxying"
+ echo >&2 " requests. Port unification is used to"
+ echo >&2 " support all protocols for proxying and"
+ echo >&2 " mocking on the same port(s). Supports"
+ echo >&2 " comma separated list for binding to"
+ echo >&2 " multiple ports."
+ echo >&2 " "
+ echo >&2 " -proxyRemotePort Optionally enables port forwarding mode."
+ echo >&2 " When specified all requests received will"
+ echo >&2 " be forwarded to the specified port, unless"
+ echo >&2 " they match an expectation."
+ echo >&2 " "
+ echo >&2 " -proxyRemoteHost Specified the host to forward all proxy"
+ echo >&2 " requests to when port forwarding mode has"
+ echo >&2 " been enabled using the proxyRemotePort"
+ echo >&2 " option. This setting is ignored unless"
+ echo >&2 " proxyRemotePort has been specified. If no"
+ echo >&2 " value is provided for proxyRemoteHost when"
+ echo >&2 " proxyRemotePort has been specified,"
+ echo >&2 " proxyRemoteHost will default to \"localhost\"."
+ echo >&2 " "
+ echo >&2 " -logLevel Optionally specify log level using SLF4J levels:"
+ echo >&2 " TRACE, DEBUG, INFO, WARN, ERROR, OFF or Java"
+ echo >&2 " Logger levels: FINEST, FINE, INFO, WARNING,"
+ echo >&2 " SEVERE or OFF. If not specified default is INFO"
+ echo >&2 " "
+ echo >&2 " -jvmOptions Specified generic JVM options or system properties."
+ echo >&2 " "
+ echo >&2 " i.e. /opt/mockserver/run_mockserver.sh -serverPort 1080,1081 -proxyRemotePort 80 -proxyRemoteHost www.mock-server.com -logLevel DEBUG -jvmOptions \"-Dmockserver.enableCORSForAllResponses=true -Dmockserver.sslSubjectAlternativeNameDomains='org.mock-server.com,mock-server.com'\""
+ echo >&2 " "
+ exit 1
+}
+
+function runCommand {
+ echo
+ echo "$1"
+ echo
+ eval $1
+}
+
+function prep_term {
+ unset term_child_pid
+ unset term_kill_needed
+ trap 'handle_term' TERM INT
+}
+
+function handle_term {
+ if [ "${term_child_pid}" ]; then
+ kill -TERM "${term_child_pid}" 2>/dev/null
+ else
+ term_kill_needed="yes"
+ fi
+}
+
+function wait_term {
+ term_child_pid=$!
+ if [ "${term_kill_needed}" ]; then
+ kill -TERM "${term_child_pid}" 2>/dev/null
+ fi
+ wait ${term_child_pid}
+ trap - TERM INT
+ wait ${term_child_pid}
+}
+
+while [ $# -gt 0 ]
+do
+ case "$1" in
+ -serverPort) serverPort="$2"; shift;;
+ -proxyRemotePort) proxyRemotePort="$2"; shift;;
+ -proxyRemoteHost) proxyRemoteHost="$2"; shift;;
+ -logLevel) logLevel="$2"; shift;;
+ -jvmOptions) jvmOptions="$2"; shift;;
+ -*) notset="true"; break;;
+ *) break;;
+ esac
+ shift
+done
+
+COMMAND_LINE_OPTS=""
+
+# serverPort
+if [ -z "$SERVER_PORT" ]
+then
+ if [ -n "$serverPort" ]
+ then
+ SERVER_PORT="$serverPort"
+ fi
+fi
+if [ -n "$SERVER_PORT" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -serverPort $SERVER_PORT"
+else
+ echo
+ echo " Error: At least 'serverPort' must be provided"
+ echo
+ showUsage
+fi
+
+# proxyRemotePort
+if [ -z "$PROXY_REMOTE_PORT" ]
+then
+ if [ -n "$proxyRemotePort" ]
+ then
+ PROXY_REMOTE_PORT="$proxyRemotePort"
+ fi
+fi
+if [ -n "$PROXY_REMOTE_PORT" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -proxyRemotePort $PROXY_REMOTE_PORT"
+fi
+
+# proxyRemoteHost
+if [ -z "$PROXY_REMOTE_HOST" ]
+then
+ if [ -n "$proxyRemoteHost" ]
+ then
+ PROXY_REMOTE_HOST="$proxyRemoteHost"
+ fi
+fi
+if [ -n "$PROXY_REMOTE_HOST" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -proxyRemoteHost $PROXY_REMOTE_HOST"
+fi
+
+# logLevel
+if [ -z "$LOG_LEVEL" ]
+then
+ if [ -n "$logLevel" ]
+ then
+ LOG_LEVEL="$logLevel"
+ else
+ LOG_LEVEL="INFO"
+ fi
+fi
+if [ -n "$LOG_LEVEL" ]
+then
+ COMMAND_LINE_OPTS="$COMMAND_LINE_OPTS -logLevel $LOG_LEVEL"
+fi
+
+if [ -z "$JVM_OPTIONS" ]
+then
+ if [ -n "$jvmOptions" ]
+ then
+ JVM_OPTIONS="$jvmOptions"
+ fi
+fi
+
+prep_term
+runCommand "java ${JVM_OPTIONS} -Dfile.encoding=UTF-8 -jar /opt/mockserver/mockserver-netty-jar-with-dependencies.jar ${COMMAND_LINE_OPTS} &"
+wait_term
diff --git a/docker_build/Dockerfile b/docker_build/Dockerfile
deleted file mode 100644
index 3b67fa68c4..0000000000
--- a/docker_build/Dockerfile
+++ /dev/null
@@ -1,28 +0,0 @@
-#
-# MockServer Dockerfile
-#
-# https://github.com/jamesdbloom/mockserver
-# http://www.mock-server.com
-#
-
-# pull base image.
-FROM dockerfile/ubuntu
-
-# maintainer details
-MAINTAINER James Bloom "jamesdbloom@gmail.com"
-
-# install Java
-RUN \
- export DEBIAN_FRONTEND=noninteractive && \
- sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
- apt-get update && \
- apt-get -y upgrade && \
- apt-get install -y build-essential && \
- apt-get install -y software-properties-common && \
- add-apt-repository -y ppa:webupd8team/java && \
- apt-get update && \
- apt-get install -y curl git htop man unzip vim wget pkg-config && \
- echo debconf shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
- echo debconf shared/accepted-oracle-license-v1-1 seen true | debconf-set-selections && \
- apt-get install -y oracle-java6-installer maven && \
- \curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1.2
diff --git a/docker_build/Vagrantfile b/docker_build/Vagrantfile
deleted file mode 100644
index 833ece89ef..0000000000
--- a/docker_build/Vagrantfile
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- mode: ruby -*-
-# vi: set ft=ruby :
-
-# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
-VAGRANTFILE_API_VERSION = "2"
-
-Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
- config.vm.box = "box-cutter/ubuntu1404"
-end
diff --git a/docker_build/grunt/Dockerfile b/docker_build/grunt/Dockerfile
new file mode 100644
index 0000000000..086f7e8ebe
--- /dev/null
+++ b/docker_build/grunt/Dockerfile
@@ -0,0 +1,32 @@
+#
+# MockServer Build Dockerfile
+#
+# https://github.com/jamesdbloom/mockserver
+# http://www.mock-server.com
+#
+
+# pull base image.
+FROM debian:jessie
+
+# update packages
+RUN export DEBIAN_FRONTEND=noninteractive
+RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list
+RUN apt-get update
+RUN apt-get -y upgrade
+
+# install basic build tools
+RUN apt-get install -y build-essential
+RUN apt-get install -y software-properties-common
+RUN apt-get install -y curl git htop man unzip vim wget pkg-config python2.7 openjdk-7-jre
+
+# install xvfb & chromium
+RUN apt-get install -y xvfb chromium
+ADD chrome-xvfb /usr/bin/chrome
+ENV CHROME_BIN=/usr/bin/chrome
+
+# install node
+RUN curl -sL https://deb.nodesource.com/setup_7.x | bash -
+RUN apt-get install -y nodejs
+
+# install grunt
+RUN npm install -g grunt-cli
diff --git a/docker_build/grunt/chrome-xvfb b/docker_build/grunt/chrome-xvfb
new file mode 100755
index 0000000000..15f2780d43
--- /dev/null
+++ b/docker_build/grunt/chrome-xvfb
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+_kill_procs() {
+ kill -TERM $chromium
+ wait $chromium
+ kill -TERM $xvfb
+}
+
+# Setup a trap to catch SIGTERM and relay it to child processes
+trap _kill_procs SIGTERM
+
+XVFB_WHD=${XVFB_WHD:-1280x720x16}
+
+# Start Xvfb
+Xvfb :99 -ac -screen 0 $XVFB_WHD -nolisten tcp &
+xvfb=$!
+
+export DISPLAY=:99
+
+chromium --no-sandbox $@ &
+chromium=$!
+
+wait $chromium
+wait $xvfb
\ No newline at end of file
diff --git a/docker_build/maven/Dockerfile b/docker_build/maven/Dockerfile
new file mode 100644
index 0000000000..38e36c84f9
--- /dev/null
+++ b/docker_build/maven/Dockerfile
@@ -0,0 +1,34 @@
+#
+# MockServer Build Dockerfile
+#
+# https://github.com/jamesdbloom/mockserver
+# http://www.mock-server.com
+#
+
+# pull base image.
+FROM ubuntu:trusty
+
+# maintainer details
+MAINTAINER James Bloom "jamesdbloom@gmail.com"
+
+# update packages
+RUN export DEBIAN_FRONTEND=noninteractive
+RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list
+RUN apt-get update
+RUN apt-get -y upgrade
+
+# install basic build tools
+RUN apt-get install -y build-essential
+RUN apt-get install -y software-properties-common
+RUN apt-get install -y curl git htop man unzip vim wget pkg-config
+
+# install java
+RUN add-apt-repository -y ppa:openjdk-r/ppa
+RUN apt-get update
+RUN apt-get install -y openjdk-8-jdk maven
+COPY settings.xml /etc/maven/settings.xml
+RUN rm -f /etc/alternatives/java && ln -s /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java /etc/alternatives/java
+
+# pre-fetch maven dependencies
+RUN git clone https://github.com/jamesdbloom/mockserver.git
+RUN cd mockserver && ./mvnw -s /etc/maven/settings.xml dependency:go-offline && cd .. && rm -rf mockserver
diff --git a/docker_build/maven/settings.xml b/docker_build/maven/settings.xml
new file mode 100644
index 0000000000..f27e90c7fa
--- /dev/null
+++ b/docker_build/maven/settings.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ sonatype
+
+ true
+
+
+
+ sonatype-nexus-snapshots
+ sonatype-nexus-snapshots
+ https://oss.sonatype.org/content/repositories/snapshots
+ default
+
+ true
+
+
+ true
+
+
+
+
+
+ sonatype-nexus-snapshots
+ sonatype-nexus-snapshots
+ https://oss.sonatype.org/content/repositories/snapshots
+ default
+
+ true
+
+
+ true
+
+
+
+
+
+
diff --git a/docker_build/performance/Dockerfile b/docker_build/performance/Dockerfile
new file mode 100644
index 0000000000..ed61913e7e
--- /dev/null
+++ b/docker_build/performance/Dockerfile
@@ -0,0 +1,34 @@
+#
+# MockServer Performance Dockerfile
+#
+# https://github.com/jamesdbloom/mockserver
+# http://www.mock-server.com
+#
+
+# pull base image.
+FROM ubuntu:trusty
+
+# maintainer details
+MAINTAINER James Bloom "jamesdbloom@gmail.com"
+
+# update packages
+RUN export DEBIAN_FRONTEND=noninteractive
+RUN sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list
+RUN apt-get update
+RUN apt-get -y upgrade
+
+# install basic build tools
+RUN apt-get install -y build-essential
+RUN apt-get install -y software-properties-common
+RUN apt-get install -y apache2-utils libssl-dev curl git htop man unzip vim wget pkg-config
+
+# install locustio
+RUN apt-get -y install python-setuptools python-dev build-essential
+RUN easy_install pip
+RUN pip install locustio
+
+# install wrk
+RUN git clone https://github.com/giltene/wrk2.git
+WORKDIR wrk2
+RUN make
+RUN cp wrk /usr/local/bin
diff --git a/git-hooks/pre-commit b/git-hooks/pre-commit
deleted file mode 100644
index e5db19b64f..0000000000
--- a/git-hooks/pre-commit
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env bash
-
-./build.sh
diff --git a/git-hooks/pre-push b/git-hooks/pre-push
deleted file mode 100644
index 20d602bdd3..0000000000
--- a/git-hooks/pre-push
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/usr/bin/env bash
-
diff --git a/git-hooks/setup-git-hooks b/git-hooks/setup-git-hooks
deleted file mode 100755
index 781dc65820..0000000000
--- a/git-hooks/setup-git-hooks
+++ /dev/null
@@ -1,59 +0,0 @@
-#!/usr/bin/env bash
-
-#
-# Setup script which installs git hooks under .git/hooks of the Git repository
-# in which this script is run.
-#
-# Exit:
-# 0 - on success
-# 1 - on error
-
-# git > 1.8.2
-GIT_REQUIRED_VERSION='1.8.2'
-git_version=$(git --version | awk '{print $3}' | awk -F'.' '{print $1"."$2"."$3}')
-if [[ ${git_version} < ${GIT_REQUIRED_VERSION} ]]; then
- echo "[ERROR] $(which git) is older than ${GIT_REQUIRED_VERSION}"
- echo "[ERROR] Please carry out the following steps:"
- echo ""
- echo "[ERROR] 1. Upgrade git to +${GIT_REQUIRED_VERSION} http://git-scm.com/downloads"
- echo '[ERROR] 2. Once installed add the following to your ~/.bash_profile'
- echo '[ERROR] export PATH=/usr/local/git/bin:$PATH'
- echo '[ERROR] 3. Within IntelliJ preferences change "Path to Git executable"'
- echo '[ERROR] to be /usr/local/git/bin/git'
- exit 1
-else
- echo "# found git ${git_version} > ${GIT_REQUIRED_VERSION}"
-fi
-
-git_top_path=$(git rev-parse --show-toplevel)
-source_git_hook_path="${git_top_path}/git-hooks"
-target_git_hook_path="${git_top_path}/.git/hooks"
-
-# Initial validation
-if [ ! -d "${git_top_path}" ]; then
- echo "[ERROR] this command must be run from the top level of checkout Git repository"
- exit 1
-fi
-if [ ! -e "${source_git_hook_path}" ]; then
- echo "[ERROR] cannot find ${source_git_hook_path}"
- exit 1
-fi
-
-# Set up git hooks
-echo "# setting up git hook for ${git_top_path}"
-[ -f "${target_git_hook_path}" ] && mkdir -p "${target_git_hook_path}"
-rm -f "${target_git_hook_path}/pre-commit"
-ln -s "${source_git_hook_path}/pre-commit" "${target_git_hook_path}/pre-commit"
-rm -f "${target_git_hook_path}/pre-push"
-ln -s "${source_git_hook_path}/pre-push" "${target_git_hook_path}/pre-push"
-
-# Sanity-check the results
-if [ ! -h "${target_git_hook_path}/pre-commit" ]; then
- echo "[ERROR] failed to install git pre-commit"
- exit 1
-fi
-if [ ! -h "${target_git_hook_path}/pre-push" ]; then
- echo "[ERROR] failed to install git pre-push"
- exit 1
-fi
-echo '# setup git-hooks successful'
diff --git a/helm/mockserver/.helmignore b/helm/mockserver/.helmignore
new file mode 100644
index 0000000000..11d183e235
--- /dev/null
+++ b/helm/mockserver/.helmignore
@@ -0,0 +1,4 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
diff --git a/helm/mockserver/Chart.yaml b/helm/mockserver/Chart.yaml
new file mode 100644
index 0000000000..6b8af11f8f
--- /dev/null
+++ b/helm/mockserver/Chart.yaml
@@ -0,0 +1,24 @@
+name: mockserver
+version: "5.6.1"
+description: Chart to deploy MockServer to Kubernetes. MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
+keywords:
+ - mocking
+ - mock-server
+ - http-mock
+ - http
+ - test
+ - test-server
+ - proxy
+ - http-proxy
+ - socks-proxy
+ - https-proxy
+home: "http://mock-server.com"
+sources:
+ - "https://github.com/jamesdbloom/mockserver"
+ - "https://hub.docker.com/r/jamesdbloom/mockserver"
+maintainers:
+ - name: James D Bloom
+ email: jamesdbloom+mockserver@gmail.com
+engine: gotpl
+icon: http://mock-server.com/apple-touch-icon.png
+appVersion: "1.0"
diff --git a/helm/mockserver/README.md b/helm/mockserver/README.md
new file mode 100644
index 0000000000..b581c5f7fd
--- /dev/null
+++ b/helm/mockserver/README.md
@@ -0,0 +1,112 @@
+## Installing MockServer
+
+### Prerequisites
+
+- Kubernetes (i.e. [minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/))
+- [Helm](https://docs.helm.sh/using_helm/#quickstart-guide)
+
+### Helm Install
+To install the chart with:
+- **release name:** `mockserver`
+- **namespace:** `mockserver`
+- **configuration:** `values` (see [values.yaml](values.yaml) for values definitions)
+
+Remotely using `www.mock-server.com` as a chart repo:
+
+```bash
+helm upgrade --install --namespace mockserver mockserver http://www.mock-server.com/mockserver-5.6.1.tgz
+```
+
+**OR**
+
+If you have helm chart source folder (i.e. you have the repository cloned):
+
+```bash
+helm upgrade --install --values helm/mockserver/values.yaml --namespace mockserver mockserver helm/mockserver
+```
+
+**THEN**
+
+To wait until the deployment is complete run:
+
+```bash
+kubectl rollout status deployments mockserver -n mockserver
+```
+
+To check the status of the deployment without waiting, run the following command and confirm the `mockserver` has the `Running` status:
+
+```bash
+kubectl get po -l release=mockserver -n mockserver
+```
+
+To view the logs:
+
+```bash
+kubectl logs $(kubectl get po -l release=mockserver -n mockserver | awk '{if(NR==2)print $1}') -n mockserver
+```
+
+### Modify Start Command
+
+Modify the argument used to start the docker container by setting values explicitly as follows:
+
+```bash
+helm upgrade --install --values helm/mockserver/values.yaml --set app.serverPort=1080 --set app.logLevel=INFO --namespace mockserver mockserver helm/mockserver
+```
+
+The following values are supported:
+- `app.serverPort` (default: 1080)
+- `app.logLevel` (default: INFO)
+- `app.proxyRemoteHost` (no default)
+- `app.proxyRemotePort` (no default)
+- `app.jvmOptions` (no default)
+
+For example configure a proxyRemoteHost and proxyRemotePort, as follows:
+
+```bash
+helm upgrade --install --values helm/mockserver/values.yaml --set app.serverPort=1080 --set app.logLevel=INFO --set app.proxyRemoteHost=www.mock-server.com --set app.proxyRemotePort=443 --namespace mockserver mockserver helm/mockserver
+```
+
+Double check the correct arguments have been passed to the pod, as follows:
+
+```bash
+kubectl -n mockserver logs -l app=mockserver,release=mockserver
+```
+
+### MockServer URL
+
+#### Outside Local Kubernetes Cluster (i.e. minikube)
+
+If the `service` type hasn't been modified the following will provide the MockServer URL from outside the cluster.
+
+```bash
+export NODE_PORT=$(kubectl get --namespace mockserver -o jsonpath="{.spec.ports[0].nodePort}" services mockserver)
+export NODE_IP=$(kubectl get nodes --namespace mockserver -o jsonpath="{.items[0].status.addresses[0].address}")
+export MOCKSERVER_HOST=$NODE_IP:$NODE_PORT
+echo http://$MOCKSERVER_HOST
+```
+
+To test the installation the following `curl` command should return the ports MockServer is bound to:
+
+```bash
+curl -v -X PUT http://$MOCKSERVER_HOST/status
+```
+
+#### Outside Remote Kubernetes Cluster (i.e. Azure AKS, AWS EKS, etc)
+
+```bash
+kubectl -n mockserver port-forward svc/mockserver 1080:1080 &
+export MOCKSERVER_HOST=127.0.0.1:1080
+echo http://$MOCKSERVER_HOST
+```
+
+#### Inside Kubernetes Cluster
+
+If a [DNS server](https://kubernetes.io/docs/concepts/services-networking/service/#dns) has been installed in the Kubernetes cluster the following DNS name should be available `mockserver..svc.cluster.local`, i.e. `mockserver.mockserver.svc.cluster.local`
+
+### Helm Delete
+
+To completely remove the chart:
+
+```bash
+helm delete mockserver --purge
+```
diff --git a/helm/mockserver/requirements.yaml b/helm/mockserver/requirements.yaml
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/helm/mockserver/templates/NOTES.txt b/helm/mockserver/templates/NOTES.txt
new file mode 100644
index 0000000000..7e7f175a8a
--- /dev/null
+++ b/helm/mockserver/templates/NOTES.txt
@@ -0,0 +1,52 @@
+
+1. To wait until the deployment is complete run:
+
+ kubectl rollout status deployments {{ .Release.Name }} -n {{ .Release.Namespace }}
+
+2. To check the status of the deployment without waiting, run the following command and confirm the `mockserver` has the `Running` status:
+
+ kubectl get po -l release={{ .Release.Name }} -n {{ .Release.Namespace }}
+
+3. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+ {{- range .Values.ingress.hosts }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ . }}{{ $.Values.ingress.path }}
+ {{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "mockserver.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ export MOCKSERVER_HOST=$NODE_IP:$NODE_PORT
+ echo http://$MOCKSERVER_HOST
+
+ OR
+
+ kubectl -n mockserver port-forward svc/mockserver 1080:1080 &
+ export MOCKSERVER_HOST=127.0.0.1:1080
+ echo http://$MOCKSERVER_HOST
+{{- else if contains "LoadBalancer" .Values.service.type }}
+
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get svc -w {{ template "mockserver.name" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "mockserver.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
+ export MOCKSERVER_HOST=$SERVICE_IP:{{ .Values.service.port }}
+ echo http://$MOCKSERVER_HOST
+
+ OR
+
+ kubectl -n mockserver port-forward svc/mockserver 1080:1080 &
+ export MOCKSERVER_HOST=127.0.0.1:1080
+ echo http://$MOCKSERVER_HOST
+{{- else if contains "ClusterIP" .Values.service.type }}
+
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "mockserver.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ kubectl port-forward $POD_NAME {{ .Values.service.port }}:{{ .Values.service.port }} -n {{ .Release.Namespace }} &
+ sleep 1 && export MOCKSERVER_HOST=127.0.0.1:{{ .Values.service.port }}
+ echo http://$MOCKSERVER_HOST
+
+ OR
+
+ kubectl -n mockserver port-forward svc/mockserver 1080:1080 &
+ export MOCKSERVER_HOST=127.0.0.1:1080
+ echo http://$MOCKSERVER_HOST
+{{- end }}
diff --git a/helm/mockserver/templates/_helpers.tpl b/helm/mockserver/templates/_helpers.tpl
new file mode 100644
index 0000000000..d6dd15a79c
--- /dev/null
+++ b/helm/mockserver/templates/_helpers.tpl
@@ -0,0 +1,25 @@
+{{/* vim: set filetype=mustache: */}}
+
+{{/* Expand the name of the chart. */}}
+{{- define "mockserver.name" -}}
+ {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/* Create a default fully qualified app name truncated at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). */}}
+{{- define "mockserver.fullname" -}}
+ {{- if .Values.fullnameOverride -}}
+ {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+ {{- else -}}
+ {{- $name := default .Chart.Name .Values.nameOverride -}}
+ {{- if contains $name .Release.Name -}}
+ {{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+ {{- else -}}
+ {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{/* Create chart name and version as used by the chart label. */}}
+{{- define "mockserver.chart" -}}
+ {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
diff --git a/helm/mockserver/templates/deployment.yaml b/helm/mockserver/templates/deployment.yaml
new file mode 100644
index 0000000000..11a2889dd4
--- /dev/null
+++ b/helm/mockserver/templates/deployment.yaml
@@ -0,0 +1,85 @@
+apiVersion: apps/v1beta2
+kind: Deployment
+metadata:
+ name: {{ template "mockserver.name" . }}
+ namespace: {{ .Release.Namespace }}
+ labels:
+ app: {{ template "mockserver.name" . }}
+ chart: {{ template "mockserver.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+spec:
+ replicas: {{ .Values.replicaCount }}
+ selector:
+ matchLabels:
+ app: {{ template "mockserver.name" . }}
+ release: {{ .Release.Name }}
+ template:
+ metadata:
+{{- if .Values.podAnnotations }}
+ # Allows custom annotations to be specified
+ annotations:
+{{ toYaml .Values.podAnnotations | indent 8 }}
+{{- end }}
+ name: {{ template "mockserver.name" . }}
+ labels:
+ app: {{ template "mockserver.name" . }}
+ release: {{ .Release.Name }}
+ spec:
+ containers:
+ - name: {{ template "mockserver.name" . }}
+ image: {{ .Values.image.repository }}/mockserver:mockserver-{{- if .Values.image.snapshot }}snapshot{{- else }}{{ .Chart.Version }}{{- end }}
+{{- if .Values.image.snapshot }}
+ imagePullPolicy: Always
+{{- else }}
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+{{- end }}
+ ports:
+ - name: serviceport
+ containerPort: {{ .Values.app.serverPort }}
+ protocol: TCP
+ readinessProbe:
+ tcpSocket:
+ port: serviceport
+ initialDelaySeconds: 2
+ periodSeconds: 2
+ successThreshold: 1
+ failureThreshold: 10
+ livenessProbe:
+ tcpSocket:
+ port: serviceport
+ initialDelaySeconds: 10
+ periodSeconds: 5
+ successThreshold: 1
+ failureThreshold: 10
+ env:
+ - name: LOG_LEVEL
+ value: {{ .Values.app.logLevel | quote }}
+ - name: SERVER_PORT
+ value: {{ .Values.app.serverPort | quote }}
+{{- if .Values.app.proxyRemoteHost }}
+ - name: PROXY_REMOTE_HOST
+ value: {{ .Values.app.proxyRemoteHost | quote }}
+{{- end }}
+{{- if .Values.app.proxyRemotePort }}
+ - name: PROXY_REMOTE_PORT
+ value: {{ .Values.app.proxyRemotePort | quote }}
+{{- end }}
+{{- if .Values.app.jvmOptions }}
+ - name: JVM_OPTIONS
+ value: {{ .Values.app.jvmOptions | quote }}
+{{- end }}
+ resources:
+{{ toYaml .Values.resources | indent 12 }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+{{ toYaml . | indent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+{{ toYaml . | indent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+{{ toYaml . | indent 8 }}
+ {{- end }}
diff --git a/helm/mockserver/templates/ingress.yaml b/helm/mockserver/templates/ingress.yaml
new file mode 100644
index 0000000000..f8819e9535
--- /dev/null
+++ b/helm/mockserver/templates/ingress.yaml
@@ -0,0 +1,39 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "mockserver.fullname" . -}}
+{{- $servicePort := .Values.service.port -}}
+{{- $ingressPath := .Values.ingress.path -}}
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+ name: {{ $fullName }}
+ labels:
+ app: {{ template "mockserver.name" . }}
+ chart: {{ template "mockserver.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+{{- with .Values.ingress.annotations }}
+ annotations:
+{{ toYaml . | indent 4 }}
+{{- end }}
+spec:
+{{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+{{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ . }}
+ http:
+ paths:
+ - path: {{ $ingressPath }}
+ backend:
+ serviceName: {{ $fullName }}
+ servicePort: serviceport
+ {{- end }}
+{{- end }}
diff --git a/helm/mockserver/templates/service-test.yaml b/helm/mockserver/templates/service-test.yaml
new file mode 100644
index 0000000000..a826273f5c
--- /dev/null
+++ b/helm/mockserver/templates/service-test.yaml
@@ -0,0 +1,18 @@
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ template "mockserver.fullname" . }}-service-test"
+ labels:
+ heritage: {{ .Release.Service }}
+ release: {{ .Release.Name }}
+ chart: {{ template "mockserver.chart" . }}
+ app: {{ template "mockserver.name" . }}
+ annotations:
+ "helm.sh/hook": test-success
+spec:
+ containers:
+ - name: curl
+ image: radial/busyboxplus:curl
+ command: ['curl']
+ args: ['-v', '-s', '-X', 'PUT', '{{ template "mockserver.fullname" . }}:{{ .Values.service.port }}/status']
+ restartPolicy: Never
diff --git a/helm/mockserver/templates/service.yaml b/helm/mockserver/templates/service.yaml
new file mode 100644
index 0000000000..9066821b9d
--- /dev/null
+++ b/helm/mockserver/templates/service.yaml
@@ -0,0 +1,38 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "mockserver.fullname" . }}
+{{- if .Values.service.annotations }}
+ annotations:
+{{ toYaml .Values.service.annotations | indent 4 }}
+{{- end }}
+ labels:
+ app: {{ template "mockserver.name" . }}
+ chart: {{ template "mockserver.chart" . }}
+ release: {{ .Release.Name }}
+ heritage: {{ .Release.Service }}
+spec:
+ type: {{ .Values.service.type }}
+ clusterIP: "{{ .Values.service.clusterIP }}"
+{{- if .Values.service.externalIPs }}
+ externalIPs:
+{{ toYaml .Values.service.externalIPs | indent 4 }}
+{{- end }}
+{{- if .Values.service.loadBalancerIP }}
+ loadBalancerIP: "{{ .Values.service.loadBalancerIP }}"
+{{- end }}
+{{- if .Values.service.loadBalancerSourceRanges }}
+ loadBalancerSourceRanges:
+{{ toYaml .Values.service.loadBalancerSourceRanges | indent 4 }}
+{{- end }}
+ ports:
+ - name: serviceport
+ port: {{ .Values.service.port }}
+ protocol: TCP
+ targetPort: serviceport
+ {{- if (and (eq .Values.service.type "NodePort") (not (empty .Values.service.nodePort))) }}
+ nodePort: {{ .Values.service.nodePort }}
+ {{- end }}
+ selector:
+ app: {{ template "mockserver.name" . }}
+ release: {{ .Release.Name }}
diff --git a/helm/mockserver/values.yaml b/helm/mockserver/values.yaml
new file mode 100644
index 0000000000..715e88776d
--- /dev/null
+++ b/helm/mockserver/values.yaml
@@ -0,0 +1,37 @@
+replicaCount: 1
+
+app:
+ logLevel: "INFO"
+ serverPort: "1080"
+
+image:
+ repository: jamesdbloom
+ snapshot: false
+ pullPolicy: IfNotPresent
+
+service:
+ annotations: {}
+ clusterIP: ""
+ externalIPs: []
+ loadBalancerIP: ""
+ loadBalancerSourceRanges: []
+ type: NodePort
+ port: 1080
+ nodePort: ""
+
+ingress:
+ enabled: false
+ annotations: {}
+ path: /
+ hosts:
+ - mockserver.local
+
+podAnnotations: {}
+
+resources: {}
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
diff --git a/jekyll-www.mock-server.com/.gitignore b/jekyll-www.mock-server.com/.gitignore
index badbc02f6c..c62ab35d31 100644
--- a/jekyll-www.mock-server.com/.gitignore
+++ b/jekyll-www.mock-server.com/.gitignore
@@ -1,2 +1,30 @@
+# Ruby #
+########
+*.gem
+*.a
+*.log
+.bundle
+.config
+.yardoc
+.rakeTasks
+Gemfile.lock
+InstalledFiles
+coverage
+*doc
+*tmp
+lib/bundler/man
+pkg
+spec/reports
+vendor/bundle
+
+# Jekyll #
+##########
_site
+
+# SASS #
+########
.sass-cache
+
+# Temporary Image Artefacts #
+#############################
+images/MockServerScenarios
diff --git a/jekyll-www.mock-server.com/.htaccess b/jekyll-www.mock-server.com/.htaccess
deleted file mode 100644
index 36cd2e2674..0000000000
--- a/jekyll-www.mock-server.com/.htaccess
+++ /dev/null
@@ -1,2 +0,0 @@
-BrowserMatch MSIE ie
-Header set X-UA-Compatible "IE=Edge,chrome=1" env=ie
\ No newline at end of file
diff --git a/jekyll-www.mock-server.com/.well-known/keybase.txt b/jekyll-www.mock-server.com/.well-known/keybase.txt
new file mode 100644
index 0000000000..08be049717
--- /dev/null
+++ b/jekyll-www.mock-server.com/.well-known/keybase.txt
@@ -0,0 +1,55 @@
+==================================================================
+https://keybase.io/jdb197
+--------------------------------------------------------------------
+
+I hereby claim:
+
+ * I am an admin of https://www.mock-server.com
+ * I am jdb197 (https://keybase.io/jdb197) on keybase.
+ * I have a public key ASAIDPMUvr-G_xHQVpLONu_2X8_nEJDjGKFYOc7G6Ht-2Qo
+
+To do so, I am signing this object:
+
+{
+ "body": {
+ "key": {
+ "eldest_kid": "0120080cf314bebf86ff11d05692ce36eff65fcfe71090e318a15839cec6e87b7ed90a",
+ "host": "keybase.io",
+ "kid": "0120080cf314bebf86ff11d05692ce36eff65fcfe71090e318a15839cec6e87b7ed90a",
+ "uid": "ec37ae692d738198b6e4b03e43ac9f19",
+ "username": "jdb197"
+ },
+ "merkle_root": {
+ "ctime": 1509727075,
+ "hash": "97a6dc6670f453ab0b8ba77324504a5d64edba9f86373d9dfeec5cef9c5ed4057adc9065a6ed5876969a70a5b067872dfb3cf696c5d8b17c7d35bc4745fb5647",
+ "hash_meta": "8b108fed467757e89245494f4256aec1f42d8e773f581a3e63095eedee761eb9",
+ "seqno": 1663306
+ },
+ "service": {
+ "hostname": "www.mock-server.com",
+ "protocol": "https:"
+ },
+ "type": "web_service_binding",
+ "version": 1
+ },
+ "client": {
+ "name": "keybase.io go client",
+ "version": "1.0.34"
+ },
+ "ctime": 1509727098,
+ "expire_in": 504576000,
+ "prev": "6e79f11e679422adbcfe27422d0cbd422e08fd73ad7160351a416fef80664554",
+ "seqno": 8,
+ "tag": "signature"
+}
+
+which yields the signature:
+
+hKRib2R5hqhkZXRhY2hlZMOpaGFzaF90eXBlCqNrZXnEIwEgCAzzFL6/hv8R0FaSzjbv9l/P5xCQ4xihWDnOxuh7ftkKp3BheWxvYWTFA0l7ImJvZHkiOnsia2V5Ijp7ImVsZGVzdF9raWQiOiIwMTIwMDgwY2YzMTRiZWJmODZmZjExZDA1NjkyY2UzNmVmZjY1ZmNmZTcxMDkwZTMxOGExNTgzOWNlYzZlODdiN2VkOTBhIiwiaG9zdCI6ImtleWJhc2UuaW8iLCJraWQiOiIwMTIwMDgwY2YzMTRiZWJmODZmZjExZDA1NjkyY2UzNmVmZjY1ZmNmZTcxMDkwZTMxOGExNTgzOWNlYzZlODdiN2VkOTBhIiwidWlkIjoiZWMzN2FlNjkyZDczODE5OGI2ZTRiMDNlNDNhYzlmMTkiLCJ1c2VybmFtZSI6ImpkYjE5NyJ9LCJtZXJrbGVfcm9vdCI6eyJjdGltZSI6MTUwOTcyNzA3NSwiaGFzaCI6Ijk3YTZkYzY2NzBmNDUzYWIwYjhiYTc3MzI0NTA0YTVkNjRlZGJhOWY4NjM3M2Q5ZGZlZWM1Y2VmOWM1ZWQ0MDU3YWRjOTA2NWE2ZWQ1ODc2OTY5YTcwYTViMDY3ODcyZGZiM2NmNjk2YzVkOGIxN2M3ZDM1YmM0NzQ1ZmI1NjQ3IiwiaGFzaF9tZXRhIjoiOGIxMDhmZWQ0Njc3NTdlODkyNDU0OTRmNDI1NmFlYzFmNDJkOGU3NzNmNTgxYTNlNjMwOTVlZWRlZTc2MWViOSIsInNlcW5vIjoxNjYzMzA2fSwic2VydmljZSI6eyJob3N0bmFtZSI6Ind3dy5tb2NrLXNlcnZlci5jb20iLCJwcm90b2NvbCI6Imh0dHBzOiJ9LCJ0eXBlIjoid2ViX3NlcnZpY2VfYmluZGluZyIsInZlcnNpb24iOjF9LCJjbGllbnQiOnsibmFtZSI6ImtleWJhc2UuaW8gZ28gY2xpZW50IiwidmVyc2lvbiI6IjEuMC4zNCJ9LCJjdGltZSI6MTUwOTcyNzA5OCwiZXhwaXJlX2luIjo1MDQ1NzYwMDAsInByZXYiOiI2ZTc5ZjExZTY3OTQyMmFkYmNmZTI3NDIyZDBjYmQ0MjJlMDhmZDczYWQ3MTYwMzUxYTQxNmZlZjgwNjY0NTU0Iiwic2Vxbm8iOjgsInRhZyI6InNpZ25hdHVyZSJ9o3NpZ8RAgpAa/HK/PRuQiOlWieBp2jOYhHnEe1SMQh6JksKfoCnJP+7iuBXQUdKgq/Q2veyMJGbSUO8f2fhuRd1CcHRXDahzaWdfdHlwZSCkaGFzaIKkdHlwZQildmFsdWXEIE+oifdP/LZ13ZDYTsVUuL/lsP+/GOk7rzmhkAPQN9UCo3RhZ80CAqd2ZXJzaW9uAQ==
+
+And finally, I am proving ownership of this host by posting or
+appending to this document.
+
+View my publicly-auditable identity here: https://keybase.io/jdb197
+
+==================================================================
\ No newline at end of file
diff --git a/jekyll-www.mock-server.com/Gemfile b/jekyll-www.mock-server.com/Gemfile
new file mode 100644
index 0000000000..4fd2b24046
--- /dev/null
+++ b/jekyll-www.mock-server.com/Gemfile
@@ -0,0 +1,7 @@
+source 'https://rubygems.org'
+
+gem 'jekyll'
+
+group :jekyll_plugins do
+ gem 'jekyll-code-example-tag'
+end
diff --git a/jekyll-www.mock-server.com/README.md b/jekyll-www.mock-server.com/README.md
new file mode 100644
index 0000000000..6971fa636b
--- /dev/null
+++ b/jekyll-www.mock-server.com/README.md
@@ -0,0 +1,15 @@
+#install jekyll
+1. brew install rbenv
+1. rbenv install -l
+1. rbenv install 2.6.3
+1. rbenv local 2.6.3
+1. `rbenv which gem` install bundler
+1. `rbenv which bundle` install --path vendor/bundle
+1. `rbenv which bundle` exec jekyll serve
+
+#deploy:
+1. cd jekyll-www.mock-server.com
+1. rm -rf _site
+1. `rbenv which bundle` exec jekyll build
+1. open _site
+1. copy to https://s3.console.aws.amazon.com/s3/buckets/aws-website-mockserver-nb9hq/?region=us-east-1
diff --git a/jekyll-www.mock-server.com/_config.yml b/jekyll-www.mock-server.com/_config.yml
index 7feb7929f4..0ca1ea2dd8 100644
--- a/jekyll-www.mock-server.com/_config.yml
+++ b/jekyll-www.mock-server.com/_config.yml
@@ -1,14 +1,18 @@
+exclude: ["vendor", "*.rb", "Gemfile*", "*.gemspec", "*.md", "*.pptx", "*.psd", "images/MockServerScenarios"]
+include: [".well-known"]
+
# Site settings
title: Mock Server
email: jamesdbloom@gmail.com
description: An API to easily mock any system or service you integrate with via HTTP or HTTPS from either Java or JavaScript.
-keywords: >
- mockserver, mock server, mock http server, http mock server, mock-server, mock rest service, mock server java,
- mock api, java mock http server, server mock, java mock server, mock rest server, java mock web service, api mock,
- mock web service java, mock web server, mock service, mock rest api, mock http response, mock http server java,
- mock api server, json mock service, api mocking
+keywords: mockserver, mock server, mock http server, http mock server, mock-server, mock rest service, mock server java, mock api, java mock http server, server mock, java mock server, mock rest server, java mock web service, api mock, mock web service java, mock web server, mock service, mock rest api, mock http response, mock http server java, mock api server, json mock service, api mocking
baseurl: "" # the subpath of your site, e.g. /blog/
url: "http://www.mock-server.com"
+sitemap:
+ exclude:
+ - "/css/main.scss"
+
+# Author
author:
name:
full: James D Bloom
@@ -21,3 +25,5 @@ author:
# Build settings
markdown: kramdown
+sass:
+ style: :compressed
diff --git a/jekyll-www.mock-server.com/_includes/footer.html b/jekyll-www.mock-server.com/_includes/footer.html
index 9533ed4459..6fbed85f0f 100644
--- a/jekyll-www.mock-server.com/_includes/footer.html
+++ b/jekyll-www.mock-server.com/_includes/footer.html
@@ -1,8 +1,7 @@
diff --git a/jekyll-www.mock-server.com/_includes/head.html b/jekyll-www.mock-server.com/_includes/head.html
index 6b1208a354..eb6e5b311b 100644
--- a/jekyll-www.mock-server.com/_includes/head.html
+++ b/jekyll-www.mock-server.com/_includes/head.html
@@ -14,7 +14,7 @@
-
+
@@ -22,8 +22,8 @@
-
-
+
+
-
+
+
+ {% if page.section == 'error' %}
+
+ {% endif %}
+
+
+
+
diff --git a/jekyll-www.mock-server.com/_includes/header.html b/jekyll-www.mock-server.com/_includes/header.html
index f8cc790856..d8ed00b352 100644
--- a/jekyll-www.mock-server.com/_includes/header.html
+++ b/jekyll-www.mock-server.com/_includes/header.html
@@ -3,7 +3,7 @@
- {% assign url = page.url|remove:'index.html' %}
+ {% assign url = page.url | remove:'index.html' %}
{% assign sorted_pages = site.pages | sort:"pageOrder" %}
diff --git a/jekyll-www.mock-server.com/_plugins/IncludeSubPage.rb b/jekyll-www.mock-server.com/_plugins/IncludeSubPage.rb
new file mode 100644
index 0000000000..0dfcb38b39
--- /dev/null
+++ b/jekyll-www.mock-server.com/_plugins/IncludeSubPage.rb
@@ -0,0 +1,77 @@
+# encoding: UTF-8
+
+class IncludeSubPageTag < Liquid::Tag
+ def initialize(tag_name, file, tokens)
+ super
+ @file = file.strip
+ end
+
+ def page_path(context)
+ context.registers[:page].nil? ? includes_dir : File.dirname(context.registers[:page]["path"])
+ end
+
+ def resolved_includes_dir(context)
+ context.registers[:site].in_source_dir(page_path(context))
+ end
+
+ def file_read_opts(context)
+ context.registers[:site].file_read_opts
+ end
+
+ def read_file(file, context)
+ File.read(file, file_read_opts(context))
+ end
+
+ def render(context)
+ dir = resolved_includes_dir(context)
+
+ file = @file
+ path = File.join(dir, file)
+
+ file_contents = read_file(path, context).gsub(/\-{3}.*\-{3}/m, '')
+ partial = Liquid::Template.parse(file_contents)
+
+ context.stack do
+ context['include'] = parse_params(context) if @params
+ partial.render!(context)
+ end
+ end
+end
+
+Liquid::Template.register_tag('include_subpage', IncludeSubPageTag)
+
+class IncludeSubPageAbsoluteTag < Liquid::Tag
+ def initialize(tag_name, file, tokens)
+ super
+ @file = file.strip
+ end
+
+ def page_path(context)
+ context.registers[:page].nil? ? includes_dir : File.dirname(context.registers[:page]["path"])
+ end
+
+ def file_read_opts(context)
+ context.registers[:site].file_read_opts
+ end
+
+ def read_file(file, context)
+ File.read(file, file_read_opts(context))
+ end
+
+ def render(context)
+ dir = '_includes/..'
+
+ file = @file
+ path = File.join(dir, file)
+
+ file_contents = read_file(path, context).gsub(/\-{3}.*\-{3}/m, '')
+ partial = Liquid::Template.parse(file_contents)
+
+ context.stack do
+ context['include'] = parse_params(context) if @params
+ partial.render!(context)
+ end
+ end
+end
+
+Liquid::Template.register_tag('include_subpage_absolute', IncludeSubPageTag)
diff --git a/jekyll-www.mock-server.com/_sass/_accordion.scss b/jekyll-www.mock-server.com/_sass/_accordion.scss
new file mode 100644
index 0000000000..b430614f38
--- /dev/null
+++ b/jekyll-www.mock-server.com/_sass/_accordion.scss
@@ -0,0 +1,78 @@
+/* Style the buttons that are used to open and close the accordion panel */
+.accordion {
+ font-family: 'Averia Sans Libre', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ background-color: #eee;
+ color: #444;
+ cursor: pointer;
+ padding: 18px;
+ width: 100%;
+ text-align: left;
+ border: none;
+ outline: none;
+ transition: 0.5s;
+ margin: 1px;
+ vertical-align: middle;
+}
+
+.accordion.title {
+ padding: 6px;
+ color: black;
+ font-size: 1.1em;
+ background-color: #ccc;
+}
+
+.accordion:hover.title:hover {
+ background-color: #eee;
+}
+
+.accordion.inner {
+ background-color: #000;
+ color: #fff;
+ padding: 2px 8px;
+ width: 99%;
+ margin: 6px;
+}
+
+/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
+.accordion.active, .accordion:hover {
+ background-color: #ccc;
+}
+
+/* Style the accordion panel. Note: hidden by default */
+.panel {
+ padding: 0 1%;
+ background-color: white;
+ display: none;
+}
+
+.panel.title {
+ padding: 0 18px;
+ border-style: solid;
+ border-width: 1px;
+ border-bottom-width: 0px;
+ border-top-width: 0px;
+ border-color: #e8e8e8;
+}
+
+button.accordion.active:after {
+ content: "\2212";
+}
+
+button.accordion:after {
+ content: '\002B';
+ color: #cc1313;
+ font-weight: bold;
+ float: right;
+ margin-left: 5px;
+ font-family: 'Averia Sans Libre', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ font-size: 1.1em;
+}
+
+@media (max-width: 568px) {
+ .accordion {
+ font-size: 0.85em;
+ }
+ .accordion.title {
+ font-size: 1em;
+ }
+}
diff --git a/jekyll-www.mock-server.com/_sass/_prettify.scss b/jekyll-www.mock-server.com/_sass/_prettify.scss
new file mode 100644
index 0000000000..a4df9daafa
--- /dev/null
+++ b/jekyll-www.mock-server.com/_sass/_prettify.scss
@@ -0,0 +1,243 @@
+/* Pretty printing styles. Used with prettify.js. */
+
+pre .str, code .str {
+ color: #5BA382;
+}
+
+/* string - green */
+pre .kwd, code .kwd {
+ color: #E28964;
+}
+
+/* keyword - dark pink */
+pre .com, code .com {
+ color: #9c9c9c;
+ font-style: italic;
+}
+
+/* comment - gray */
+pre .typ, code .typ {
+ color: #5B93DA;
+}
+
+/* type - light blue */
+pre .lit, code .lit {
+ color: #3387CC;
+}
+
+/* literal - blue */
+pre .pun, code .pun {
+ color: #fff;
+}
+
+/* punctuation - white */
+pre .pln, code .pln {
+ color: #e2e2e2;
+}
+
+/* plaintext - white */
+pre .tag, code .tag {
+ color: #89bdff;
+}
+
+/* html/xml tag - light blue */
+pre .atn, code .atn {
+ color: #bdb76b;
+}
+
+/* html/xml attribute name - khaki */
+pre .atv, code .atv {
+ color: #65B042;
+}
+
+/* html/xml attribute value - green */
+pre .dec, code .dec {
+ color: #3387CC;
+}
+
+/* decimal - blue */
+
+pre.prettyprint, code.prettyprint {
+ background-color: #0f0101;
+ border-radius: 8px;
+}
+
+pre.prettyprint {
+ white-space: pre-wrap;
+ font-family: Menlo, Monaco, "Courier New", monospace;
+}
+
+.code {
+ display: block;
+ white-space: pre;
+ overflow: auto;
+ padding: 1%;
+ background-color: #0f0101;
+ color: #F1F1F1;
+ border-radius: 8px;
+ font-size: 1em;
+}
+
+.inline {
+ display: inline;
+ white-space: pre;
+ word-wrap: normal;
+ overflow: auto;
+ margin: 0;
+ line-height: 3.5em;
+}
+
+.xml {
+ color: #C9C9C9;
+}
+
+ol.linenums {
+ margin-top: 0;
+ margin-bottom: 0;
+ color: #AEAEAE;
+}
+
+/* IE indents via margin-left */
+li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
+ list-style-type: none
+}
+
+li.L1, li.L3, li.L5, li.L7, li.L9 {
+ background: none;
+}
+
+@media print {
+ pre .str, code .str {
+ color: #060;
+ }
+ pre .kwd, code .kwd {
+ color: #006;
+ font-weight: bold;
+ }
+ pre .com, code .com {
+ color: #600;
+ font-style: italic;
+ }
+ pre .typ, code .typ {
+ color: #404;
+ font-weight: bold;
+ }
+ pre .lit, code .lit {
+ color: #044;
+ }
+ pre .pun, code .pun {
+ color: #440;
+ }
+ pre .pln, code .pln {
+ color: #000;
+ }
+ pre .tag, code .tag {
+ color: #006;
+ font-weight: bold;
+ }
+ pre .atn, code .atn {
+ color: #404;
+ }
+ pre .atv, code .atv {
+ color: #060;
+ }
+}
+
+@media (max-width: 765px) {
+ pre.prettyprint {
+ width: 98%;
+ }
+ .code {
+ font-size: 0.8em;
+ }
+}
+
+@media (max-width: 568px) {
+ pre.prettyprint {
+ width: 100%;
+ }
+ .code {
+ padding: 2%;
+ }
+}
+
+/* OLD */
+span.keyword {
+ color: #5B93DA;
+}
+
+span.annotation {
+ color: #bdb76b;
+}
+
+span.inline_code {
+ color: #2b2b2b;
+ font-size: 1.1em;
+ font-weight: bolder;
+}
+
+span.numeric_literal {
+ color: #008dff;
+}
+
+span.final,
+span.constant {
+ color: #e28964;
+ font-style: italic;
+}
+
+span.ruby_constant {
+ color: #e28964;
+}
+
+span.string_literal,
+span.command_line_argument_switch {
+ color: #5BA382;
+}
+
+span.this_value {
+ color: #a30707;
+}
+
+span.element {
+ color: #89bdff;
+ font-size: 0.9em;
+}
+
+span.attribute_name,
+span.comment {
+ color: #9c9c9c;
+ font-style: italic;
+ font-size: 0.9em;
+}
+
+span.comment a {
+ color: #6391c3;
+ text-decoration: none;
+}
+
+span.comment.bold {
+ color: gray;
+}
+
+span.javadoc_param_name {
+ color: #c5c5c5;
+}
+
+span.javadoc_param_annotation {
+ color: #9c9c9c;
+ text-decoration: underline;
+}
+
+span.element_value {
+ /*font-size: 1.15em;*/
+ /*color: #E2642F;*/
+}
+
+span.attribute_value {
+ color: blue;
+}
+
+span.command_line_argument_placeholder {
+ color: #9c9c9c;
+}
diff --git a/jekyll-www.mock-server.com/_sass/_styles.scss b/jekyll-www.mock-server.com/_sass/_styles.scss
index 425d5e8748..ee836719c9 100644
--- a/jekyll-www.mock-server.com/_sass/_styles.scss
+++ b/jekyll-www.mock-server.com/_sass/_styles.scss
@@ -1,78 +1,85 @@
body {
- color: #000;
- min-width: 345px;
+ color: #000;
+ min-width: 345px;
}
/*
This is the parent `
` that contains the menu and the content area.
*/
#layout {
- padding-left: 200px; /* left col width "#menu" */
- left: 0;
+ padding-left: 200px; /* left col width "#menu" */
+ left: 0;
}
/*
The content `
` is where all your content goes.
*/
.content {
- margin: 0 auto;
- padding: 0 2em;
- max-width: 1350px;
- line-height: 1.6em;
+ margin: 0 auto;
+ padding: 0 2em;
+ max-width: 1500px;
+ line-height: 1.6em;
}
.header {
- margin: 0;
- color: #333;
- text-align: center;
- padding: 2.5em 2em 0;
- border-bottom: 1px solid #eee;
+ margin: 0;
+ color: #333;
+ text-align: center;
+ padding: 2.5em 2em 0;
+ border-bottom: 1px solid #eee;
}
.header h1 {
- margin: 0.2em 0;
- font-weight: 300;
- font: 4em 'Averia Sans Libre', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+ margin: 0.2em 0;
+ font-weight: 300;
+ font: 4em 'Averia Sans Libre', 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.header h2 {
- font-weight: 300;
- color: #ccc;
- padding: 0;
- margin-top: 0;
+ font-weight: 300;
+ color: #ccc;
+ padding: 0;
+ margin-top: 0;
}
.page_header {
- margin: 0;
- text-align: center;
- padding: 2.5em 2em 0;
- border-bottom: 1px solid #eee;
+ margin: 0;
+ text-align: center;
+ padding: 2.5em 2em 0;
+ border-bottom: 1px solid #eee;
}
.page_header h1 {
- margin: 0.2em 0;
- font: 4em 'Gloria Hallelujah', 'Indie Flower', Helvetica, Arial, sans-serif;
+ margin: 0.2em 0;
+ font: 4em 'Averia Sans Libre', 'Gloria Hallelujah', 'Indie Flower', Helvetica, Arial, sans-serif;
}
.footer {
- display: block;
- overflow: hidden;
- padding-top: 55px;
- padding-bottom: 30px;
- font: 1.25em 'Indie Flower', 'Lato', sans-serif;
- color: #ccc
+ display: block;
+ overflow: hidden;
+ padding-top: 55px;
+ padding-bottom: 30px;
+ // font: 1em 'Indie Flower', 'Lato', sans-serif;
+ font: 1em 'Lato', sans-serif;
+ color: #ccc
}
.footer .left {
- float: left
+ float: left
}
.footer .right {
- float: right
+ float: right
}
.footer a {
- text-decoration: none
+ text-decoration: none
+}
+
+a img.action_image {
+ max-width: 600px;
+ width: 75%;
+ padding-left: 10%;
}
/*
@@ -83,25 +90,25 @@ By using the combination of `position: fixed; top: 0; bottom:0;`, we can make
the menu have 100% height and be fixed on the page as the rest of it scrolls.
*/
#menu {
- margin-left: -200px; /* this should be "#menu" width */
- width: 200px;
- position: fixed;
- top: 0;
- left: 200px; /* this should be "#menu" width */
- bottom: 0;
- z-index: 1; /* so the menu or its navicon stays above all content */
- background: #191818;
- overflow-y: auto;
- -webkit-overflow-scroll: touch; /* for smooth scrolling on mobile */
+ margin-left: -200px; /* this should be "#menu" width */
+ width: 200px;
+ position: fixed;
+ top: 0;
+ left: 200px; /* this should be "#menu" width */
+ bottom: 0;
+ z-index: 1; /* so the menu or its navicon stays above all content */
+ background: #191818;
+ overflow-y: auto;
+ -webkit-overflow-scroll: touch; /* for smooth scrolling on mobile */
}
/*
All anchors inside the menu should be styled like this.
*/
#menu li a {
- color: #999;
- border: none;
- padding: 0.6em 0 0.6em 0.6em;
+ color: #999;
+ border: none;
+ padding: 0.6em 0 0.6em 0.6em;
}
/*
@@ -109,8 +116,8 @@ Remove all background/borders, since we are applying them to #menu.
*/
#menu .pure-menu,
#menu .pure-menu ul {
- border: none;
- background: transparent;
+ border: none;
+ background: transparent;
}
/*
@@ -126,13 +133,13 @@ Change color of the anchor links on hover/focus.
*/
#menu .pure-menu li a:hover,
#menu .pure-menu li a:focus {
- background: #fff;
- color: #000;
+ background: #fff;
+ color: #000;
}
#menu #siteMapLink a {
- padding: 0;
- color: #fff;
+ padding: 0;
+ color: #fff;
}
/*
@@ -140,14 +147,14 @@ Change color of the anchor links on hover/focus.
*/
#menu #siteMapLink:hover,
#menu #siteMapLink:focus {
- background: #999;
+ background: #999;
}
#menu #siteMapLink:hover a,
#menu #siteMapLink:focus a {
- background: #999;
- color: #111;
- font-weight: 900;
+ background: #999;
+ color: #111;
+ font-weight: 900;
}
/*
@@ -155,39 +162,47 @@ This styles the selected menu item `
Travis CI is used for the continuous integration. The build uses both Java 1.6, Java 1.7 and Java 1.8 to build the different modules in their appropriate java version, the latest SNAPSHOT is also deployed to
- Sonatype.
-
-
The status of the build is shown at the top of this page and on the github project using the Travis CI logo
-
-
-
drone.io
-
-
drone.io is an alternative continuous integration platform also being used. Currently Travis CI and drone.io are both being used to determine which platform works better for MockServer.
MockServer is available as a docker container that allows you to easily run MockServer as a separate container on any environment without having to install Java or any other libraries. The docker container fully encapsulates all requirements required to run MockServer (such as Java) and separates the running MockServer instance from all other parts of the system.
The simplest way to run and download MockServer is by using the fully stand alone web server embedded with all dependencies that mocks HTTP and HTTPS requests, as follows:
kubectl rollout status deployments mockserver -n mockserver
+
+
To check the status of the deployment without waiting, run the following command and confirm the mockserver has the Running status:
+
+
kubectl get po -l release=mockserver -n mockserver
+
+
To view the logs:
+
+
kubectl logs $(kubectl get po -l release=mockserver -n mockserver | awk '{if(NR==2)print $1}') -n mockserver
+
+
MockServer will know be deployed a DNS inside kubernetes cluster, of mockserver.<namespace>.svc.cluster.local, i.e. mockserver.mockserver.svc.cluster.local
+
+
To retrieve MockServer address outside kubernetes cluster:
Note: typically it is best practice to configure the ~/.m2/settings.xml file instead of the settings.xml file located inside the conf directory in the maven installation directory (i.e. $M2_HOME). This is because the
+ ~/.m2/settings.xml file will be consistent between maven version upgrades and any changes to this file will only affect a single user.
+
+
Once the Sonatype SNAPSHOT repository has been added, as above, the latest SNAPSHOT build can referenced.
For example add a dependency on the latest SNAPSHOT build for mockserver-netty, as follows:
\ No newline at end of file
diff --git a/license.txt b/license.txt
deleted file mode 100644
index 4542b36504..0000000000
--- a/license.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Copyright 2014 James D Bloom
-
-Licensed 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.
diff --git a/mockserver-client-java/pom.xml b/mockserver-client-java/pom.xml
index 32041fd4fd..062ffad596 100644
--- a/mockserver-client-java/pom.xml
+++ b/mockserver-client-java/pom.xml
@@ -3,7 +3,7 @@
org.mock-servermockserver
- 3.9.1
+ 5.7.04.0.0
@@ -37,8 +37,9 @@
slf4j-api
- ch.qos.logback
- logback-classic
+ org.slf4j
+ slf4j-jdk14
+ true
@@ -56,4 +57,4 @@
-
\ No newline at end of file
+
diff --git a/mockserver-client-java/src/main/java/org/mockserver/client/AbstractClient.java b/mockserver-client-java/src/main/java/org/mockserver/client/AbstractClient.java
deleted file mode 100644
index 1e55222be2..0000000000
--- a/mockserver-client-java/src/main/java/org/mockserver/client/AbstractClient.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package org.mockserver.client;
-
-import com.google.common.base.Strings;
-import org.apache.commons.lang3.StringUtils;
-import org.mockserver.client.netty.NettyHttpClient;
-import org.mockserver.client.serialization.ExpectationSerializer;
-import org.mockserver.client.serialization.HttpRequestSerializer;
-import org.mockserver.client.serialization.VerificationSequenceSerializer;
-import org.mockserver.client.serialization.VerificationSerializer;
-import org.mockserver.model.HttpRequest;
-import org.mockserver.model.HttpResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import static org.mockserver.model.OutboundHttpRequest.outboundRequest;
-
-/**
- * @author jamesdbloom
- */
-public abstract class AbstractClient {
-
- protected static final Logger logger = LoggerFactory.getLogger(AbstractClient.class);
-
- protected final String host;
- protected final int port;
- protected final String contextPath;
- protected NettyHttpClient nettyHttpClient = new NettyHttpClient();
- protected HttpRequestSerializer httpRequestSerializer = new HttpRequestSerializer();
- protected ExpectationSerializer expectationSerializer = new ExpectationSerializer();
- protected VerificationSerializer verificationSerializer = new VerificationSerializer();
- protected VerificationSequenceSerializer verificationSequenceSerializer = new VerificationSequenceSerializer();
-
- /**
- * Start the client communicating to the proxy at the specified host and port
- * and contextPath for example:
- *
- * ProxyClient mockServerClient = new ProxyClient("localhost", 1080, "/proxy");
- *
- * @param host the host for the proxy to communicate with
- * @param port the port for the proxy to communicate with
- * @param contextPath the context path that the proxy war is deployed to
- */
- protected AbstractClient(String host, int port, String contextPath) {
- if (StringUtils.isEmpty(host)) {
- throw new IllegalArgumentException("Host can not be null or empty");
- }
- if (contextPath == null) {
- throw new IllegalArgumentException("ContextPath can not be null");
- }
- this.host = host;
- this.port = port;
- this.contextPath = cleanContextPath(contextPath);
- }
-
- private String cleanContextPath(String contextPath) {
- if (!Strings.isNullOrEmpty(contextPath)) {
- if (!contextPath.endsWith("/")) {
- contextPath += "/";
- }
- if (!contextPath.startsWith("/")) {
- contextPath = "/" + contextPath;
- }
- }
- return contextPath;
- }
-
- protected String calculatePath(String path) {
- return "/" + path;
- }
-
- protected HttpResponse sendRequest(HttpRequest httpRequest) {
- return nettyHttpClient.sendRequest(outboundRequest(host, port, contextPath, httpRequest));
- }
-}
diff --git a/mockserver-client-java/src/main/java/org/mockserver/client/ClientException.java b/mockserver-client-java/src/main/java/org/mockserver/client/ClientException.java
new file mode 100644
index 0000000000..050a72bb8e
--- /dev/null
+++ b/mockserver-client-java/src/main/java/org/mockserver/client/ClientException.java
@@ -0,0 +1,16 @@
+package org.mockserver.client;
+
+/**
+ * @author jamesdbloom
+ */
+public class ClientException extends RuntimeException {
+
+ ClientException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ ClientException(String message) {
+ super(message);
+ }
+
+}
diff --git a/mockserver-client-java/src/main/java/org/mockserver/client/ForwardChainExpectation.java b/mockserver-client-java/src/main/java/org/mockserver/client/ForwardChainExpectation.java
new file mode 100644
index 0000000000..a7ead865ec
--- /dev/null
+++ b/mockserver-client-java/src/main/java/org/mockserver/client/ForwardChainExpectation.java
@@ -0,0 +1,212 @@
+package org.mockserver.client;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.mockserver.client.MockServerEventBus.EventType;
+import org.mockserver.client.MockServerEventBus.SubscriberHandler;
+import org.mockserver.mock.Expectation;
+import org.mockserver.mock.action.ExpectationCallback;
+import org.mockserver.mock.action.ExpectationForwardCallback;
+import org.mockserver.mock.action.ExpectationResponseCallback;
+import org.mockserver.model.*;
+import org.mockserver.websocket.WebSocketClient;
+import org.mockserver.websocket.WebSocketException;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+
+/**
+ * @author jamesdbloom
+ */
+public class ForwardChainExpectation {
+
+ private final MockServerClient mockServerClient;
+ private final Expectation expectation;
+ private final Semaphore availableWebSocketCallbackRegistrations;
+
+ ForwardChainExpectation(MockServerClient mockServerClient, Expectation expectation, Semaphore availableWebSocketCallbackRegistrations) {
+ this.mockServerClient = mockServerClient;
+ this.expectation = expectation;
+ this.availableWebSocketCallbackRegistrations = availableWebSocketCallbackRegistrations;
+ }
+
+ /**
+ * Return response when expectation is matched
+ *
+ * @param httpResponse response to return
+ */
+ public void respond(HttpResponse httpResponse) {
+ expectation.thenRespond(httpResponse);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Evaluate Velocity or JavaScript template to generate response
+ * to return when expectation is matched
+ *
+ * @param httpTemplate Velocity or JavaScript template used to generate response
+ */
+ public void respond(HttpTemplate httpTemplate) {
+ expectation.thenRespond(httpTemplate);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on local class in same JVM implementing ExpectationResponseCallback
+ * to generate response to return when expectation is matched
+ *
+ * The callback class must:
+ * - implement org.mockserver.mock.action.ExpectationResponseCallback
+ * - have a zero argument constructor
+ * - be available in the classpath of the MockServer
+ *
+ * @param httpClassCallback class to callback as a fully qualified class name, i.e. "com.foo.MyExpectationResponseCallback"
+ */
+ public void respond(HttpClassCallback httpClassCallback) {
+ expectation.thenRespond(httpClassCallback);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on object locally or remotely (over web socket)
+ * to generate response to return when expectation is matched
+ *
+ * @param expectationResponseCallback object to call locally or remotely to generate response
+ */
+ public void respond(final ExpectationResponseCallback expectationResponseCallback) {
+ expectation.thenRespond(new HttpObjectCallback().withClientId(registerWebSocketClient(expectationResponseCallback)));
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on object locally or remotely (over web socket)
+ * to generate response to return when expectation is matched
+ *
+ * @param expectationResponseCallback object to call locally or remotely to generate response
+ */
+ public void respond(final ExpectationResponseCallback expectationResponseCallback, Delay delay) {
+ expectation
+ .thenRespond(
+ new HttpObjectCallback()
+ .withClientId(registerWebSocketClient(expectationResponseCallback))
+ .withDelay(delay)
+ );
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Forward request to the specified host and port when expectation is matched
+ *
+ * @param httpForward host and port to forward to
+ */
+ public void forward(HttpForward httpForward) {
+ expectation.thenForward(httpForward);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Evaluate Velocity or JavaScript template to generate
+ * request to forward when expectation is matched
+ *
+ * @param httpTemplate Velocity or JavaScript template used to generate response
+ */
+ public void forward(HttpTemplate httpTemplate) {
+ expectation.thenForward(httpTemplate);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on local class in same JVM implementing ExpectationResponseCallback
+ * to generate request to forward when expectation is matched
+ *
+ * The callback class must:
+ * - implement org.mockserver.mock.action.ExpectationForwardCallback
+ * - have a zero argument constructor
+ * - be available in the classpath of the MockServer
+ *
+ * @param httpClassCallback class to callback as a fully qualified class name, i.e. "com.foo.MyExpectationResponseCallback"
+ */
+ public void forward(HttpClassCallback httpClassCallback) {
+ expectation.thenForward(httpClassCallback);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on object locally or remotely (over web socket)
+ * to generate request to forward when expectation is matched
+ *
+ * @param expectationForwardCallback object to call locally or remotely to generate request
+ */
+ public void forward(final ExpectationForwardCallback expectationForwardCallback) {
+ expectation.thenForward(new HttpObjectCallback().withClientId(registerWebSocketClient(expectationForwardCallback)));
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Call method on object locally or remotely (over web socket)
+ * to generate request to forward when expectation is matched
+ *
+ * @param expectationForwardCallback object to call locally or remotely to generate request
+ */
+ public void forward(final ExpectationForwardCallback expectationForwardCallback, final Delay delay) {
+ expectation
+ .thenForward(new HttpObjectCallback()
+ .withClientId(registerWebSocketClient(expectationForwardCallback))
+ .withDelay(delay)
+ );
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ private String registerWebSocketClient(ExpectationCallback expectationCallback) {
+ try {
+ final WebSocketClient webSocketClient = new WebSocketClient<>(availableWebSocketCallbackRegistrations);
+ final Future register = webSocketClient.registerExpectationCallback(
+ expectationCallback,
+ mockServerClient.getEventLoopGroup(),
+ mockServerClient.remoteAddress(),
+ mockServerClient.contextPath(),
+ mockServerClient.isSecure()
+ );
+ MockServerEventBus.getInstance().subscribe(new SubscriberHandler() {
+ @Override
+ public void handle() {
+ webSocketClient.stopClient();
+ }
+ }, EventType.STOP, EventType.RESET);
+ return register.get();
+ } catch (Exception e) {
+ if (e.getCause() instanceof WebSocketException) {
+ throw new ClientException(e.getCause().getMessage(), e);
+ } else {
+ throw new ClientException("Unable to retrieve client registration id", e);
+ }
+ }
+ }
+
+ /**
+ * Override fields, headers, and cookies etc in request being forwarded with
+ * specified fields, headers and cookies, etc in the specified request
+ * when expectation is matched
+ *
+ * @param httpOverrideForwardedRequest contains request to override request being forwarded
+ */
+ public void forward(HttpOverrideForwardedRequest httpOverrideForwardedRequest) {
+ expectation.thenForward(httpOverrideForwardedRequest);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ /**
+ * Return error when expectation is matched
+ *
+ * @param httpError error to return
+ */
+ public void error(HttpError httpError) {
+ expectation.thenError(httpError);
+ mockServerClient.sendExpectation(expectation);
+ }
+
+ @VisibleForTesting
+ Expectation getExpectation() {
+ return expectation;
+ }
+
+}
diff --git a/mockserver-client-java/src/main/java/org/mockserver/client/MockServerClient.java b/mockserver-client-java/src/main/java/org/mockserver/client/MockServerClient.java
new file mode 100644
index 0000000000..55c5030a6a
--- /dev/null
+++ b/mockserver-client-java/src/main/java/org/mockserver/client/MockServerClient.java
@@ -0,0 +1,647 @@
+package org.mockserver.client;
+
+import com.google.common.base.Strings;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.nio.NioEventLoopGroup;
+import org.apache.commons.lang3.StringUtils;
+import org.mockserver.Version;
+import org.mockserver.client.MockServerEventBus.EventType;
+import org.mockserver.configuration.ConfigurationProperties;
+import org.mockserver.logging.MockServerLogger;
+import org.mockserver.matchers.TimeToLive;
+import org.mockserver.matchers.Times;
+import org.mockserver.mock.Expectation;
+import org.mockserver.model.*;
+import org.mockserver.serialization.*;
+import org.mockserver.stop.Stoppable;
+import org.mockserver.verify.Verification;
+import org.mockserver.verify.VerificationSequence;
+import org.mockserver.verify.VerificationTimes;
+
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import static io.netty.handler.codec.http.HttpHeaderNames.HOST;
+import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import static org.mockserver.formatting.StringFormatter.formatLogMessage;
+import static org.mockserver.mock.HttpStateHandler.LOG_SEPARATOR;
+import static org.mockserver.model.HttpRequest.request;
+import static org.mockserver.model.PortBinding.portBinding;
+import static org.mockserver.verify.Verification.verification;
+import static org.mockserver.verify.VerificationTimes.exactly;
+
+/**
+ * @author jamesdbloom
+ */
+public class MockServerClient implements Stoppable {
+
+ protected final MockServerLogger mockServerLogger = new MockServerLogger(this.getClass());
+ private final EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
+ private final Semaphore availableWebSocketCallbackRegistrations = new Semaphore(1);
+ private final String host;
+ private final String contextPath;
+ private final Class clientClass;
+ protected Future portFuture;
+ private Boolean secure;
+ private Integer port;
+ private NettyHttpClient nettyHttpClient = new NettyHttpClient(eventLoopGroup, null);
+ private HttpRequestSerializer httpRequestSerializer = new HttpRequestSerializer(mockServerLogger);
+ private HttpRequestResponseSerializer httpRequestResponseSerializer = new HttpRequestResponseSerializer(mockServerLogger);
+ private PortBindingSerializer portBindingSerializer = new PortBindingSerializer(mockServerLogger);
+ private ExpectationSerializer expectationSerializer = new ExpectationSerializer(mockServerLogger);
+ private VerificationSerializer verificationSerializer = new VerificationSerializer(mockServerLogger);
+ private VerificationSequenceSerializer verificationSequenceSerializer = new VerificationSequenceSerializer(mockServerLogger);
+
+ /**
+ * Start the client communicating to a MockServer on localhost at the port
+ * specified with the Future
+ *
+ * @param portFuture the port for the MockServer to communicate with
+ */
+ public MockServerClient(Future portFuture) {
+ this.clientClass = MockServerClient.class;
+ this.host = "127.0.0.1";
+ this.portFuture = portFuture;
+ this.contextPath = "";
+ }
+
+ /**
+ * Start the client communicating to a MockServer at the specified host and port
+ * for example:
+ *
+ * MockServerClient mockServerClient = new MockServerClient("localhost", 1080);
+ *
+ * @param host the host for the MockServer to communicate with
+ * @param port the port for the MockServer to communicate with
+ */
+ public MockServerClient(String host, int port) {
+ this(host, port, "");
+ }
+
+ /**
+ * Start the client communicating to a MockServer at the specified host and port
+ * and contextPath for example:
+ *
+ * MockServerClient mockServerClient = new MockServerClient("localhost", 1080, "/mockserver");
+ *
+ * @param host the host for the MockServer to communicate with
+ * @param port the port for the MockServer to communicate with
+ * @param contextPath the context path that the MockServer war is deployed to
+ */
+ public MockServerClient(String host, int port, String contextPath) {
+ this.clientClass = MockServerClient.class;
+ if (StringUtils.isEmpty(host)) {
+ throw new IllegalArgumentException("Host can not be null or empty");
+ }
+ if (contextPath == null) {
+ throw new IllegalArgumentException("ContextPath can not be null");
+ }
+ this.host = host;
+ this.port = port;
+ this.contextPath = contextPath;
+ }
+
+ EventLoopGroup getEventLoopGroup() {
+ return eventLoopGroup;
+ }
+
+ public boolean isSecure() {
+ return secure != null ? secure : false;
+ }
+
+ public MockServerClient withSecure(boolean secure) {
+ this.secure = secure;
+ return this;
+ }
+
+ private int port() {
+ if (this.port == null) {
+ try {
+ port = portFuture.get();
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ return this.port;
+ }
+
+ public InetSocketAddress remoteAddress() {
+ return new InetSocketAddress(this.host, port());
+ }
+
+ public String contextPath() {
+ return contextPath;
+ }
+
+ private String calculatePath(String path) {
+ String cleanedPath = "/mockserver/" + path;
+ if (isNotBlank(contextPath)) {
+ cleanedPath =
+ (!contextPath.startsWith("/") ? "/" : "") +
+ contextPath +
+ (!contextPath.endsWith("/") ? "/" : "") +
+ (cleanedPath.startsWith("/") ? cleanedPath.substring(1) : cleanedPath);
+ }
+ return (!cleanedPath.startsWith("/") ? "/" : "") + cleanedPath;
+ }
+
+ private HttpResponse sendRequest(HttpRequest request) {
+ try {
+ if (secure != null) {
+ request.withSecure(secure);
+ }
+
+ HttpResponse response = nettyHttpClient.sendRequest(
+ request.withHeader(HOST.toString(), this.host + ":" + port()),
+ ConfigurationProperties.maxSocketTimeout(),
+ TimeUnit.MILLISECONDS
+ );
+
+ if (response != null) {
+ if (response.getStatusCode() != null &&
+ response.getStatusCode() == BAD_REQUEST.code()) {
+ throw new IllegalArgumentException(response.getBodyAsString());
+ }
+ String serverVersion = response.getFirstHeader("version");
+ String clientVersion = Version.getVersion();
+ if (isNotBlank(serverVersion) && isNotBlank(clientVersion) && !clientVersion.equals(serverVersion)) {
+ throw new ClientException("Client version \"" + clientVersion + "\" does not match server version \"" + serverVersion + "\"");
+ }
+ }
+
+ return response;
+ } catch (RuntimeException rex) {
+ if (isNotBlank(rex.getMessage()) && (rex.getMessage().contains("executor not accepting a task") || rex.getMessage().contains("loop shut down"))) {
+ throw new IllegalStateException(this.getClass().getSimpleName() + " has already been closed, please create new " + this.getClass().getSimpleName() + " instance");
+ } else {
+ throw rex;
+ }
+ }
+ }
+
+ /**
+ * Returns whether MockServer is running
+ */
+ public boolean isRunning() {
+ return isRunning(10, 500, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * Returns whether server MockServer is running, by polling the MockServer a configurable amount of times
+ */
+ public boolean isRunning(int attempts, long timeout, TimeUnit timeUnit) {
+ try {
+ HttpResponse httpResponse = sendRequest(request().withMethod("PUT").withPath(calculatePath("status")));
+ if (httpResponse.getStatusCode() == HttpStatusCode.OK_200.code()) {
+ return true;
+ } else if (attempts == 0) {
+ return false;
+ } else {
+ try {
+ timeUnit.sleep(timeout);
+ } catch (InterruptedException e) {
+ // ignore interrupted exception
+ }
+ return isRunning(attempts - 1, timeout, timeUnit);
+ }
+ } catch (SocketConnectionException | IllegalStateException sce) {
+ return false;
+ }
+ }
+
+ /**
+ * Bind new ports to listen on
+ */
+ public List bind(Integer... ports) {
+ String boundPorts = sendRequest(request().withMethod("PUT").withPath(calculatePath("bind")).withBody(portBindingSerializer.serialize(portBinding(ports)), StandardCharsets.UTF_8)).getBodyAsString();
+ return portBindingSerializer.deserialize(boundPorts).getPorts();
+ }
+
+ /**
+ * Stop MockServer gracefully (only support for Netty version, not supported for WAR version)
+ */
+ public void stop() {
+ stop(true);
+ }
+
+ /**
+ * Stop MockServer gracefully (only support for Netty version, not supported for WAR version)
+ */
+ public MockServerClient stop(boolean ignoreFailure) {
+ MockServerEventBus.getInstance().publish(EventType.STOP);
+ try {
+ sendRequest(request().withMethod("PUT").withPath(calculatePath("stop")));
+ if (isRunning()) {
+ for (int i = 0; isRunning() && i < 50; i++) {
+ TimeUnit.MILLISECONDS.sleep(5);
+ }
+ }
+ } catch (RejectedExecutionException ree) {
+ mockServerLogger.trace("Request rejected because closing down but logging at trace level for information just in case due to some other actual error " + ree);
+ } catch (Exception e) {
+ if (!ignoreFailure) {
+ mockServerLogger.warn("Failed to send stop request to MockServer " + e.getMessage());
+ }
+ }
+ if (!eventLoopGroup.isShuttingDown()) {
+ eventLoopGroup.shutdownGracefully();
+ }
+ return clientClass.cast(this);
+ }
+
+ @Override
+ public void close() {
+ stop();
+ }
+
+ /**
+ * Reset MockServer by clearing all expectations
+ */
+ public MockServerClient reset() {
+ MockServerEventBus.getInstance().publish(EventType.RESET);
+ sendRequest(request().withMethod("PUT").withPath(calculatePath("reset")));
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Clear all expectations and logs that match the http
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to clear each expectation if null all expectations are cleared
+ */
+ public MockServerClient clear(HttpRequest httpRequest) {
+ sendRequest(request().withMethod("PUT").withPath(calculatePath("clear")).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8));
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Clear expectations, logs or both that match the http
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to clear each expectation if null all expectations are cleared
+ * @param type the type to clear, EXPECTATION, LOG or BOTH
+ */
+ public MockServerClient clear(HttpRequest httpRequest, ClearType type) {
+ sendRequest(request().withMethod("PUT").withPath(calculatePath("clear")).withQueryStringParameter("type", type.name().toLowerCase()).withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8));
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Verify a list of requests have been sent in the order specified for example:
+ *
+ *
+ * @param httpRequests the http requests that must be matched for this verification to pass
+ * @throws AssertionError if the request has not been found
+ */
+ public MockServerClient verify(HttpRequest... httpRequests) throws AssertionError {
+ if (httpRequests == null || httpRequests.length == 0 || httpRequests[0] == null) {
+ throw new IllegalArgumentException("verify(HttpRequest...) requires a non null non empty array of HttpRequest objects");
+ }
+
+ VerificationSequence verificationSequence = new VerificationSequence().withRequests(httpRequests);
+ String result = sendRequest(request().withMethod("PUT").withPath(calculatePath("verifySequence")).withBody(verificationSequenceSerializer.serialize(verificationSequence), StandardCharsets.UTF_8)).getBodyAsString();
+
+ if (result != null && !result.isEmpty()) {
+ throw new AssertionError(result);
+ }
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Verify a request has been sent for example:
+ *
+ * once() - verify the request was only received once
+ * exactly(n) - verify the request was only received exactly n times
+ * atLeast(n) - verify the request was only received at least n times
+ *
+ * @param httpRequest the http request that must be matched for this verification to pass
+ * @param times the number of times this request must be matched
+ * @throws AssertionError if the request has not been found
+ */
+ public MockServerClient verify(HttpRequest httpRequest, VerificationTimes times) throws AssertionError {
+ if (httpRequest == null) {
+ throw new IllegalArgumentException("verify(HttpRequest, VerificationTimes) requires a non null HttpRequest object");
+ }
+ if (times == null) {
+ throw new IllegalArgumentException("verify(HttpRequest, VerificationTimes) requires a non null VerificationTimes object");
+ }
+
+ Verification verification = verification().withRequest(httpRequest).withTimes(times);
+ String result = sendRequest(request().withMethod("PUT").withPath(calculatePath("verify")).withBody(verificationSerializer.serialize(verification), StandardCharsets.UTF_8)).getBodyAsString();
+
+ if (result != null && !result.isEmpty()) {
+ throw new AssertionError(result);
+ }
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Verify no requests have been have been sent.
+ *
+ * @throws AssertionError if any request has been found
+ */
+ public MockServerClient verifyZeroInteractions() throws AssertionError {
+ Verification verification = verification().withRequest(request()).withTimes(exactly(0));
+ String result = sendRequest(request().withMethod("PUT").withPath(calculatePath("verify")).withBody(verificationSerializer.serialize(verification), StandardCharsets.UTF_8)).getBodyAsString();
+
+ if (result != null && !result.isEmpty()) {
+ throw new AssertionError(result);
+ }
+ return clientClass.cast(this);
+ }
+
+ /**
+ * Retrieve the recorded requests that match the httpRequest parameter, use null for the parameter to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @return an array of all requests that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public HttpRequest[] retrieveRecordedRequests(HttpRequest httpRequest) {
+ String recordedRequests = retrieveRecordedRequests(httpRequest, Format.JSON);
+ if (StringUtils.isNotEmpty(recordedRequests) && !recordedRequests.equals("[]")) {
+ return httpRequestSerializer.deserializeArray(recordedRequests);
+ } else {
+ return new HttpRequest[0];
+ }
+ }
+
+ /**
+ * Retrieve the recorded requests that match the httpRequest parameter, use null for the parameter to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @param format the format to retrieve the expectations, either JAVA or JSON
+ * @return an array of all requests that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public String retrieveRecordedRequests(HttpRequest httpRequest, Format format) {
+ HttpResponse httpResponse = sendRequest(
+ request()
+ .withMethod("PUT")
+ .withPath(calculatePath("retrieve"))
+ .withQueryStringParameter("type", RetrieveType.REQUESTS.name())
+ .withQueryStringParameter("format", format.name())
+ .withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8)
+ );
+ return httpResponse.getBodyAsString();
+ }
+
+ /**
+ * Retrieve the recorded requests and responses that match the httpRequest parameter, use null for the parameter to retrieve all requests and responses
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request (and its corresponding response), use null for the parameter to retrieve for all requests
+ * @return an array of all requests and responses that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public HttpRequestAndHttpResponse[] retrieveRecordedRequestsAndResponses(HttpRequest httpRequest) {
+ String recordedRequests = retrieveRecordedRequestsAndResponses(httpRequest, Format.JSON);
+ if (StringUtils.isNotEmpty(recordedRequests) && !recordedRequests.equals("[]")) {
+ return httpRequestResponseSerializer.deserializeArray(recordedRequests);
+ } else {
+ return new HttpRequestAndHttpResponse[0];
+ }
+ }
+
+ /**
+ * Retrieve the recorded requests that match the httpRequest parameter, use null for the parameter to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @param format the format to retrieve the expectations, either JAVA or JSON
+ * @return an array of all requests that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public String retrieveRecordedRequestsAndResponses(HttpRequest httpRequest, Format format) {
+ HttpResponse httpResponse = sendRequest(
+ request()
+ .withMethod("PUT")
+ .withPath(calculatePath("retrieve"))
+ .withQueryStringParameter("type", RetrieveType.REQUEST_RESPONSES.name())
+ .withQueryStringParameter("format", format.name())
+ .withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8)
+ );
+ return httpResponse.getBodyAsString();
+ }
+
+ /**
+ * Retrieve the request-response combinations that have been recorded as a list of expectations, only those that match the httpRequest parameter are returned, use null to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @return an array of all expectations that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public Expectation[] retrieveRecordedExpectations(HttpRequest httpRequest) {
+ String recordedExpectations = retrieveRecordedExpectations(httpRequest, Format.JSON);
+ if (isNotBlank(recordedExpectations) && !recordedExpectations.equals("[]")) {
+ return expectationSerializer.deserializeArray(recordedExpectations);
+ } else {
+ return new Expectation[0];
+ }
+ }
+
+ /**
+ * Retrieve the request-response combinations that have been recorded as a list of expectations, only those that match the httpRequest parameter are returned, use null to retrieve all requests
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @param format the format to retrieve the expectations, either JAVA or JSON
+ * @return an array of all expectations that have been recorded by the MockServer in the order they have been received and including duplicates where the same request has been received multiple times
+ */
+ public String retrieveRecordedExpectations(HttpRequest httpRequest, Format format) {
+ HttpResponse httpResponse = sendRequest(
+ request()
+ .withMethod("PUT")
+ .withPath(calculatePath("retrieve"))
+ .withQueryStringParameter("type", RetrieveType.RECORDED_EXPECTATIONS.name())
+ .withQueryStringParameter("format", format.name())
+ .withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8)
+ );
+ return httpResponse.getBodyAsString();
+ }
+
+ /**
+ * Retrieve the logs associated to a specific requests, this shows all logs for expectation matching, verification, clearing, etc
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @return all log messages recorded by the MockServer when creating expectations, matching expectations, performing verification, clearing logs, etc
+ */
+ public String retrieveLogMessages(HttpRequest httpRequest) {
+ HttpResponse httpResponse = sendRequest(
+ request()
+ .withMethod("PUT")
+ .withPath(calculatePath("retrieve"))
+ .withQueryStringParameter("type", RetrieveType.LOGS.name())
+ .withBody(httpRequest != null ? httpRequestSerializer.serialize(httpRequest) : "", StandardCharsets.UTF_8)
+ );
+ return httpResponse.getBodyAsString();
+ }
+
+ /**
+ * Retrieve the logs associated to a specific requests, this shows all logs for expectation matching, verification, clearing, etc
+ *
+ * @param httpRequest the http request that is matched against when deciding whether to return each request, use null for the parameter to retrieve for all requests
+ * @return an array of all log messages recorded by the MockServer when creating expectations, matching expectations, performing verification, clearing logs, etc
+ */
+ public String[] retrieveLogMessagesArray(HttpRequest httpRequest) {
+ return retrieveLogMessages(httpRequest).split(LOG_SEPARATOR);
+ }
+
+ /**
+ * Specify an unlimited expectation that will respond regardless of the number of matching http
+ * for example:
+ *
+ *
+ * @param httpRequest the http request that must be matched for this expectation to respond
+ * @return an Expectation object that can be used to specify the response
+ */
+ public ForwardChainExpectation when(HttpRequest httpRequest) {
+ return when(httpRequest, Times.unlimited());
+ }
+
+ /**
+ * Specify an limited expectation that will respond a specified number of times when the http is matched
+ * for example:
+ *
+ *
+ * @param httpRequest the http request that must be matched for this expectation to respond
+ * @param times the number of times to respond when this http is matched
+ * @return an Expectation object that can be used to specify the response
+ */
+ public ForwardChainExpectation when(HttpRequest httpRequest, Times times) {
+ return new ForwardChainExpectation(this, new Expectation(httpRequest, times, TimeToLive.unlimited()), availableWebSocketCallbackRegistrations);
+ }
+
+ /**
+ * Specify an limited expectation that will respond a specified number of times when the http is matched
+ * for example:
+ *
+ *
+ * @param httpRequest the http request that must be matched for this expectation to respond
+ * @param times the number of times to respond when this http is matched
+ * @param timeToLive the length of time from when the server receives the expectation that the expectation should be active
+ * @return an Expectation object that can be used to specify the response
+ */
+ public ForwardChainExpectation when(HttpRequest httpRequest, Times times, TimeToLive timeToLive) {
+ return new ForwardChainExpectation(this, new Expectation(httpRequest, times, timeToLive), availableWebSocketCallbackRegistrations);
+ }
+
+ /**
+ * Specify one or more expectations, normally this method should not be used directly instead the when(...) and response(...) or forward(...) or error(...) methods should be used
+ * for example:
+ *