Extensions

You can use extensions to add dynamic content to response headers and response body.

For example, if you create a response with body { "Number": "{{randomInteger}}", "Date": "{{httpNow}}" } it will be rendered as { "Number": "165007562", "Date": "Sat, 02 Apr 2017 18:41:35 GMT" }

Below you will find all available extensions.

Load CSV data file

Save your data in trafficparrot-release-x.y.z/data/data.csv in CSV format.

To load the data in the response use {{csvDataFile 'row,col'}} in the response definition.

For example, {{csvDataFile '2,4'}} will read file trafficparrot-release-x.y.z/data/data.csv then load the 2nd row in the file and then lookup the 4th column value.

Generate random values

To generate a random value in the response use one of the following:

  1. {{randomInteger}} - A random integer, e.g. 1543243211
  2. {{randomDouble}} - A random double, e.g. -0.3476573
  3. {{randomString}} - A random String, e.g. lW7H2gRfFqALsev0zDoJ4o3qGMtNYYgs
  4. {{randomUUID}} - A random UUID, e.g. 5d0d4989-b5c1-412e-bbe6-457fd5d58493

Use request data in response *

To use request attributes in the response:

  1. {{request.url}} - URL
  2. {{request.path}} - Path
  3. {{request.path.[n]}} - N-th path element
  4. {{request.query.parameterName}} - Parameter value
  5. {{request.query.parameterName.[n]}} - N-th parameter value
  6. {{request.headers.headerName}} - First value of a header
  7. {{request.headers.[headerName]}} - First value of a header
  8. {{request.headers.headerName.[n]}}- N-th value of header
  9. {{request.cookies.cookieName}} - Cookie value
  10. {{request.body}} - Request body
(*) Implemented with ResponseTemplateTransformer

Handlebars extension functions

All of jknack Handlebars string helpers are available for use in response headers and body.

  1. {{defaultIfEmpty value ["default value"]}}} - Render a default value if the specified value is not available, for example {{defaultIfEmpty request.query.username "Username parameter was not present in the request"}}
  2. {{substring value start end}} - Render the beginning of the string value, for example {{defaultIfEmpty request.query.username 0 3}}
  3. {{substring value start}} - Render the end of the string value, for example {{defaultIfEmpty request.query.username 5}}
  4. {{replace value "aaa" "bbb"}} - Replace string aaa with bbb
  5. {{abbreviate value 5}} - Render a truncated version of a string. Minimum value is 4.
  6. {{yesno value [yes="yes"] [no="no"] maybe=["maybe"]}} - Convert a boolean "true", "false" to a string representation
  7. {{capitalize value [fully=false]}} - Capitalize a string
  8. {{stripTags value}} - Remove all HTML or XML tags from the string
  9. {{stringFormat string param0 param1 ... paramN}} - Format the string
  10. {{slugify value}} - Create a slug, for example "a b c" will be rendered as "a-b-c"
  11. {{numberFormat number ["format"] [locale=default]}} - Format a number for a given locale or format
  12. {{now ["format"] [tz=timeZone|timeZoneId]}} - Date is a specified format and timezone
  13. {{upper value}} - Uppercase string
  14. {{lower value}} - Lowercase string
  15. {{rjust value 20 [pad=" "]}} - Right adjust string
  16. {{ljust value 20 [pad=" "]}} - Left adjust string
  17. {{cut value [" "]}} - Cut out all the occurrences in the string
  18. {{center value size=19 [pad="char"]}} - Center string value padded with the specified character
  19. {{capitalizeFirst value}} - Capitalize first word
  20. {{join value "," [prefix="aPrefix"] [suffix="aSuffix"]}} - Join an array of values

Loops and iterators

All block helpers defined in handlebars specification are available. As an example the following use of {{#each}} in a response body will render all request headers:
<requestHeaders>
  {{#each request.headers}}
    <name>{{@key}}</name>
    <value>{{this}}</value>
  {{/each}}
</requestHeaders>

Conditionals (if, else)

All block helpers defined in handlebars specification are available. As an example the following use of {{#if}} in a response body will render a different response based on availability of a request paramater:
{{#if request.query.password}}
  Password was present in the request.
{{else}}
  Please provide a password!
{{/if}}

Assorted

  1. {{httpNow}} - Date in RFC 1123 format (HTTP date format), e.g. Date: {{httpNow}} can be rendered as Date: Sat, 01 Apr 2017 10:55:05 GMT. Typically used as a value for the "Date" header.

Ask for new extensions

If you need new extensions just email us at help@trafficparrot.com we will will do our best to create them for you.

Disabling {{...}}

If you would like to use {{...}} notation in your templates and not having it interpreted as an attempt to use an extension you need to do one of the following things:
  1. For individual responses, use escaped syntax: \{{...}}
  2. Or, disable extensions globally by setting both trafficparrot.jms.handlebars.enabled=false and trafficparrot.http.handlebars.enabled=false in trafficparrot.properties and restarting Traffic Parrot

Create your own custom extensions

Introduction

In order to create your own HTTP extensions basic Java programming language knowledge is required. We use Java to write extensions because it is a simple to use and yet very powerful language. It is also the most popular programming language in the world. If this is not something you can do, we can create the extensions for you instead.

There are two types of extensions you can create:
  • Custom handlebar helpers. Simple, for basic usage. These extensions can be used to transform or generate dynamically the response content.
  • Custom response transformers for HTTP and JMS. Complex, for advanced usage. These extensions can do advanced transformations, routing of responses, and many more.

Custom handlebar helpers

Traffic Parrot allows for Handlebars notation in the responses. They are typically used to add dynamic content to the responses. They can be used for both HTTP and JMS.

For example, all of these existing extensions are handlebar helpers: If you would like to add new Handlebars Helpers, have a look at the following example:
  1. Download and open the SDK workspace project in an IDE like IntelliJ IDEA or Eclipse
  2. Explore the project and the Java classes available in the SDK. Look for usages of TrafficParrotHelper They provide example usages of Handlebars Helpers. Have a look at both main and test classes.
  3. Create a new extension class based on the examples provided in the SDK (by extending TrafficParrotHelper class). For example:
    package com.trafficparrot.sdk.example.http.template;
    
    import com.github.jknack.handlebars.Handlebars;
    import com.github.jknack.handlebars.Options;
    import com.trafficparrot.sdk.handlebars.TrafficParrotHelper;
    
    import java.io.IOException;
    import java.util.Random;
    
    public class RandomInteger extends TrafficParrotHelper<Object> {
        @Override
        public Handlebars.SafeString doApply(Object context, Options options) throws IOException {
            return new Handlebars.SafeString(String.valueOf(new Random().nextInt()));
        }
    }
  4. Build the project ./mvnw clean install
  5. Copy target/trafficparrot-sdk-workspace-x.y.z.jar
    to directory trafficparrot-enterprise-release-x.y.z/lib/virtualservice-x.y.z to use with HTTP
    or to directory trafficparrot-enterprise-release-x.y.z/lib/external to use with JMS
  6. Look for properties trafficparrot.http.handlebars.helpers and trafficparrot.jms.handlebars.helpers in trafficparrot.properties and add your new class to the list of extension classes there. (Why do I have to edit the extensions properties every time?)
  7. Stop Traffic Parrot
  8. Start Traffic Parrot
  9. If the name of the class you have created is RandomInteger the extension you will use in response templates will be called {{randomInteger}} by default. The name can be changed by implementing the TrafficParrotHelper.getName method.
  10. Edit an existing mapping and put {{randomInteger}} anywhere in the response body.
  11. Make a request to the virtual service
  12. The response you receive should contain the randomly generated integer.

Custom HTTP response transformers

Traffic Parrot allows for creating custom HTTP response transformers. They allow for altering any part of the HTTP response in any way you like, and have access to the request data.

If you would like to add a new HTTP response transformer, have a look at the following example:
  1. Download and open the SDK workspace project in an IDE like IntelliJ IDEA or Eclipse
  2. Explore the project and the Java classes available in the SDK. They provide example usages of HTTP response transformers. Look for usages of HttpResponseTransformer and HttpResponseDefinitionTransformer. Have a look at both main and test classes.
  3. Create a new extension class based on the examples provided in the SDK (by extending HttpResponseTransformer class). For example:
    package com.trafficparrot.sdk.example.http.responsetransformer;
    
    import com.github.tomakehurst.wiremock.common.FileSource;
    import com.github.tomakehurst.wiremock.extension.Parameters;
    import com.github.tomakehurst.wiremock.http.Request;
    import com.github.tomakehurst.wiremock.http.Response;
    import com.trafficparrot.sdk.http.HttpResponseTransformer;
    
    import java.util.Random;
    
    import static com.github.tomakehurst.wiremock.http.HttpHeaders.noHeaders;
    
    public class RandomServerFailure extends HttpResponseTransformer {
        @Override
        protected Response doTransform(Request request, Response response, FileSource fileSource, Parameters parameters) {
            if (new Random().nextBoolean()) {
                return Response.Builder
                        .like(response)
                        .but()
                        .status(500)
                        .headers(noHeaders())
                        .body("Server error!")
                        .build();
            } else {
                return response;
            }
        }
    
        @Override
        public String getName() {
            return getClass().getSimpleName();
        }
    }
  4. Build the project ./mvnw clean install
  5. Copy target/trafficparrot-sdk-workspace-x.y.z.jar to directory trafficparrot-enterprise-release-x.y.z/lib/virtualservice-x.y.z
  6. Look for property trafficparrot.http.responsetransformers in trafficparrot.properties and add your new class to the list of extension classes there. (Why do I have to edit the extensions properties every time?)
  7. Stop Traffic Parrot
  8. Start Traffic Parrot
  9. If the name of the class you have created is RandomServerFailure the extension you will use in response templates will be automatically called {{randomServerFailure}}
  10. Edit an existing mapping and put {{randomServerFailure}} anywhere in the response body.
  11. Make a few requests to the virtual service
  12. The response you receive should randomly fail, as defined in the response transformer RandomServerFailure.

Custom JMS response transformers

Traffic Parrot allows for creating custom JMS response transformers. They allow for altering any part of the JMS response message in any way you like, and have access to the request data.

If you would like to add a new JMS response transformer, have a look at the following example:
  1. Download and open the SDK workspace project in an IDE like IntelliJ IDEA or Eclipse
  2. Explore the project and the Java classes available in the SDK. They provide example usages of JMS response transformers. Look for usages of JmsResponseTransformer and TextJmsResponseTransformer. Have a look at both main and test classes.
  3. Create a new extension class based on the examples provided in the SDK (by extending TextJmsResponseTransformer class). For example:
    package com.trafficparrot.sdk.example.jms;
    
    import com.github.tomakehurst.wiremock.common.Json;
    import com.trafficparrot.sdk.jms.Destination;
    import com.trafficparrot.sdk.jms.JmsResponse;
    import com.trafficparrot.sdk.jms.JmsResponseBuilder;
    import com.trafficparrot.sdk.jms.TextJmsResponseTransformer;
    
    import javax.jms.JMSException;
    import javax.jms.TextMessage;
    
    public class ChooseResponseQueueBasedOnRequestMessageBody extends TextJmsResponseTransformer {
        @Override
        protected JmsResponse doTransform(Destination requestDestination, TextMessage requestMessage, JmsResponse response) throws JMSException {
            Req payment = Json.read(requestMessage.getText(), Req.class);
            String newDestinationName;
            if ("foo".equals(payment.requestField)) {
                newDestinationName = "response_queue_1";
            } else if ("bar".equals(payment.requestField)) {
                newDestinationName = "response_queue_2";
            } else {
                logger.error("Destination not configured for req.requestField '" + payment.requestField + "'");
                throw new UnsupportedOperationException(payment.requestField);
            }
            logger.info("Redirecting message to " + newDestinationName);
    
            return new JmsResponseBuilder()
                    .like(response)
                    .withDestination(new Destination(newDestinationName, response.destination.type))
                    .build();
        }
    }
    
    class Req {
        public String requestField;
    }
  4. Build the project ./mvnw clean install
  5. Copy target/trafficparrot-sdk-workspace-x.y.z.jar to directory trafficparrot-enterprise-release-x.y.z/lib/external
  6. Look for property trafficparrot.jms.responsetransformers in trafficparrot.properties and add your new class to the list of extension classes there. (Why do I have to edit the extensions properties every time?)
  7. Stop Traffic Parrot
  8. Start Traffic Parrot
  9. Edit an existing JMS mapping and select ChooseResponseQueueBasedOnRequestMessageBody from the "Response transformer" dropdown.
  10. Start the JMS virtual service in replay mode and send a JMS request with content {"requestField": "foo"}
  11. The response message should be sent to queue response_queue_1
  12. Send a JMS request with content {"requestField": "bar"}
  13. The response message should be sent to queue response_queue_2

Video

The following video describes usage of Traffic Parrot extensions in version 3.7.x and below. Note: property names and class names have changed since.
If you cannot see a video frame below please download it here