djangid / rest-assured

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

Can't PUT to server byte[] with content type set #160

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1.
Run the following code:

    byte[] bytes = "Some Text".getBytes();
    given()
      .contentType("application/vnd.myitem+xml")
      .body(bytes)
    .put("http://localhost:8080/some/path/myitem/1");

(my real binary payload is larger which is partly why it's binary, but this 
demonstrates the principle)

What is the expected output? What do you see instead?
I expect a PUT to the server and corresponding response, instead I get the 
following stack trace:

No signature of method: 
com.jayway.restassured.internal.encoderregistry.RestAssuredEncoderRegistry.encod
eForm() is applicable for argument types: ([B) values: [[83, 111, 109, 101, 32, 
84, 101, 120, 116]] Possible solutions: encodeForm(java.lang.String), 
encodeForm(java.util.Map), encodeJSON(java.lang.Object), 
encodeStream(java.lang.Object), encodeText(java.lang.Object), 
encodeXML(java.lang.Object)

groovy.lang.MissingMethodException: No signature of method: 
com.jayway.restassured.internal.encoderregistry.RestAssuredEncoderRegistry.encod
eForm() is applicable for argument types: ([B) values: [[83, 111, 109, 101, 32, 
84, 101, 120, 116]]
Possible solutions: encodeForm(java.lang.String), encodeForm(java.util.Map), 
encodeJSON(java.lang.Object), encodeStream(java.lang.Object), 
encodeText(java.lang.Object), encodeXML(java.lang.Object)
at 
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.j
ava:54)
at 
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.j
ava:59)
at 
org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setGroovyObjectProperty(Script
BytecodeAdapter.java:533)
at 
com.jayway.restassured.internal.RequestSpecificationImpl$_sendHttpRequest_closur
e10.doCall(RequestSpecificationImpl.groovy:800)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at 
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaC
lass.java:273)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:886)
at groovy.lang.Closure.call(Closure.java:282)
at groovy.lang.Closure.call(Closure.java:295)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:425)
at groovyx.net.http.HTTPBuilder.request(HTTPBuilder.java:376)
at groovyx.net.http.HTTPBuilder$request.call(Unknown Source)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.sendHttpRequest(Request
SpecificationImpl.groovy:794)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendHttpRequest(
RequestSpecificationImpl.groovy)
at 
com.jayway.restassured.internal.RequestSpecificationImpl$this$2$sendHttpRequest.
callCurrent(Unknown Source)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpec
ificationImpl.groovy:717)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendRequest(Requ
estSpecificationImpl.groovy)
at 
com.jayway.restassured.internal.RequestSpecificationImpl$this$2$sendRequest.call
(Unknown Source)
at 
com.jayway.restassured.internal.filter.RootFilter.filter(RootFilter.groovy:28)
at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
at 
com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.
groovy:45)
at com.jayway.restassured.filter.FilterContext$next.call(Unknown Source)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(Reque
stSpecificationImpl.groovy:608)
at 
com.jayway.restassured.internal.RequestSpecificationImpl$invokeFilterChain.callC
urrent(Unknown Source)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendR
equest(RequestSpecificationImpl.groovy:957)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.this$2$applyPathParamsA
ndSendRequest(RequestSpecificationImpl.groovy)
at 
com.jayway.restassured.internal.RequestSpecificationImpl$this$2$applyPathParamsA
ndSendRequest.callCurrent(Unknown Source)
at 
org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteAr
ray.java:44)
at 
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSi
te.java:141)
at 
org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSi
te.java:157)
at 
com.jayway.restassured.internal.RequestSpecificationImpl.put(RequestSpecificatio
nImpl.groovy:124)
at 
com.myorg.project.test.IntegrationTest.testThatBreaks(IntegrationTest.java:100)
at net.sf.antcontrib.logic.TryCatchTask.execute(TryCatchTask.java:207)

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

version 1.5
Windows

Please provide any additional information below.

I also have set global BASIC auth and a baseURI that I'm overriding here, plus 
a RestArsured.registerParser for my content type

Original issue reported on code.google.com by phas...@gmail.com on 14 Feb 2012 at 1:04

GoogleCodeExporter commented 8 years ago
Please try out version 1.6-SNAPSHOT by adding the following repo:
<repositories>
        <repository>
            <id>sonatype</id>
            <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
            <snapshots />
        </repository>
</repositories>

I think it should be fixed there.

Original comment by johan.ha...@gmail.com on 15 Feb 2012 at 2:15

GoogleCodeExporter commented 8 years ago
And please try to verify it soon because I'd like to release a new version asap 
:)

Original comment by johan.ha...@gmail.com on 15 Feb 2012 at 2:21

GoogleCodeExporter commented 8 years ago
I'll try and verify that in the next few hours

Original comment by phas...@gmail.com on 15 Feb 2012 at 11:12

GoogleCodeExporter commented 8 years ago
Update: I'm still trying to test this - I need to massage Ivy into downloading 
this (by default our settings have module name identical to file name which 
doesn't apply in this case).

Original comment by phas...@gmail.com on 16 Feb 2012 at 2:45

GoogleCodeExporter commented 8 years ago
Couldn't get Ivy do do it. Couldn't get Eclipse to override just that one jar. 

I'll make up a test project using Maven.

Original comment by phas...@gmail.com on 16 Feb 2012 at 4:16

GoogleCodeExporter commented 8 years ago
OK, created a stand-alone Maven project to test this (attached)

Still got the following error:

Exception in thread "main" groovy.lang.MissingMethodException: No signature of 
method: com.jayway.restassured.internal.http.EncoderRegistry.encodeForm() is 
applicable for argument types: (null, [B) values: [null, [83, 111, 109, 101, 
32, 84, 101, 120, ...]]
Possible solutions: encodeForm(java.lang.Object, java.lang.String), 
encodeForm(java.util.Map)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:55)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:60)
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.setGroovyObjectProperty(ScriptBytecodeAdapter.java:530)
    at com.jayway.restassured.internal.RequestSpecificationImpl$_sendHttpRequest_closure13.doCall(RequestSpecificationImpl.groovy:813)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:884)
    at groovy.lang.Closure.call(Closure.java:410)
    at groovy.lang.Closure.call(Closure.java:423)
    at com.jayway.restassured.internal.http.HTTPBuilder.doRequest(HTTPBuilder.java:417)
    at com.jayway.restassured.internal.http.HTTPBuilder.request(HTTPBuilder.java:368)
    at com.jayway.restassured.internal.http.HTTPBuilder$request.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
    at com.jayway.restassured.internal.RequestSpecificationImpl.sendHttpRequest(RequestSpecificationImpl.groovy:807)
    at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendHttpRequest(RequestSpecificationImpl.groovy)
    at com.jayway.restassured.internal.RequestSpecificationImpl$this$2$sendHttpRequest.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at com.jayway.restassured.internal.RequestSpecificationImpl.sendRequest(RequestSpecificationImpl.groovy:681)
    at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$sendRequest(RequestSpecificationImpl.groovy)
    at com.jayway.restassured.internal.RequestSpecificationImpl$this$2$sendRequest.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
    at com.jayway.restassured.internal.filter.RootFilter.filter(RootFilter.groovy:28)
    at com.jayway.restassured.filter.Filter$filter.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
    at com.jayway.restassured.internal.filter.FilterContextImpl.next(FilterContextImpl.groovy:45)
    at com.jayway.restassured.filter.FilterContext$next.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:42)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:120)
    at com.jayway.restassured.internal.RequestSpecificationImpl.invokeFilterChain(RequestSpecificationImpl.groovy:627)
    at com.jayway.restassured.internal.RequestSpecificationImpl$invokeFilterChain.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
    at com.jayway.restassured.internal.RequestSpecificationImpl.applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy:996)
    at com.jayway.restassured.internal.RequestSpecificationImpl.this$2$applyPathParamsAndSendRequest(RequestSpecificationImpl.groovy)
    at com.jayway.restassured.internal.RequestSpecificationImpl$this$2$applyPathParamsAndSendRequest.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:46)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
    at com.jayway.restassured.internal.RequestSpecificationImpl.put(RequestSpecificationImpl.groovy:129)
    at mvn.scratch.RestAssuredTest.main(RestAssuredTest.java:12)

Original comment by phas...@gmail.com on 16 Feb 2012 at 6:00

GoogleCodeExporter commented 8 years ago
The above was using 1.6 snapshot.

Original comment by phas...@gmail.com on 16 Feb 2012 at 6:00

GoogleCodeExporter commented 8 years ago
oops, still had some of our code in the attachment. Here is the code calling 
rest-assured 1.6-SNAPSHOT that still fails.

Original comment by phas...@gmail.com on 16 Feb 2012 at 6:03

Attachments:

GoogleCodeExporter commented 8 years ago
Thanks for your help! I'll try out your example asap.

Original comment by johan.ha...@gmail.com on 16 Feb 2012 at 7:09

GoogleCodeExporter commented 8 years ago
Alright I think I've fixed it in trunk and I've deployed a new snapshot version 
of 1.6. Please try it out.

Original comment by johan.ha...@gmail.com on 17 Feb 2012 at 8:28

GoogleCodeExporter commented 8 years ago
Sorry, I've been off of work and haven't gotten a chance to look at this yet. 
I'll confirm against the final version today.

Original comment by phas...@gmail.com on 19 Feb 2012 at 8:55

GoogleCodeExporter commented 8 years ago
That worked for me for the harness i uploaded, but not for my original system.

Original comment by phas...@gmail.com on 20 Feb 2012 at 4:04

GoogleCodeExporter commented 8 years ago
Actually, I made a mistake with my harness (I'd switched it to a GET, which did 
work). This doesn't work with the harness I uploaded either.

I couldn't find any info on that error "No signature of method"  - it seems to 
be some sort of groovy method resolution issue?  Do we know anything about this 
error?

Original comment by phas...@gmail.com on 20 Feb 2012 at 4:16

