我正在为YouTrack API实现REST客户端。每当我的POST请求返回空响应时,我都会收到异常(只有一个有效的标头)。 HTTP状态代码为200。 这就是堆栈跟踪:
[Fatal Error] :-1:-1: Premature end of file.
gru 03, 2013 10:34:49 AM groovyx.net.http.HTTPBuilder doRequest
WARNING: Error parsing 'application/xml; charset=UTF-8' response
org.xml.sax.SAXParseException; Premature end of file.
at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
at groovy.util.XmlSlurper.parse(XmlSlurper.java:181)
at groovy.util.XmlSlurper.parse(XmlSlurper.java:234)
at groovyx.net.http.ParserRegistry.parseXML(ParserRegistry.java:267)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1085)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:952)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
at groovy.lang.Closure.call(Closure.java:423)
at groovy.lang.Closure.call(Closure.java:439)
at groovyx.net.http.HTTPBuilder.parseResponse(HTTPBuilder.java:561)
at groovyx.net.http.HTTPBuilder.doRequest(HTTPBuilder.java:494)
at groovyx.net.http.RESTClient.post(RESTClient.java:140)
at groovyx.net.http.RESTClient$post.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at groovy.YouTrackRest.releaseVersion(YouTrackRest.groovy:66)
at groovy.YouTrackRest$releaseVersion$0.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at YouTrack.run(YouTrack.groovy:13)
[...]
我已经调试并发现了直接原因。我注意到在groovyx.net.http.HTTPBuilder:492中,在解析之前检查响应是否为空,但在我的情况下,调用entity.getContentLength()返回-1。在Apache documentation for HttpEntity之后 内容的字节数,如果未知则为负数
我的客户端实现非常简单。我通过捕获HttpResponseException并断言statusCode 200解决了这个问题。我仍在控制台中获取堆栈跟踪,但这可能只是记录器设置。
我的实施:
import groovyx.net.http.RESTClient
class YouTrackRest extends RESTClient {
[...]
def activateVersion(versionNumber) {
try {
post(
path: getVersionPath(versionNumber),
body: [
colorIndex: ACTIVE_COLOR_INDEX,
released: false,
releaseDate: null,
archived: false,
newName: versionNumber
]
)
} catch (HttpResponseException ex) {
assert ex.response.status == 200
}
}
修改 这些是响应标头
Server: nginx
Date: Fri, 06 Dec 2013 10:36:10 GMT
Content-Type: application/xml; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Set-Cookie: JSESSIONID=ny2s3cxwsvveya6vgwj2fmig;Path=/youtrack
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store, no-transform, must-revalidate
现在Transfer-Encoding: chunked
标题解释了缺少'Content-Length'标题。这必须是未知内容长度的原因。
现在,根据Wikipedia ,数据传输由长度为零的最终块终止。那么也许这种情况下第一个块也是最后一个?
Web服务器和Http客户端库都是我的第三方。我想提出一个行为不端的问题:
groovyx.net.http.HTTPBuilder
无法处理分块编码的响应。我将非常乐于帮助我了解这个问题。
答案 0 :(得分:1)
我只是使用httpbuilder遇到了同样的问题。我可以通过以下方法解决它:
def service = new HTTPBuilder(...)
service.request(Method.POST, ContentType.JSON) {
uri.path = ...
body = ...
response.'200' = { resp ->
logInfo resp.statusLine
}
response.success = { resp, result ->
logInfo resp.statusLine
}
response.failure = { resp ->
logError resp.statusLine
}
}
如果响应为200,则基本上不要尝试解析正文。
答案 1 :(得分:0)
显然问题是由非标准WS响应引起的:HTTP状态200和空响应主体。要么是HTTP状态204,要么是有效的XML主体和状态200.
我在WS提供商处报告了issue。希望它会得到解决。我将问题标记为已回答
感谢@tim_yates和@Ian Roberts的有用评论。