Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

templating using Request.Body jsonpath will replace characters with HTML character encodings #963

Open
MartynDavis opened this issue Feb 15, 2021 · 2 comments

Comments

@MartynDavis
Copy link

MartynDavis commented Feb 15, 2021

Description of the bug

When templating is enabled for JSON request/response, if the request body is:

{ "name": "O'Reilly" }

And the response body is set to:

{ "name": "{{ Request.Body 'jsonpath' '$.name' }}"

The Hoverfly will return:

{ "name": "O@apos;Reilly" }

Steps to reproduce the issue

Import attached Hoverfly simulation file hoverfly-templating-example.json, and set Hoverfly to simulate.

Templated POST response is:

{
  "id": {{ randomIntegerRange 100 199 }},
  "name": "{{ Request.Body 'jsonpath' '$.name' }}",
  "username": "{{ Request.Body 'jsonpath' '$.username' }}",
  "email": "{{ Request.Body 'jsonpath' '$.email' }}",
  "address": {
    "street": "{{ Request.Body 'jsonpath' '$.address.street' }}",
    "suite": "{{ Request.Body 'jsonpath' '$.address.suite' }}",
    "city": "{{ Request.Body 'jsonpath' '$.address.city' }}",
    "zipcode": "{{ Request.Body 'jsonpath' '$.address.zipcode' }}",
    "geo": {
      "lat": "{{ Request.Body 'jsonpath' '$.address.geo.lat' }}",
      "lng": "{{ Request.Body 'jsonpath' '$.address.geo.lng' }}"
    }
  },
  "phone": "{{ Request.Body 'jsonpath' '$.phone' }}",
  "website": "{{ Request.Body 'jsonpath' '$.website' }}",
  "company": {
    "name": "{{ Request.Body 'jsonpath' '$.company.name' }}",
    "catchPhrase": "{{ Request.Body 'jsonpath' '$.company.catchPhrase' }}",
    "bs": "{{ Request.Body 'jsonpath' '$.company.bs' }}"
  }
}

Execute the non-proxied POST:

curl  --request POST --data @post-data.json --header "Content-type: application/json" --header "Accept: application/json" http://jsonplaceholder.typicode.com/users

post-data.json contains the following:

{
  "name": "Stephanie Hackett DVM",
  "username": "kiara.langworth",
  "email": "[email protected]",
  "address": {
    "street": "3027 O'hara Lane",
    "suite": "Penthouse",
    "city": "Johnstonmouth",
    "zipcode": "3341",
    "geo": {
      "lat": "14.511382",
      "lng": "46.748701"
    }
  },
  "phone": "0449-415-927",
  "website": "www.hamilton-ohara.net",
  "company": {
    "name": "O'connell-Tillman",
    "catchPhrase": "Synergized tangible parallelism",
    "bs": "facilitate killer bandwidth"
  }
}

Which will return:

{
  "name": "Stephanie Hackett DVM",
  "username": "kiara.langworth",
  "email": "[email protected]",
  "address": {
    "street": "3027 O'hara Lane",
    "suite": "Penthouse",
    "city": "Johnstonmouth",
    "zipcode": "3341",
    "geo": {
      "lat": "14.511382",
      "lng": "46.748701"
    }
  },
  "phone": "0449-415-927",
  "website": "www.hamilton-ohara.net",
  "company": {
    "name": "O'connell-Tillman",
    "catchPhrase": "Synergized tangible parallelism",
    "bs": "facilitate killer bandwidth"
  },
  "id": 11
}

Execute the proxied POST:

curl  --proxy http://localhost:8500 --request POST --data @post-data.json --header "Content-type: application/json" --header "Accept: application/json" http://jsonplaceholder.typicode.com/users

Which will return:

{
  "id": 192,
  "name": "Stephanie Hackett DVM",
  "username": "kiara.langworth",
  "email": "[email protected]",
  "address": {
    "street": "3027 O'hara Lane",
    "suite": "Penthouse",
    "city": "Johnstonmouth",
    "zipcode": "3341",
    "geo": {
      "lat": "14.511382",
      "lng": "46.748701"
    }
  },
  "phone": "0449-415-927",
  "website": "www.hamilton-ohara.net",
  "company": {
    "name": "O'connell-Tillman",
    "catchPhrase": "Synergized tangible parallelism",
    "bs": "facilitate killer bandwidth"
  }
}

The address.street and company.name values contain @apos; instead of ' (single quote).

Observed result

{{ Request.Body 'jsonpath' '$.address.street' }} returns 3027 O'hara Lane
{{ Request.Body 'jsonpath' '$.company.name' }} returns O'connell-Tillman

Expected result

{{ Request.Body 'jsonpath' '$.address.street' }} returns 3027 O'hara Lane
{{ Request.Body 'jsonpath' '$.company.name' }} returns O'connell-Tillman

Attached files.zip contains:

$ hoverctl version

+----------+-------------+
| hoverctl | master-3593 |
| hoverfly | v1.3.1      |
+----------+-------------+
  • hoverfly-templating-example.json - example simulation file
  • post-data.json - curl POST data

files.zip

@MartynDavis MartynDavis changed the title templating using Request.Body jsonpath will replace characters ith HTML character encodings templating using Request.Body jsonpath will replace characters with HTML character encodings Feb 15, 2021
@tommysitu tommysitu added bug and removed bug labels Feb 20, 2021
@tommysitu
Copy link
Member

tommysitu commented Feb 20, 2021

We use this library for templating: https://github.com/aymerick/raymond

According to the doc, if you need to unescaped value, you can triple the mustache {{{ 🧔

if you try this, it should work: { "name": "{{{ Request.Body 'jsonpath' '$.name' }}}"

@MartynDavis
Copy link
Author

MartynDavis commented Feb 23, 2021

Thank you @tommysitu for the solution.

Triple moustache it is.

I have attached hoverfly-templating-example-triple-moustache.json which is the original JSON file with the triple moustache solution.

With that said, Hoverfly does needs address the issues with escaping JSON when jsonpath is used within templating. Consider the case where double quotes and/or newlines are used within the request JSON. Using triple moustache in this instance does not address the issue as malformed JSON is returned.

Consider the file post-data-bad.json, which contains:

{
  "name": "Stephanie Hackett DVM",
  "username": "kiara.langworth",
  "email": "[email protected]",
  "address": {
    "street": "3027 O'hara Lane",
    "suite": "\"Penthouse\"",
    "city": "Johnstonmouth",
    "zipcode": "3341",
    "geo": {
      "lat": "14.511382",
      "lng": "46.748701"
    }
  },
  "phone": "0449-415-927",
  "website": "www.hamilton-ohara.net",
  "company": {
    "name": "O'connell-Tillman",
    "catchPhrase": "Synergized tangible parallelism\nEat tangerines",
    "bs": "facilitate killer bandwidth"
  },
  "id": 11
}

The suite property contains double quote and catchPhrase contains newline.

When the Hoverfly simulates the POST response, malformed JSON is returned:

curl  --proxy http://localhost:8500 --request POST --data @post-data-bad.json --header "Content-type: application/json" --header "Accept: application/json" http://jsonplaceholder.typicode.com/users

Data returned is:

{
  "id": 123,
  "name": "Stephanie Hackett DVM",
  "username": "kiara.langworth",
  "email": "[email protected]",
  "address": {
    "street": "3027 O'hara Lane",
    "suite": ""Penthouse"",
    "city": "Johnstonmouth",
    "zipcode": "3341",
    "geo": {
      "lat": "14.511382",
      "lng": "46.748701"
    }
  },
  "phone": "0449-415-927",
  "website": "www.hamilton-ohara.net",
  "company": {
    "name": "O'connell-Tillman",
    "catchPhrase": "Synergized tangible parallelism
Eat tangerines",
    "bs": "facilitate killer bandwidth"
  }
}

The double quote characters within the suite property are not escaped, and the newline within the catchPhrase property is not encoded as '\n'.

hoverfly-templating-example-triple-moustache.zip
post-data-bad.zip

@tommysitu tommysitu reopened this Feb 24, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants