monkeyWie / proxyee

HTTP proxy server,support HTTPS&websocket.MITM impl,intercept and tamper HTTPS traffic.
MIT License
1.5k stars 566 forks source link

多个拦截器 若某个拦截器的match方法若匹配一次 后续不匹配还会执行此拦截器的handleResponse方法 || Multiple interceptors If the match method of an interceptor matches once, the handleResponse method of this interceptor will be executed if there is no subsequent match #283

Open liuxuan-account opened 10 months ago

liuxuan-account commented 10 months ago

多个拦截器, com.github.monkeywie.proxyee.intercept.common.FullResponseIntercept
match() 方法根据不同的url进行匹配, 按道理来说每次响应都会先执行 match()方法 ,后执行 handleResponse()方法 但是不尽相同如果某个FullResponseIntercept 中的macth方法匹配一次,后续有时不执行match方法 会直接执行 handleResponse()方法

public final void afterResponse(Channel clientChannel, Channel proxyChannel,
                                HttpResponse httpResponse,
                                HttpProxyInterceptPipeline pipeline) throws Exception {
    if (httpResponse instanceof FullHttpResponse) {
        FullHttpResponse fullHttpResponse = (FullHttpResponse) httpResponse;
        // 判断是第一个处理FullResponse的拦截器是否匹配
        boolean isFirstMatch = isMatch != null && isMatch == true;
        // 判断后续的拦截器是否匹配
        boolean isAfterMatch = isFirstMatch ? false : match(pipeline.getHttpRequest(), pipeline.getHttpResponse(), pipeline);
        if (isFirstMatch || isAfterMatch) {
            handleResponse(pipeline.getHttpRequest(), fullHttpResponse, pipeline);
            if (fullHttpResponse.headers().contains(HttpHeaderNames.CONTENT_LENGTH)) {
                httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, fullHttpResponse.content().readableBytes());
            }
            if (pipeline.getHttpRequest() instanceof FullHttpRequest) {
                FullHttpRequest fullHttpRequest = (FullHttpRequest) pipeline.getHttpRequest();
                if (fullHttpRequest.content().refCnt() > 0) {
                    ReferenceCountUtil.release(fullHttpRequest);
                }
            }
        }
        if (isFirstMatch) {
            proxyChannel.pipeline().remove("decompress");
            proxyChannel.pipeline().remove("aggregator");
        }
    } else {
        this.isMatch = match(pipeline.getHttpRequest(), pipeline.getHttpResponse(), pipeline);
        if (this.isMatch) {
            proxyChannel.pipeline().addAfter("httpCodec", "decompress", new HttpContentDecompressor());
            proxyChannel.pipeline()
                    .addAfter("decompress", "aggregator", new HttpObjectAggregator(maxContentLength));
            proxyChannel.pipeline().fireChannelRead(httpResponse);
            return;
        }
    }
    pipeline.afterResponse(clientChannel, proxyChannel, httpResponse);
}

这个方法有问题


Multiple interceptors, com.github.monkeywie.proxyee.intercept.common.FullResponseIntercept The match() method matches according to different urls, It stands to reason that each response will first execute the match() method, and then execute the handleResponse() method But it is not the same. If the macth method in a FullResponseIntercept matches once, sometimes the match method will not be executed later, and the handleResponse() method will be executed directly.

public final void afterResponse(Channel clientChannel, Channel proxyChannel,
                                HttpResponse httpResponse,
                                HttpProxyInterceptPipeline pipeline) throws Exception {
    if (httpResponse instanceof FullHttpResponse) {
        FullHttpResponse fullHttpResponse = (FullHttpResponse) httpResponse;
        // Determine whether the first interceptor that handles FullResponse matches
        boolean isFirstMatch = isMatch != null && isMatch == true;
        // Determine whether the subsequent interceptor matches
        boolean isAfterMatch = isFirstMatch ? false : match(pipeline. getHttpRequest(), pipeline. getHttpResponse(), pipeline);
        if (isFirstMatch || isAfterMatch) {
            handleResponse(pipeline. getHttpRequest(), fullHttpResponse, pipeline);
            if (fullHttpResponse. headers(). contains(HttpHeaderNames. CONTENT_LENGTH)) {
                httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, fullHttpResponse.content().readableBytes());
            }
            if (pipeline. getHttpRequest() instanceof FullHttpRequest) {
                FullHttpRequest fullHttpRequest = (FullHttpRequest) pipeline. getHttpRequest();
                if (fullHttpRequest. content(). refCnt() > 0) {
                    ReferenceCountUtil. release(fullHttpRequest);
                }
            }
        }
        if (isFirstMatch) {
            proxyChannel.pipeline().remove("decompress");
            proxyChannel.pipeline().remove("aggregator");
        }
    } else {
        this.isMatch = match(pipeline.getHttpRequest(), pipeline.getHttpResponse(), pipeline);
        if (this. isMatch) {
            proxyChannel.pipeline().addAfter("httpCodec", "decompress", new HttpContentDecompressor());
            proxyChannel. pipeline()
                    .addAfter("decompress", "aggregator", new HttpObjectAggregator(maxContentLength));
            proxyChannel.pipeline().fireChannelRead(httpResponse);
            return;
        }
    }
    pipeline.afterResponse(clientChannel, proxyChannel, httpResponse);
}

There is a problem with this method