Charles 断点导致 EOFException 和 MalformedChunkCodingException

Charles breakpoints cause EOFException and MalformedChunkCodingException

我正在使用 Charles 拦截来自我的 Android 应用程序的 Web API 调用,以便我可以操纵响应并测试超时和令牌过期等条件(当令牌时我收到 403已过期)。但是我从前一段时间开始就收到 EOFException,我不知道问题出在哪里。异常看起来像这样,

05-29 18:28:12.374 W/System.err: java.io.EOFException
05-29 18:28:12.374 W/System.err:     at okio.RealBufferedSource.require(RealBufferedSource.java:59)
05-29 18:28:12.374 W/System.err:     at okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:284)
05-29 18:28:12.374 W/System.err:     at okhttp3.internal.http1.Http1Codec$ChunkedSource.readChunkSize(Http1Codec.java:444)
05-29 18:28:12.374 W/System.err:     at okhttp3.internal.http1.Http1Codec$ChunkedSource.read(Http1Codec.java:425)
05-29 18:28:12.374 W/System.err:     at okio.RealBufferedSource.request(RealBufferedSource.java:66)
05-29 18:28:12.374 W/System.err:     at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:387)
05-29 18:28:12.375 W/System.err:     at okio.RealBufferedSource.rangeEquals(RealBufferedSource.java:371)
05-29 18:28:12.375 W/System.err:     at okhttp3.internal.Util.bomAwareCharset(Util.java:412)
05-29 18:28:12.375 W/System.err:     at okhttp3.ResponseBody.string(ResponseBody.java:173)
05-29 18:28:12.375 W/System.err:     at facilit.net.core.webapi.WebApi.workOrderGetList(WebApi.java:200)

起初我认为这可能是因为我正在编辑响应,但似乎任何在断点处停止的 Web API 调用都会导致异常。总是一样的例外。我尝试了不同的模拟器和我的设备。在所有情况下都是准确的结果。

请求代码

@Nullable
    public WorkOrderListResultObject workOrderGetList(@Nonnull JSONObject params) throws WebApiNotInitializedException, IOException {
        if (isInitialized()) {
            final RequestBody requestBody = getRequestBody(params);
            final Request request = getRequest(NetworkConstants.GET_WORK_ORDER_LIST_URL, requestBody);

            try {
                final okhttp3.Response response = mClient.newCall(request).execute();
                final String string = response.body().string();

                final WorkOrderListResultObject workOrderListResultObject = new WorkOrderListResultObject();
                workOrderListResultObject.setResponseString(string);
                workOrderListResultObject.setStatusCode(response.code());

                return workOrderListResultObject;
            } catch (IOException e) {
                if (BuildConfig.DEBUG) {
                    e.printStackTrace();
                }

                throw e;
            }
        } else {
            throwNotInitializedException();

            return null;
        }
    }

private RequestBody getRequestBody(@Nonnull JSONObject params) {
        return RequestBody.create(mediaType, params.toString());
    }

private Request getRequest(@Nonnull String url, @Nonnull RequestBody requestBody) throws IllegalArgumentException {
        if (url.isEmpty()) {
            throw new IllegalArgumentException("url cannot be empty");
        }

        return new Request.Builder()
                .url(BuildConfig.FACILIT_SERVER_BASE_URL + url)
                .addHeader(NetworkConstants.CONSTANT_AUTHENTICATION_TOKEN, FacilitApplicationContext.getFacilitApplicationContext().getAuthenticationToken())
                .addHeader(NetworkConstants.CONSTANT_MOBILE_APP_VERSION, mVersionName)
                .addHeader(NetworkConstants.CONSTANT_MOBILE_PLATFORM_ID, mMobilePlatformValue)
                .addHeader(NetworkConstants.CONSTANT_APPLICATION_ID, mApplicationIDValue)
                .post(requestBody)
                .build();
    }

public static WebApi getInstance() {
        if (mInstance == null) {
            mInstance = new WebApi();
            mClient = new OkHttpClient.Builder()
                    .connectTimeout(TIME_OUT_MILLISECONDS, TimeUnit.MILLISECONDS)
                    .readTimeout(TIME_OUT_MILLISECONDS, TimeUnit.MILLISECONDS)
                    .writeTimeout(TIME_OUT_MILLISECONDS, TimeUnit.MILLISECONDS)
                    .build();
        }

        return mInstance;
    }

如果它对我有进一步的帮助,我正在从传统的 Apache API 迁移到 OkHttp 和旧的 Apache API 的 Web API 也会抛出错误。 .

org.apache.http.MalformedChunkCodingException: Chunked stream ended unexpectedly

我非常怀疑这是由于服务器设置更改造成的。

服务器响应示例,

HTTP/1.1 403 Forbidden
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 30 May 2017 05:16:38 GMT
Content-Length: 0

在 OkHttp 中使用拦截器后,我注意到以下差异, 如果没有在断点处停止:

Received response for http://webapitest.demo.net/api/workOrder/getList in 1979.3ms
                             Cache-Control: no-cache
                             Pragma: no-cache
                             Content-Type: application/json; charset=utf-8
                             Expires: -1
                             Server: Microsoft-IIS/8.5
                             X-AspNet-Version: 4.0.30319
                             X-Powered-By: ASP.NET
                             Date: Tue, 30 May 2017 12:45:41 GMT
                             Content-Length: 23461
                             Proxy-Connection: Keep-alive

如果停止:

Received response for http://webapitest.demo.net/api/workOrder/getList in 8169.2ms
                             Cache-Control: no-cache
                             Pragma: no-cache
                             Content-Type: application/json; charset=utf-8
                             Expires: -1
                             Server: Microsoft-IIS/8.5
                             X-AspNet-Version: 4.0.30319
                             X-Powered-By: ASP.NET
                             Date: Tue, 30 May 2017 12:46:36 GMT
                             Transfer-Encoding: chunked
                             Proxy-Connection: Keep-alive

在注意到使用 OkHttp 拦截器的响应 header 差异后,很明显是 Charles 引起了 header 更改,我检查并确认响应中缺少 'Content-Length: 23461' header 被 OkHttp 接收是 EOFException 的原因。对 API 进行任何更改不是一个选项,我很确定我也没有对 Charles 进行设置更改。所以我尝试使用 mitmproxy 但那太复杂了,所以我开始使用 ZAP。它更好地服务于 Charles 和 IMO 的目的。 ZAP 是免费的,所以之后我什至没有理会 Charles。