Skip to content

Response Templating

Stef Heyenrath edited this page Dec 2, 2018 · 29 revisions

Response Templating

Response headers and bodies can optionally be rendered using Handlebars.Net templates. This enables attributes of the request to be used in generating the response e.g. to pass the value of a request ID header as a response header or render an identifier from part of the URL in the response body. To use this functionality, add .WithTransformer() to the response builder.

Example:

var server = FluentMockServer.Start();
server
  .Given(
    Request.Create().WithPath("/some/thing").UsingGet()
  )
  .RespondWith(
    Response.Create()
      .WithStatusCode(200)
      .WithHeader("Content-Type", "text/plain")
      .WithBody("Hello world! Your path is {{request.path}}.")
      .WithTransformer()
  );

The request model

The model of the request is supplied to the header and body templates. The following request attributes are available:

  • request.url - URL path and query
  • request.absoluteurl - URL path and query (absolute)
  • request.path - URL path
  • request.absolutepath - URL path (absolute)
  • request.PathSegments.[<n>] - URL path segment (zero indexed) e.g. request.PathSegments.[2]
  • request.AbsolutePathSegments.[<n>] - URL absolute path segments (zero indexed) e.g. request.AbsolutePathSegments.[2]
  • request.query.<key>- First value of a query parameter e.g. request.query.search
  • request.query.<key>.[<n>]- nth value of a query parameter (zero indexed) e.g. request.query.search.[5]
  • request.headers.<key> - First value of a request header e.g. request.headers.X-Request-Id
  • request.headers.[<key>] - Header with awkward characters e.g. request.headers.[$?blah]
  • request.headers.<key>.[<n>] - nth value of a header (zero indexed) e.g. request.headers.ManyThings.[1]
  • request.cookies.<key> - Value of a request cookie e.g. request.cookies.JSESSIONID
  • request.body - Request body text as string
  • request.bodyAsJson - Request body as dynamic Json Object. Note that the request must contain the header Content-Type with value application/json!

Handlebars helpers

All of the standard helpers (template functions) provided by the C# Handlebars implementation plus all of the string helpers are available e.g. {{capitalize request.query.search}}

Generate Random Data Support

It's possible to return random data using the Random Handlebars function.

Random Text

Example: to generate a random string between 8 and 20 characters, use this code in C#:

var server = FluentMockServer.Start();
server
    .Given(Request.Create().WithPath("/random").UsingGet())
    .RespondWith(Response.Create()
        .WithHeader("Content-Type", "application/json")
        .WithBodyAsJson(
            Text = "{{Random Type=\"Text\" Min=8 Max=20}}",
        )
        .WithTransformer()
    );

Example: to generate a random string using a Regex pattern, use this code in C#:

var server = FluentMockServer.Start();
server
    .Given(Request.Create().WithPath("/random-regex").UsingGet())
    .RespondWith(Response.Create()
        .WithHeader("Content-Type", "application/json")
        .WithBodyAsJson(
            Text = "{{Xeger \"[1-9][0-9]{3}[A-Z]{2}\"}",
        )
        .WithTransformer()
    );

Random (all supported randomizers)

You can use the powerful Regular Expression string generator based on Fare - Finite Automata and Regular Expressions.

  • Text Regex Pattern: "{{Xeger Pattern=\"[1-9][0-9]{3}[A-Z]{2}"}}"

Besides a random text string, it's also possible to generate this random data:

  • Integer: "{{Random Type=\"Integer\" Min=100 Max=999}}"
  • Guid: "{{Random Type=\"Guid\"}}"
  • City: "{{Random Type=\"City\"}}"
  • Country: "{{Random Type=\"Country\"}}"
  • First Name: "{{Random Type=\"FirstName\" Male=false Female=true}}"
  • Email Address: "{{Random Type=\"EmailAddress\"}}"
  • Text Words: "{{Random Type=\"TextWords\" Min=10 Max=20}}"
  • Text Regex Pattern: "{{Random Type=\"TextRegex\" Pattern=\"[1-9][0-9]{3}[A-Z]{2}"}}"
  • Text Lorum Ipsum: "{{Random Type=\"TextIpsum\" Paragraphs=2}}"
  • String List: "{{Random Type=\"StringList\" Values=[\"a\", \"b\", \"c\"]}}"
  • IPv4 Address: "{{Random Type=\"IPv4Address\"}}"
  • IPv6 Address: "{{Random Type=\"IPv6Address\" Min = "0000:0001:0000:0000:0020:ff00:0042:8000", Max = "2001:0db8:0120:0000:0030:ff00:aa42:8329"}}"
  • MAC Address: "{{Random Type=\"MACAddress\"}}"
  • For more details on the supported random data types, see RandomDataGenerator.Net;

Note: instead of using \" in above examples, you can also use '.

JsonPath support

JsonPath support is also present (internal logic is based on Newtonsoft.Json).

Two functions are present:

  1. JsonPath.SelectToken
  2. JsonPath.SelectTokens

JsonPath.SelectToken

This can be used in C# like:

var server = FluentMockServer.Start();
server
    .Given(Request.Create().WithPath("/jsonpathtestToken").UsingPost())
    .RespondWith(Response.Create()
        .WithHeader("Content-Type", "application/json")
        .WithBody("{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}")
        .WithTransformer()
    );

Or using the admin mapping file:

{
    "Request": {
        "Path": {
            "Matchers": [
                {
                    "Name": "WildcardMatcher",
                    "Pattern": "/jsonpathtestToken"
                }
            ]
        },
        "Methods": [
            "post"
        ]
    },
    "Response": {
        "Body": "{{JsonPath.SelectToken request.body \"$.Manufacturers[?(@.Name == 'Acme Co')]\"}}",
        "UseTransformer": true,
        "Headers": {
            "Content-Type": "application/json"
        }
    }
}

Note that also replacing values in a Json Object and returning a the body as Json is supported, to use this, use a mapping file like this:

{
  "Request": {
    "Path": {
      "Matchers": [
        {
          "Name": "WildcardMatcher",
          "Pattern": "/test"
        }
      ]
    },
    "Methods": [
      "post"
    ]
  },
  "Response": {
    "BodyAsJson": {
      "path": "{{request.path}}",
      "result": "{{JsonPath.SelectToken request.bodyAsJson \"username\"}}"
    },
    "UseTransformer": true,
    "Headers": {
      "Content-Type": "application/json"
    }
  }
}
Clone this wiki locally