testinggospels / camouflage

Camouflage is a backend mocking tool for HTTP, gRPC, Websockets and Thrift protocols, which helps you carry out your front end prototyping, unit testing, functional/performance testing in silos, in absence of one or more Microservices/APIs.
https://testinggospels.github.io/camouflage/
MIT License
278 stars 26 forks source link

Request body becomes empty for Content-Type: text/xml;charset=UTF-8 #187

Closed woodwo closed 2 years ago

woodwo commented 2 years ago

Describe the bug I am mocking SOAP 1.1 server. My code under test set header to Content-Type: text/xml;charset=UTF-8 (as in spec). With such header my mock body parsing is not working, response.body is empty in logs.

To Reproduce Steps to reproduce the behavior:

  1. Mock File Content
    
    {{log request.body}}
    HTTP/1.1 200 OK

{ "cid": "{{capture from='body' using='regex' selector='(\d+)<\/customerId>'}}" }

2. Folder Structure `test\POST.mock`
3. Put xml into bug1.xml: 

<?xml version="1.0"?>

1000000000 ``` 4. Execute `curl -vv -H 'Content-Type: text/xml;charset=UTF-8' --data-binary "@bug1.xml" -X POST http://localhost:8080/test` against this mock. 5. Error Stack Trace ``` camouflage | 2022-09-01 15:20:37 debug: ERROR: No match found for specified regex (\d+)<\/customerId> camouflage | 2022-09-01 15:20:37 debug: Using new line as \n camouflage | 2022-09-01 15:20:37 debug: Response Status set to 200 camouflage | 2022-09-01 15:20:37 debug: Generated Response { "cid": "No match found."} camouflage | 2022-09-01 15:20:38 debug: HTTP POST /test :: Query Parameters: {} | Request Headers {"host":"localhost:8080","user-agent":"curl/7.68.0","accept":"*/*","content-type":"text/xml;charset=UTF-8","content-length":"214"} | Request Body {} ``` **Expected behavior** customerId is recognised. It also pass when I changed header to `Content-Type: application/x-www-form-urlencoded` **Desktop (please complete the following information):** - OS: Ubuntu 20.04.4 LTS, environment from docker-compose (shubhendumadhukar/camouflage-filemanager:latest)
woodwo commented 2 years ago

I can workaround it by adding app.use(express.text({type: () => {return true}})); after https://github.com/testinggospels/camouflage/blob/develop/src/index.ts#L46

But it surely not the best option as it should be (as I am not the JS developer nor have the express insights =).

shubhendumadhukar commented 2 years ago

That seems like a valid solution. By using express.text() you are parsing the request body into a plain string. If you want to continue using this solution, you may want to inject it as an external middleware.

  1. Create a file middleware.js at the root of your camouflage project.
  2. Install express globally. npm i -g express
  3. Export NODE_PATH. If you are on mac/linux, run
    export NODE_PATH=`npm root -g`

    If you are on windows

    npm root -g
    set NODE_PATH="output of previous command"
  4. Modify middleware.js file as follows:
    var require = global.require || global.process.mainModule.constructor._load;
    (() => {
    const express = require('express')
    this.app.use(express.text({ type: () => { return true } }));
    this.app.use("/", this.allRoutes);
    })();

    For more details on middleware injection, refer to the documentation.

woodwo commented 2 years ago

Now it seems clear from docs that it can be used in my case too. Issue should be closed now! Thank you for your help.