You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SoapUI Mock Service中reader.readLine()首次请求后返回null问题

SoapUI Mock Service 请求体重复读取返回null的解决方法

问题根源

你遇到的问题是因为Servlet 请求输入流是一次性消费的:首次调用request.getReader()或request.getInputStream()读取流后,流的指针会移动到末尾,后续再读取就会返回null。哪怕更换LineNumberReader为BufferedReader,或者改用read(char[])方法,只要流已经被消费,就无法再读取到内容。另外,SoapUI 的MockRequest内部可能已经提前读取过请求流,导致自定义的setData方法无法再次获取内容。

解决方案

方案1:直接使用SoapUI内置API获取请求体

SoapUI 提供了MockRequest.getRequestContent()方法,已经封装了请求体的读取和缓存,无需手动操作输入流。直接替换你的setData方法即可:

修改后的完整代码:

def requestMethod = mockRequest.getMethod()
log.info "mockRequest.method: " + requestMethod

if (requestMethod.toString() != "GET") {
    log.info "dispatch:Status 405"
    return "405 - Method Not Allowed"
}

def acceptEncodingHeaderList = mockRequest.getRequestHeaders().get("Accept-Encoding")
log.info "AcceptEncoding Header List: " + acceptEncodingHeaderList

if (!acceptEncodingHeaderList.contains("gzip, deflate, br")) {
    log.info "dispatch:Status 406"
    return "406 - Not Acceptable"
}

// 直接使用内置API获取请求体
def data = mockRequest.getRequestContent()
log.info "data:" + data

if (!data.contains("bscs")) {
    log.info "dispatch:Status 400"
    return "400 - Bad Request"
}
log.info "dispatch:ok "
return "200 - OK"

方案2:手动缓存请求体(如果需要自定义读取逻辑)

如果必须保留自定义的读取逻辑,可在首次读取后将请求体缓存到MockRequest的属性中,后续直接取用缓存内容:

def requestMethod = mockRequest.getMethod()
log.info "mockRequest.method: " + requestMethod

if (requestMethod.toString() != "GET") {
    log.info "dispatch:Status 405"
    return "405 - Method Not Allowed"
}

def acceptEncodingHeaderList = mockRequest.getRequestHeaders().get("Accept-Encoding")
log.info "AcceptEncoding Header List: " + acceptEncodingHeaderList

if (!acceptEncodingHeaderList.contains("gzip, deflate, br")) {
    log.info "dispatch:Status 406"
    return "406 - Not Acceptable"
}

def data = setData()
log.info "data:" + data

if (!data.contains("bscs")) {
    log.info "dispatch:Status 400"
    return "400 - Bad Request"
}
log.info "dispatch:ok "
return "200 - OK"

def setData() {
    // 检查是否已有缓存的请求体
    def cachedBody = mockRequest.getProperty("REQUEST_BODY")
    if (cachedBody) {
        return cachedBody
    }
    
    def request = mockRequest.getHttpRequest()
    def buffer = new StringWriter()
    def inputStream = request.getInputStream()
    def byteBuffer = new byte[1024]
    int bytesRead
    
    // 读取输入流内容
    while ((bytesRead = inputStream.read(byteBuffer)) != -1) {
        buffer.write(byteBuffer, 0, bytesRead)
    }
    
    def data = buffer.toString()
    // 缓存到MockRequest属性中
    mockRequest.setProperty("REQUEST_BODY", data)
    return data
}

注意事项

  • 避免重复调用request.getReader()或request.getInputStream(),这两个方法会返回同一个流对象,读取后无法重置。
  • 优先使用SoapUI提供的内置API,这类方法已经处理了流的复用和缓存问题,更稳定可靠。

内容的提问来源于stack exchange,提问作者Luiz Henrique Oliveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 05:50:27