1

我正在为 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。在HttpEntity 的 Apache 文档之后,内容的字节数,如果未知,则为负数

我的客户端实现非常简单。我通过捕获 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标头解释了缺少的“内容长度”标头。这一定是未知内容长度的原因。现在,根据Wikipedia 数据传输由长度为零的最终块终止。那么也许这种情况下第一个块也是最后一个块?

Web 服务器和 Http 客户端库对我来说都是第三方。我想通过行为不端的人提出一个问题:

  • YouTrack REST WS 承诺XML并且不返回任何内容
  • groovyx.net.http.HTTPBuilder无法处理分块的编码响应。

我会非常有帮助的一些专业知识来帮助我理解问题。

4

2 回答 2

1

遇到了同样的问题。我能够通过以下方式解决它:

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,则基本上不要尝试解析正文。

于 2020-02-14T22:19:03.317 回答
0

显然问题是由非标准 WS 响应引起的:HTTP 状态 200 和空响应正文。预期为 HTTP 状态 204,或有效的 XML 正文和状态 200。

我在 WS 提供商处报告了一个问题。希望它会得到解决。我将问题标记为已回答

感谢@tim_yates 和@Ian Roberts 的有益评论。

于 2013-12-11T10:09:48.440 回答