znsio / specmatic

Turn your contracts into executable specifications. Contract Driven Development - Collaboratively Design & Independently Deploy MicroServices & MicroFrontends.
https://specmatic.io
MIT License
275 stars 51 forks source link

2 json files getting created when creating contract from existing application using Inbound proxy #350

Closed avinashkandimalla closed 1 year ago

avinashkandimalla commented 2 years ago

Hi,

I am new to Specmatic and started to use the library. I am going through the documentation and trying to generate the contracts from an existing application using Inbound proxy. When I try this, I am seeing 2 requests being generated(1. with path having localhost and another with out the domain in the path) for each api call made.

When I tried using the same contracts as stubs, the response is always being returned dynamically, instead of the data from the json file.

tried by modifying the headers and other stuff but nothing worked. I couldn't find any community channel to reach for help. So trying to post it here. Can some one please help me on this. or redirect me to some community channel where I can get some help on the same and get unblocked.

Thanks

joelrosario commented 2 years ago

Hey @avinashkandimalla , can you attach the files that Specmatic is generating?

avinashkandimalla commented 2 years ago

Hi @joelrosario

Please find attached the spec file and data files generate contracts.zip

thanks

avinashkandimalla commented 2 years ago

Hi @joelrosario

By any chance,were you able to look in to this?

Thanks, Avinash k

joelrosario commented 2 years ago

Hey @avinashkandimalla let me explain what's happening.

1 — The generated stub file and contract contain all the headers that the Specmatic proxy saw. This is because Specmatic cannot differentiate between which headers are important and what are not. Usually there are just a few headers used in the application's business logic, or auth, but the HTTP client sends quite a few more (e.g. Accept, Content-Type, etc).

We can usually trust the tools to handle the standard headers, and only need to nail down any extra non-standard headers required by the application's logic. We recommend that you declare only the non-standard headers needed by your application. Specmatic will validate the headers you have declared, and ignore the rest. JSON and XML content types are implicitly understood by Specmatic and need not be declared.

Point for future improvement: Specmatic needs to put all the headers in both contract and stub file, so that the contract can start seamlessly after being generated.

2 — The stub and contract file generated by Specmatic are placed in the same directory. This means that for the stub file to load with the contract, you need to do a bit more work. Since the contract generated is proxy_generated.spec, create a directory named proxy_generated_data, and move the stub0.json file into it.

Your directory should now look like this: |— proxy_generated.spec |— proxy_generated_data/ | |— stub0.json

Specmatic implicitly looks inside _data when stubbing out a contract.

Now start specmatic in stub mode, and it will load the contract and it's stub file.

3 — I'm not sure why two stub files got generated. I was not able to replicate this problem. My hypothesis is that somehow two requests went to Specmatic. If you can replicate the issue, please provide the steps here.

avinashkandimalla commented 2 years ago

Hi @joelrosario

for point 2 : Yes, I am following the same mentioned in the documentation. created the folder with proxy_generated_data and placed the json files inside the folder. For sending the files for reference I have placed all of them in single folder and zipped here.

for point 1: Will try to remove the non standard headers from the contract and will check if the static data is being loaded. But Can you please explain me on what conditions Specmatic decides to return the dynamic data instead of the data from json file.(I am guessing if any of the api endoint details from application doesn't match the contract parameters then Specmatic returns dynamic data instead of the static data present in the json file, Can you please correct me If my understanding is wrong).

for point 3 : Yes Joel, it is reproducible every time for me. Below are the steps I followed

  1. I have my application running locally and my api service is running on port 32000
  2. Now I have set the Specmatic proxt as below (specmatic proxy --target http://127.0.0.1:32000 ./contracts)
  3. Now I have set the proxy settings in post man
  4. and since Specmatic proxy is running on localhost on port 9000 I am hitting my application endpoint vai proxy (http://localhost:9000/service/ent_id/v2/flow/load_login_page)
  5. I can see 2 api request recorded in Specmatic.

Looks like 2 request are being generated when I use postman with proxy setting's,I tried by proxying from curl and only one request is being generated.

When I run Specmatic in stub mode I see no error and also the file is being loaded with out any error

specmatic stub "contracts/proxy_generated.spec" --host="localhost" --port="32000"
Loading contracts/proxy_generated.spec
  Loading stub expectations from /home/avinash.kandimalla/contracts/proxy_generated_data
  Reading the following stub files:
    /home/avinash.kandimalla/contracts/proxy_generated_data/stub0.json
Stub server is running on http://localhost:32000. Ctrl + C to stop.

Now when I hit the endpoint to get the response from specmatic using curl, it is still returning the dynamic data instead of stub file data.

{ "requestTime": "2021-9-15 11:31:36.818", "http-request": { "path": "/service/ent_id/v2/flow/load_login_page", "method": "POST", "headers": { "Host": "127.0.0.1:32000", "sec-ch-ua": "\"Chromium\";v=\"92\", \" Not A;Brand\";v=\"99\", \"Google Chrome\";v=\"92\"", "sec-ch-ua-mobile": "?0", "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36", "Content-Type": "text/plain; charset=UTF-8", "Accept": "*/*", "Origin": "https://quickolabs.com", "Sec-Fetch-Site": "same-origin", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Dest": "empty", "Referer": "https://quickolabs.com/local/", "Accept-Language": "en-US,en;q=0.9", "Cookie": "wfx_unq=Z2pHvNN8y5XlTtsu; __zlcmid=15dkGQzy7jb76mf; _gcl_au=1.1.491115053.1629864798; _vwo_uuid=D3E269DD6E1D45A2A7D7B724482ACFF0B; _vwo_ds=3%3Aa_1%2Ct_0%3A0%241629864798%3A71.35740277%3A%3A%3A4_1%2C3_1%3A1; _fbp=fb.1.1629864799247.249364295; _vis_opt_s=7%7C; _ga=GA1.1.1433087887.1629864799; _ga_LRK5E91CSR=GS1.1.1633528756.25.1.1633529840.0; amplitude_id_710c8418e5d8c25f0566d8be33182fabquickolabs.com=eyJkZXZpY2VJZCI6IjQ4ZDkwMTBjLTI5MTAtNDM1Ni04ZmQ3LWQ1YWIzY2QwYjY5YVIiLCJ1c2VySWQiOiJhYzAzOTY0MC0yYzFlLTExZWMtYjRjNi03MjkwNzZkZjFjZTUiLCJvcHRPdXQiOmZhbHNlLCJzZXNzaW9uSWQiOjE2MzQxNTE3NjcyNzQsImxhc3RFdmVudFRpbWUiOjE2MzQxNTE3NzEzMTAsImV2ZW50SWQiOjIyMzEsImlkZW50aWZ5SWQiOjIyMywic2VxdWVuY2VOdW1iZXIiOjI0NTR9; amplitude_id_dba41884155ddd5509e94e497a2194a8quickolabs.com=eyJkZXZpY2VJZCI6ImVhMTFkMTA4LThkY2MtNGMyOS1hNzZkLWIwOGIyYWE5N2I2Y1IiLCJ1c2VySWQiOiJhYzAzOTY0MC0yYzFlLTExZWMtYjRjNi03MjkwNzZkZjFjZTUiLCJvcHRPdXQiOmZhbHNlLCJzZXNzaW9uSWQiOjE2MzQyNzYxMDcyMjksImxhc3RFdmVudFRpbWUiOjE2MzQyNzYxMDcyMjksImV2ZW50SWQiOjg3OCwiaWRlbnRpZnlJZCI6ODAsInNlcXVlbmNlTnVtYmVyIjo5NTh9", "UNIQUE_ID": "YWkZQPbjJ2-3RWOQTu9v-AAAAFE", "X-Forwarded-For": "127.0.0.1", "X-Forwarded-Host": "quickolabs.com", "X-Forwarded-Server": "whatfix.com", "Connection": "Keep-Alive", "content-length": "16" }, "body": { "name": "local" } }, "http-response": { "status": 200, "body": { "result": "SUNKM", "detail": { "login_type": "WCJSO", "name": "EMQQX", "open": true } }, "status-text": "OK", "headers": { "Date": "XDRNN", "Transfer-Encoding": "PPOQM", "X-Specmatic-Result": "success", "Content-Type": "application/json" } }, "responseTime": "2021-9-15 11:31:36.818" }, Please let me know if I am missing any of the steps.

Thanks in advance

joelrosario commented 2 years ago

For point 1: Your understanding is correct. If we want Specmatic to display an error, use the --strict flag when running the specmatic stub command.

For point 3, thankyou for providing this info I will try these steps to reproduce the issue and get back.

joelrosario commented 2 years ago

@avinashkandimalla I was able to reproduce the issue.

Specmatic proxy can be used in two ways.

  1. Transparent proxy, in which you do not have to configure proxy settings in Postman. Postman is basically not even aware that Specmatic is acting as a proxy. For this, use --target and provide a base url. All requests are forwarded to the base url, and responses from it are returned back.
  2. HTTP proxy, in which you have to configure Postman's proxy settings, and you start the specmatic proxy without providing --target.

Your steps do both, providing a target as well as configuring Postman's proxy settings which is not the intended use of the --target parameter.

The first option functions as intended. I am seeing some issues with the second option which I am investigating.

avinashkandimalla commented 2 years ago

thanks for the input's @joelrosario

Will try to do the setup using option 1

joelrosario commented 1 year ago

Hi @avinashkandimalla, it's been a while. Hope my answer was helpful.

We've updated the documentation on using the proxy, based on customer's usage. We are now recommending option 1 in the comment above. The documentation also has been updated, and the recommended use of the proxy feature is now described here.

I'm closing this issue for now. But if you have any further questions on this topic, please reopen it and ask away! And maybe take another look at Specmatic, as we've added a whole lot of new features since this ticket was opened!

Cheers, Joel