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

Json in postBody for request object #8

Closed
moleksyuk opened this issue Nov 1, 2012 · 18 comments
Closed

Json in postBody for request object #8

moleksyuk opened this issue Nov 1, 2012 · 18 comments
Labels

Comments

@moleksyuk
Copy link
Contributor

Hi,

Could you add example to YAML configuration sample how to define json in post body?(if it's possible)
Example

  • request:
    method: POST
    url: /some/uri?param=true&anotherParam=false
    headers:
    content-type: application/json
    postBody: {
    "attr1":"value1",
    "attr2":"value2"
    }
@azagniotov
Copy link
Owner

Sure. Will do! thank you.

In the meanwhile you can do something like that if you are having problem:

request: 
   method: POST 
   url: /some/uri?param=true&anotherParam=false 
   headers: content-type: application/json 
   postBody: >
      { "attr1":"value1", "attr2":"value2" }

@moleksyuk
Copy link
Contributor Author

Unfortunately it doesn't work for me. I've figured out it works with such definition(in single quote):
postBody: '{ "attr1":"value1", "attr2":"value2" }'

It would be great to be able define file parameter for request object as response has. Because most json serializers output such json representation:
{
"attr1": "value1",
"attr2": "value2"
}

And stubby won't match request for single-line view of json to multi-line view.

@azagniotov
Copy link
Owner

Did you try putting the ">" sign after postBody, and keeping the JSON indented on the new line as per example?

postBody: >
      { "attr1":"value1", "attr2":"value2" }

@azagniotov
Copy link
Owner

When you say: "it does not work for me", what do you mean? You get errors during the YAML parse time or when you POSTing, you cant match the stubbed request?

Can you please provide more information.

Cheers

@mrak mrak closed this as completed Nov 1, 2012
@mrak mrak reopened this Nov 1, 2012
@azagniotov
Copy link
Owner

Hi Misha,

I have implemented file in request object. Just get the version stubby4j-1.0.23-SNAPSHOT.jar from artifacts or build the project your self. Keep on mind that queryParams is now query and postBody is now post.

Please refer to YAML sample under docs

Cheers

@moleksyuk
Copy link
Contributor Author

Hi @azagniotov ,

Thanks for your quick enhancement with supporting file attribute in request object. It works perfect.

But there is an issue with json specifying directly in request definition.

Steps to reproduce:
1.Define such request/response:

-  request:
      method: POST
      url: /test/url
      headers:
         content-type: application/json
      post: >
         {
            "name": "value",
            "param": "description"
         }

   response:
      headers:
         content-type: application/json
      status: 200
      body: >
         {"status" : "OK"}

2.Example of test code:

 @Test
  public void test1() throws Exception
  {
    // GIVEN
    class Foo {
      private String name = "value";
      private String param = "description";

      public String getName() {
        return name;
      }
      public String getParam() {
        return param;
      }
    }

    String content = TestUtils.JSON_OBJECT_MAPPER.writeValueAsString(new Foo());

    //configuration from step 1 loaded from file
    String config = messages.getMessage("test_configuration");
    final ClientRequestInfo adminRequest =
        new ClientRequestInfo(HttpMethods.POST, "/stubdata/new", "localhost", ADMIN_PORT, config);
    INTEGRATION_SERVER.makeRequestWith(adminRequest);

    // WHEN
    DefaultHttpClient httpclient = new DefaultHttpClient();

    HttpPost httpPost = new HttpPost("http://localhost:8882/test/url");
    httpPost.setHeader(CONTENT_TYPE, "application/json");
    httpPost.setHeader(ACCEPT, "application/json");
    httpPost.setEntity(new StringEntity(content, "UTF-8"));

    HttpResponse response = httpclient.execute(httpPost);
    // THEN
    String actualContent = RestTestUtils.toStringAndClose(response.getEntity().getContent());
    System.out.println("Response Content:" + actualContent);
  }

3.Response:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=ISO-8859-1"/>
<title>Error 404 No data found for POST request at URI /test/url for post data: {
  "name" : "value",
  "param" : "description"
}</title>
</head>
<body>
<h2>HTTP ERROR: 404</h2>
<p>Problem accessing /test/url. Reason:
<pre>    No data found for POST request at URI /test/url for post data: {
  "name" : "value",
  "param" : "description"
}</pre></p>
<hr /><i><small>Powered by Jetty://</small></i>

If you change request/response definition in such way and execute code above - everything works OK.

-  request:
      method: POST
      url: /test/url
      headers:
         content-type: application/json
      file: path/to/post/file/test.txt
   response:
      headers:
         content-type: application/json
      status: 200
      body: >
         {"status" : "OK"}

where test.txt contains:

{
  "name" : "value",
  "param" : "description"
}

@moleksyuk
Copy link
Contributor Author

We have found with @OleksandrBerezianskyi that problem is located in YamlScanner org.yaml.snakeyaml.scanner.ScannerImpl.scanLineBreak().

It transforms '\r\n' to '\n'.
So, request body from request definition is

{\n  "name" : "value",\n "param" : "description"\n }\n

And posted body from code is:

{\r\n  "name" : "value",\r\n "param" : "description"\r\n }\r\n

@OleksandrBerezianskyi
Copy link
Contributor

Hi Alexander Zagniotov,

In other words: SnakeYaml parser ruins multiline strings.
There are 2 issues:

That is why request/response from file works like a charm.

@azagniotov
Copy link
Owner

Hi,

Yeah I was afraid that this might happen. I was sceptical about this way of raw string comparison.
I will try to strip all the white spaces from post body at the time of comparison and see what happens.

Btw, stubby4j is now on maven central

@OleksandrBerezianskyi
Copy link
Contributor

I think stripping white spaces is not an option as well because sometimes you want a message with a know number of spaces (e.g. your server talks YAML).
I think you should just state in documentation that preferable way to configure multiline request/response body is a file or even check posted YAML afterwards.

@azagniotov
Copy link
Owner

What I meant is: you can still specify a multi line JSON POST body in the request in the YAML. Respectively, you can still POST a multiline JSON.

At the time of comparison, in other words in the equals() of StubRequest I will strip white spaces from POST body in order to reduce the chances of failing due to a missing or an extra \r\n... In fact, i can be comparing MD5 hashes of POSTed and expected POST after stripping...
Does it make sense?

Thanks for your comments, I will tweak the docs

@OleksandrBerezianskyi
Copy link
Contributor

Let's say that you are posting YAML to server in HTTP request and server answers with YAML back to you in HTTP response.
In this case you want to be sure that posted YAML had exactly same structure as you have configured because number of white spaces will affect result.

Of course you can change comparison mechanism to something that will skip only line separators by either replacing them in both sources with some common line separator (more strict option) or by removing them out completely (less strict option). This will result in more broad match which still should be quite accurate.

@azagniotov
Copy link
Owner

Yep, you got it right.

@azagniotov
Copy link
Owner

Do you really want to care about white space in the configured structure?
I think the most important is the JSON content, for example:

post: >
         {
            "id" :

            "8",
            "description" :
            "sweet butter"



         }

and

{"id" : "8", "description"    : "sweet butter"}

should return positive match when comparing

{"id":"8","description": "sweetbutter"}

and

{"id":"8","description": "sweetbutter"}

@OleksandrBerezianskyi
Copy link
Contributor

My point is that there are many formats besides json. Theoretically, stubbed server can produce/consume XML, JSON, YAML, HTML, etc. More over your json strings can contain a white space like

{"id":"8","description": "spaces  must  be preserved here"}

So, it would be nice to configure matching mechanism with some options like:

  • strict match
  • don't match line separators
  • don't match any white space characters

@azagniotov
Copy link
Owner

I think it would be better at this stage to simply advise users to use file for large post content that inconvenient to configure as one-liners. Since you two already confirmed that file in request works perfectly, I think it the simplest solution ATM

@OleksandrBerezianskyi
Copy link
Contributor

100% agree with you

@isa
Copy link
Collaborator

isa commented Nov 2, 2012

I'd think making Stub server dumb from the response type would be ideal. We cannot expect Stub server to recognize all sorts of response bodies. File is definitely the way to go here.

We should close this ticket.

@isa isa closed this as completed Nov 2, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants