salilbc / rest-assured

Automatically exported from code.google.com/p/rest-assured
0 stars 0 forks source link

Multiple same path parameters gets jammed  #169

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. When using same path parameters multiple times, only one is used. For 
example addlabel used multiple times:

given().log().all(true).
    pathParam("messageId", "149b9290-9514-11e1-a243-040cced3bd7a").
    pathParam("labelId1", "6").
    pathParam("labelId2", "7").
expect().
    statusCode(204).
when().
    put(REST_PATH + "/mailbox/message/{messageId}?addlabel={labelId1}&addlabel={labelId2}");

2.
3.

What is the expected output? What do you see instead?

Only one "addlabel" parameter passed to the server (addlabel=6), instead of 
both.

What version of the product are you using? On what operating system?

1.6.1. This problem appeared after upgrading from 1.4.

Please provide any additional information below.

After enabling DEBUG, I can see that RESTAssured logs correctly, but it changes 
when httpclient is reached:

Request method: PUT
Request 
path:   http://localhost:8080/rest/v2/domain.com/test/mailbox/message/149b9290-951
4-11e1-a243-040cced3bd7a?addlabel=7&addlabel=6
Request params: <none>
Query params:   <none>
Form params:    <none>
Path params:    messageId=149b9290-9514-11e1-a243-040cced3bd7a
                labelId1=7
                labelId2=6
                marker1=seen