GoogleCodeExporter commented 8 years ago
Yes that's a groovy error. How ever Rest Assured doesn't support a method body 
on the GET method (neither does HTTP Client or HTTP Builder). But are you 
saying that you still get an error when using PUT? Could you provide a test 
case?

Original comment by johan.ha...@gmail.com on 20 Feb 2012 at 7:11

GoogleCodeExporter commented 8 years ago
Yes, I'm getting this error while using PUT. I'll try to write up a test case.

Original comment by phas...@gmail.com on 20 Feb 2012 at 11:11

GoogleCodeExporter commented 8 years ago
Here's a test case project - there's one test class with a normal PUT that 
passes, then the same PUT with a content-type set, which fails with the above 
error.

You should be able to run a maven test on it...

Original comment by phas...@gmail.com on 21 Feb 2012 at 12:22

Attachments:

GoogleCodeExporter commented 8 years ago
I've just noticed that if you set the content type to "text/plain" rather than 
"application/vnd.something" it works.

Original comment by phas...@gmail.com on 21 Feb 2012 at 2:22

GoogleCodeExporter commented 8 years ago
To be clearer:
The exception occurs when the "contentType" method is called with a content 
type of "application/vnd.something", but does not occur when the "contentType" 
method is called with a content type of "text/plain"

Original comment by phas...@gmail.com on 21 Feb 2012 at 2:24

GoogleCodeExporter commented 8 years ago
OK. I *think* I've worked out what's happening at least. 

Since the call in the closure (which is passed to http.request, if I understand 
this correctly) at line 813 of RequestSpecificationImpl is a groovy beans 
setter call, it calls the setBody(Object requestBody) on line 998 of 
HTTPBuilder, which passes the currently set content type to the setBody(Object 
requestContentType, Object body) on line 1011 of HTTPBuilder. 

As part of that method, HTTPBuilder line 1015 is trying to get an encoding for 
the passed content type (which is the currently set content type). So it calls 
the encoders.getAt. Since it's not a registered encoder, and it's not any of 
the "+XML" or otherwise types, it ends up with an 'encodeForm' MethodClosure 
via the "getAt(ContentType.URLENC.toString());" recursive call (as configured 
at EncoderRegistry line 322 - the fourth line of buildDefaultEncoderMap()).

Since there's no form of encodeForm that takes a binary payload, it fails with 
the MissingMethodException.

Original comment by phas...@gmail.com on 21 Feb 2012 at 5:08

GoogleCodeExporter commented 8 years ago
So. It seems this error is a round-about way of saying "you need to register 
the type" using RestAssured.registerParser...

I tested with my test case adding "+XML" (even though it's not xml) and the 
test passed, which is consistent with my assumptions above.

So that gives me a work-around at least. 

Following on from that, though, for me it raises the question if there's a 
better way to handle this "no content type parser match found" case. 

Some options I can think of:

1. error way back when the content type is set (via 
RequestSpecification.contentType) if it doesn't match a registered one - that 
way people can see the source of the error directly and it's easier for the dev 
to understand and address the problem.

2. have the default functionality be, instead of, or in addition to defaulting 
to URLENC("application/x-www-form-urlencoded"), passing a byte array through 
unmodified. For example, if the content type is not matched, but the object is 
found to be a a byte array, perhaps default to "application/octet-stream". 
(although I guess that'd push the 'defaulting' decision out of the 
'EncoderRegistry.getAt(Object cotentType)' method...

So I guess that converts this to a feature request instead of a bug report ? :)

How does the above sound?

Original comment by phas...@gmail.com on 21 Feb 2012 at 5:22

GoogleCodeExporter commented 8 years ago
Oh, and the reason I thought it was still happening with content types that 
have '+xml' attached is that either one of my Eclipse, my IvyDE plugin or my 
Ivy cache was keeping an old copy (possibly a 1.6 snapshot?) and loading it 
instead of the current 1.6 version, but *telling me* that it was using 1.6.

grr.

Anyway, you had fixed the original problem (with a "+xml" content type) - it 
was my crappy build environment that was making me think it didn't work.

Original comment by phas...@gmail.com on 21 Feb 2012 at 5:57

GoogleCodeExporter commented 8 years ago
oops, it wasn't my 'crappy' build environment - it was the fact that I'd tried 
to work around the build env to try out the snapshot previously .. and left it 
in my build path :-~

Original comment by phas...@gmail.com on 21 Feb 2012 at 6:06

GoogleCodeExporter commented 8 years ago
I think issue 97 should slow your issues once it's implemented?

Original comment by johan.ha...@gmail.com on 21 Feb 2012 at 7:17

GoogleCodeExporter commented 8 years ago

Original comment by johan.ha...@gmail.com on 21 Feb 2012 at 7:17

GoogleCodeExporter commented 8 years ago
Providing a sensible default encoder (just copy the bytes) is part of that 
issue, yes. Either way, nicer errors would be good too :)

But yes that'd be sufficient.

Original comment by phas...@gmail.com on 21 Feb 2012 at 11:41