Headers:        Content-Type=*/*

org.apache.httpcomponents.httpclient[org.apache.http.impl.conn.SingleClientConnM
anager] : Get connection for route HttpRoute[{}->http://localhost:8080]
org.apache.httpcomponents.httpclient[org.apache.http.impl.conn.DefaultClientConn
ectionOperator] : Connecting to localhost:8080
org.apache.httpcomponents.httpclient[org.apache.http.client.protocol.RequestAddC
ookies] : CookieSpec selected: best-match
org.apache.httpcomponents.httpclient[org.apache.http.client.protocol.RequestAuth
Cache] : Auth cache not set in the context
org.apache.httpcomponents.httpclient[org.apache.http.impl.client.DefaultHttpClie
nt] : Attempt 1 to execute request
org.apache.httpcomponents.httpclient[org.apache.http.impl.conn.DefaultClientConn
ection] : Sending request: PUT 
/rest/v2/domain.com/test/mailbox/message/149b9290-9514-11e1-a243-040cced3bd7a?ad
dlabel=6 HTTP/1.1
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> "PUT 
/rest/v2/domain.com/test/mailbox/message/149b9290-9514-11e1-a243-040cced3bd7a?ad
dlabel=6 HTTP/1.1[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> "Accept: 
*/*[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> 
"Content-Length: 0[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> "Host: 
localhost:8080[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> "Connection: 
Keep-Alive[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> 
"Accept-Encoding: gzip,deflate[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.wire] : >> "[\r][\n]"
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> PUT 
/rest/v2/domain.com/test/mailbox/message/149b9290-9514-11e1-a243-040cced3bd7a?ad
dlabel=6 HTTP/1.1
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> Accept: */*
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> 
Content-Length: 0
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> Host: 
localhost:8080
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> Connection: 
Keep-Alive
org.apache.httpcomponents.httpclient[org.apache.http.headers] : >> 
Accept-Encoding: gzip,deflate

Original issue reported on code.google.com by rus...@gmail.com on 3 May 2012 at 11:58

GoogleCodeExporter commented 9 years ago
Thanks for reporting

Original comment by johan.ha...@gmail.com on 8 May 2012 at 11:25

GoogleCodeExporter commented 9 years ago
I've fixed this in trunk now. Please verify by depending on version 
1.6.2-SNAPSHOT after having added the following repo:

<repositories>
        <repository>
            <id>sonatype</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots />
        </repository>
</repositories>

Original comment by johan.ha...@gmail.com on 23 May 2012 at 12:36

GoogleCodeExporter commented 9 years ago

Original comment by johan.ha...@gmail.com on 23 May 2012 at 12:37

GoogleCodeExporter commented 9 years ago
I just tried 1.6.2, unfortunately this bug still there. Changelog also 
describes different use case.

Problem is with parameters which have same name but different values (e.g. 
"param" below):

http://localhost/some/resource?param={val1}¶m={val2}¶m={val3}

Original comment by rus...@gmail.com on 17 Jun 2012 at 7:01

GoogleCodeExporter commented 9 years ago
Oh so I misunderstood what was going on. At least another bug was fixed. I'll 
reopen the issue.

Original comment by johan.ha...@gmail.com on 18 Jun 2012 at 5:40

GoogleCodeExporter commented 9 years ago
Simple "me too" comment, yeah I know.

Because of this bug I have to write tests that relies on correct HTTP behavior 
with plain HttpClient when all other tests are wrote using rest-assured, that's 
not pretty :-)

Thanks for taking this bug report into account.

Original comment by eskato...@gmail.com on 3 Sep 2013 at 12:01

GoogleCodeExporter commented 9 years ago
Please help out with a pull request if can!

Original comment by johan.ha...@gmail.com on 3 Sep 2013 at 12:32

GoogleCodeExporter commented 9 years ago
I can give it a try.
Could you point me where in the code you think the culprit is?

Original comment by eskato...@gmail.com on 3 Sep 2013 at 1:48

GoogleCodeExporter commented 9 years ago
Hmm not quite sure, I tried to look in the code briefly but I couldn't find an 
exact spot. Probably have to debug it in order to see what's causing it. I 
don't have the time to do this atm though so if you want to help out that would 
be really nice.

Original comment by johan.ha...@gmail.com on 3 Sep 2013 at 2:18

GoogleCodeExporter commented 9 years ago
I took another look at this issue and it appears that things are working OK 
when using queryParam("key", "value1", value2" ) or when using 
queryParam("key","value1").queryParam("key","value2") but NOT when using 
get("/path/to/rsrc?key=value1&key=value2").

Original comment by eskato...@gmail.com on 5 Sep 2013 at 2:09

GoogleCodeExporter commented 9 years ago
I might be wrong (didn't debug it, just followed the code, plus I have 0 
knowledge with Groovy, I use rest-assured with Java), but it seems the reason 
may be in usage of Map to store parsed URL parameters in 
extractRequestParamsIfNeeded function (RequestSpecificationImpl class):
---
private Map<String, Object> requestParameters
private Map<String, Object> queryParameters
<...>
private String extractRequestParamsIfNeeded(Method method, String path) {
    if(path.contains("?")) {
<...>
        def keyValueParams = allParamAsString.split("&");
        keyValueParams.each {
            <...>
            } else {
                theKey = keyValue[0]
                theValue = keyValue[1]
            }
            if(method == POST) {
                queryParameters.put(theKey, theValue)
            } else {
                requestParameters.put(theKey, theValue);
            }
        };
        <...>
---
I guess Map in Groovy, as in Java will override the previous value of the 
existing key, thus discarding multiple parameters with the same name, but with 
different values.

The full chain of events:
in RequestSpecificationImpl: get(path) -> applyPathParamsAndSendRequest(path) 
-> 
invokeFilterChain(path) 
-> it has those lines:
filters << new RootFilter()
def ctx = new FilterContextImpl(..., filters);
ctx.next(this, responseSpecification) 
-> last statement calls 
in FilterContextImpl next(...), which calls:
def next = filters.next() 
-> this refers to 
in RootFilter: filter(FilterableRequestSpecification requestSpecification, ...)
requestSpecification.sendRequest
-> which refers back to RequestSpecificationImpl
private def Response sendRequest(path, method, assertionClosure) {
        path = extractRequestParamsIfNeeded(method, path);
Note that this is a private function, that I couldn't find in the 
FilterableRequestSpecification interface or interfaces it extends, so I'm not 
even sure how it's called (I suppose private can be called still due to Groovy 
issue described here: http://jira.codehaus.org/browse/GROOVY-1875), but there's 
no other sendRequest function anywhere in the code, so it must be it.
-> 
finally that function calls in RequestSpecificationImpl 
extractRequestParamsIfNeeded, which splits the path and puts all parameters in 
the Map, as I specified at the top.

Original comment by kiril.st...@gmail.com on 27 Oct 2013 at 7:22

GoogleCodeExporter commented 9 years ago
I've now fixed this in master. Please try version 1.8.2-SNAPSHOT after having 
added the following maven repo:

<repositories>
        <repository>
            <id>sonatype</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots />
        </repository>
</repositories>

Thanks for your investigation, it really helped me pinpoint the problem.

Original comment by johan.ha...@gmail.com on 14 Nov 2013 at 9:48