最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

HttpClient的RedirectStrategy重定向處理核心機(jī)制

 更新時(shí)間:2023年10月25日 08:37:09   作者:codecraft  
這篇文章主要為大家介紹了HttpClient的RedirectStrategy重定向處理核心機(jī)制源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

本文主要研究一下HttpClient的RedirectStrategy

RedirectStrategy

org/apache/http/client/RedirectStrategy.java

public interface RedirectStrategy {
    /**
     * Determines if a request should be redirected to a new location
     * given the response from the target server.
     *
     * @param request the executed request
     * @param response the response received from the target server
     * @param context the context for the request execution
     *
     * @return {@code true} if the request should be redirected, {@code false}
     * otherwise
     */
    boolean isRedirected(
            HttpRequest request,
            HttpResponse response,
            HttpContext context) throws ProtocolException;
    /**
     * Determines the redirect location given the response from the target
     * server and the current request execution context and generates a new
     * request to be sent to the location.
     *
     * @param request the executed request
     * @param response the response received from the target server
     * @param context the context for the request execution
     *
     * @return redirected request
     */
    HttpUriRequest getRedirect(
            HttpRequest request,
            HttpResponse response,
            HttpContext context) throws ProtocolException;
}
RedirectStrategy接口定義了isRedirected方法用于判斷是否需要redirect,還定義了getRedirect方法用于返回redirect的目標(biāo)地址

DefaultRedirectStrategy

org/apache/http/impl/client/DefaultRedirectStrategy.java

@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultRedirectStrategy implements RedirectStrategy {
    private final Log log = LogFactory.getLog(getClass());
    /**
     * @deprecated (4.3) use {@link org.apache.http.client.protocol.HttpClientContext#REDIRECT_LOCATIONS}.
     */
    @Deprecated
    public static final String REDIRECT_LOCATIONS = "http.protocol.redirect-locations";
    public static final DefaultRedirectStrategy INSTANCE = new DefaultRedirectStrategy();
    private final String[] redirectMethods;
    public DefaultRedirectStrategy() {
        this(new String[] {
            HttpGet.METHOD_NAME,
            HttpHead.METHOD_NAME
        });
    }
    /**
     * Constructs a new instance to redirect the given HTTP methods.
     *
     * @param redirectMethods The methods to redirect.
     * @since 4.5.10
     */
    public DefaultRedirectStrategy(final String[] redirectMethods) {
        super();
        final String[] tmp = redirectMethods.clone();
        Arrays.sort(tmp);
        this.redirectMethods = tmp;
    }
    @Override
    public boolean isRedirected(
            final HttpRequest request,
            final HttpResponse response,
            final HttpContext context) throws ProtocolException {
        Args.notNull(request, "HTTP request");
        Args.notNull(response, "HTTP response");
        final int statusCode = response.getStatusLine().getStatusCode();
        final String method = request.getRequestLine().getMethod();
        final Header locationHeader = response.getFirstHeader("location");
        switch (statusCode) {
        case HttpStatus.SC_MOVED_TEMPORARILY:
            return isRedirectable(method) && locationHeader != null;
        case HttpStatus.SC_MOVED_PERMANENTLY:
        case HttpStatus.SC_TEMPORARY_REDIRECT:
            return isRedirectable(method);
        case HttpStatus.SC_SEE_OTHER:
            return true;
        default:
            return false;
        } //end of switch
    }
    /**
     * @since 4.2
     */
    protected boolean isRedirectable(final String method) {
        return Arrays.binarySearch(redirectMethods, method) >= 0;
    }
    @Override
    public HttpUriRequest getRedirect(
            final HttpRequest request,
            final HttpResponse response,
            final HttpContext context) throws ProtocolException {
        final URI uri = getLocationURI(request, response, context);
        final String method = request.getRequestLine().getMethod();
        if (method.equalsIgnoreCase(HttpHead.METHOD_NAME)) {
            return new HttpHead(uri);
        } else if (method.equalsIgnoreCase(HttpGet.METHOD_NAME)) {
            return new HttpGet(uri);
        } else {
            final int status = response.getStatusLine().getStatusCode();
            return status == HttpStatus.SC_TEMPORARY_REDIRECT
                            ? RequestBuilder.copy(request).setUri(uri).build()
                            : new HttpGet(uri);
        }
    }
}

DefaultRedirectStrategy實(shí)現(xiàn)了RedirectStrategy接口,它定義了redirectMethods,默認(rèn)是Get和Head;isRedirected方法先獲取response的statusCode,對(duì)于302需要location的header有值且請(qǐng)求method在redirectMethods中(isRedirectable),對(duì)于301及307僅僅判斷isRedirectable,對(duì)于303返回true,其余的返回false

getRedirect方法先通過getLocationURI獲取目標(biāo)地址,然后針對(duì)get或者h(yuǎn)ead分別構(gòu)造HttpHead及HttpGet,剩下的根據(jù)statusCode判斷,是307則拷貝原來的request,否則返回HttpGet

RedirectExec

org/apache/http/impl/execchain/RedirectExec.java

/**
 * Request executor in the request execution chain that is responsible
 * for handling of request redirects.
 * <p>
 * Further responsibilities such as communication with the opposite
 * endpoint is delegated to the next executor in the request execution
 * chain.
 * </p>
 *
 * @since 4.3
 */
@Contract(threading = ThreadingBehavior.IMMUTABLE_CONDITIONAL)
public class RedirectExec implements ClientExecChain {
    private final Log log = LogFactory.getLog(getClass());
    private final ClientExecChain requestExecutor;
    private final RedirectStrategy redirectStrategy;
    private final HttpRoutePlanner routePlanner;
    public RedirectExec(
            final ClientExecChain requestExecutor,
            final HttpRoutePlanner routePlanner,
            final RedirectStrategy redirectStrategy) {
        super();
        Args.notNull(requestExecutor, "HTTP client request executor");
        Args.notNull(routePlanner, "HTTP route planner");
        Args.notNull(redirectStrategy, "HTTP redirect strategy");
        this.requestExecutor = requestExecutor;
        this.routePlanner = routePlanner;
        this.redirectStrategy = redirectStrategy;
    }
    @Override
    public CloseableHttpResponse execute(
            final HttpRoute route,
            final HttpRequestWrapper request,
            final HttpClientContext context,
            final HttpExecutionAware execAware) throws IOException, HttpException {
        Args.notNull(route, "HTTP route");
        Args.notNull(request, "HTTP request");
        Args.notNull(context, "HTTP context");
        final List<URI> redirectLocations = context.getRedirectLocations();
        if (redirectLocations != null) {
            redirectLocations.clear();
        }
        final RequestConfig config = context.getRequestConfig();
        final int maxRedirects = config.getMaxRedirects() > 0 ? config.getMaxRedirects() : 50;
        HttpRoute currentRoute = route;
        HttpRequestWrapper currentRequest = request;
        for (int redirectCount = 0;;) {
            final CloseableHttpResponse response = requestExecutor.execute(
                    currentRoute, currentRequest, context, execAware);
            try {
                if (config.isRedirectsEnabled() &&
                        this.redirectStrategy.isRedirected(currentRequest.getOriginal(), response, context)) {
                    if (redirectCount >= maxRedirects) {
                        throw new RedirectException("Maximum redirects ("+ maxRedirects + ") exceeded");
                    }
                    redirectCount++;
                    final HttpRequest redirect = this.redirectStrategy.getRedirect(
                            currentRequest.getOriginal(), response, context);
                    if (!redirect.headerIterator().hasNext()) {
                        final HttpRequest original = request.getOriginal();
                        redirect.setHeaders(original.getAllHeaders());
                    }
                    currentRequest = HttpRequestWrapper.wrap(redirect);
                    if (currentRequest instanceof HttpEntityEnclosingRequest) {
                        RequestEntityProxy.enhance((HttpEntityEnclosingRequest) currentRequest);
                    }
                    final URI uri = currentRequest.getURI();
                    final HttpHost newTarget = URIUtils.extractHost(uri);
                    if (newTarget == null) {
                        throw new ProtocolException("Redirect URI does not specify a valid host name: " +
                                uri);
                    }
                    // Reset virtual host and auth states if redirecting to another host
                    if (!currentRoute.getTargetHost().equals(newTarget)) {
                        final AuthState targetAuthState = context.getTargetAuthState();
                        if (targetAuthState != null) {
                            this.log.debug("Resetting target auth state");
                            targetAuthState.reset();
                        }
                        final AuthState proxyAuthState = context.getProxyAuthState();
                        if (proxyAuthState != null && proxyAuthState.isConnectionBased()) {
                            this.log.debug("Resetting proxy auth state");
                            proxyAuthState.reset();
                        }
                    }
                    currentRoute = this.routePlanner.determineRoute(newTarget, currentRequest, context);
                    if (this.log.isDebugEnabled()) {
                        this.log.debug("Redirecting to '" + uri + "' via " + currentRoute);
                    }
                    EntityUtils.consume(response.getEntity());
                    response.close();
                } else {
                    return response;
                }
            } catch (final RuntimeException ex) {
                response.close();
                throw ex;
            } catch (final IOException ex) {
                response.close();
                throw ex;
            } catch (final HttpException ex) {
                // Protocol exception related to a direct.
                // The underlying connection may still be salvaged.
                try {
                    EntityUtils.consume(response.getEntity());
                } catch (final IOException ioex) {
                    this.log.debug("I/O error while releasing connection", ioex);
                } finally {
                    response.close();
                }
                throw ex;
            }
        }
    }
}
RedirectExec實(shí)現(xiàn)了ClientExecChain接口,其構(gòu)造器要求傳入requestExecutor、redirectStrategy、routePlanner,其execute方法會(huì)先獲取maxRedirects參數(shù),然后執(zhí)行requestExecutor.execute,接著在config.isRedirectsEnabled()以及redirectStrategy.isRedirected為true時(shí)才進(jìn)入redirect邏輯,它會(huì)先判斷是否超出maxRedirects,大于等于則拋出RedirectException,否則通過redirectStrategy.getRedirect獲取HttpRequest,更新currentRoute,然后清理entity關(guān)閉response繼續(xù)下次循環(huán),即執(zhí)行redirect邏輯。

小結(jié)

HttpClient的RedirectStrategy定義了兩個(gè)方法,一個(gè)是是否需要redirect,一個(gè)是獲取redirect的請(qǐng)求,DefaultRedirectStrategy的構(gòu)造器支持傳入redirectMethods,默認(rèn)是Get和Head,isRedirected方法主要是對(duì)302,301,307,303進(jìn)行了判斷,getRedirect方法主要是通過location獲取目標(biāo)地址,然后根據(jù)原來的method和statusCode構(gòu)造HttpUriRequest。

以上就是HttpClient的RedirectStrategy源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于HttpClient的RedirectStrategy的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MyBatis編寫一個(gè)簡(jiǎn)單的SQL生成工具

    MyBatis編寫一個(gè)簡(jiǎn)單的SQL生成工具

    MyBatis 是一個(gè)強(qiáng)大的數(shù)據(jù)持久化框架,它提供了一種半自動(dòng)化的 ORM 實(shí)現(xiàn)方式,本文將為大家介紹如何使用MyBatis編寫一個(gè)簡(jiǎn)單的SQL生成工具,需要的可以了解下
    2025-03-03
  • Spring Boot和Thymeleaf整合結(jié)合JPA實(shí)現(xiàn)分頁效果(實(shí)例代碼)

    Spring Boot和Thymeleaf整合結(jié)合JPA實(shí)現(xiàn)分頁效果(實(shí)例代碼)

    這篇文章主要介紹了Spring Boot和Thymeleaf整合結(jié)合JPA實(shí)現(xiàn)分頁效果,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 學(xué)習(xí)java一定要知道的垃圾收集器

    學(xué)習(xí)java一定要知道的垃圾收集器

    這篇文章主要介紹了學(xué)習(xí)java一定要知道的垃圾收集器,垃圾收集器的發(fā)展路線,簡(jiǎn)單來說是隨著內(nèi)存越來越大而發(fā)生變化,更多相關(guān)介紹需要的朋友可以參考一下
    2022-07-07
  • mybatisPlus實(shí)現(xiàn)倒序拼接字符串

    mybatisPlus實(shí)現(xiàn)倒序拼接字符串

    這篇文章主要介紹了mybatisPlus實(shí)現(xiàn)倒序拼接字符串方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • RocketMQ整合SpringBoot實(shí)現(xiàn)生產(chǎn)級(jí)二次封裝

    RocketMQ整合SpringBoot實(shí)現(xiàn)生產(chǎn)級(jí)二次封裝

    本文主要介紹了RocketMQ整合SpringBoot實(shí)現(xiàn)生產(chǎn)級(jí)二次封裝,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • SpringBoot之控制器的返回值處理方式

    SpringBoot之控制器的返回值處理方式

    這篇文章主要介紹了SpringBoot之控制器的返回值處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Mybatis實(shí)現(xiàn)自定義的typehandler三步曲

    Mybatis實(shí)現(xiàn)自定義的typehandler三步曲

    這篇文章主要介紹了Mybatis實(shí)現(xiàn)自定義的typehandler三步曲的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • SpringBoot+Netty實(shí)現(xiàn)簡(jiǎn)單聊天室的示例代碼

    SpringBoot+Netty實(shí)現(xiàn)簡(jiǎn)單聊天室的示例代碼

    這篇文章主要介紹了如何利用SpringBoot Netty實(shí)現(xiàn)簡(jiǎn)單聊天室,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)SpringBoot有一定幫助,感興趣的同學(xué)可以了解一下
    2022-02-02
  • MyBatis Plus 中 update_time 字段自動(dòng)填充失效的原因分析及解決方案(最新整理)

    MyBatis Plus 中 update_time 字段自動(dòng)填充失效的原因分析

    在使用MyBatis Plus時(shí),通常我們會(huì)在數(shù)據(jù)庫表中設(shè)置create_time和update_time兩個(gè)字段,借助 MyBatis Plus 的自動(dòng)填充功能來維護(hù)這些時(shí)間字段,下面通過本文介紹MyBatis Plus 中 update_time 字段自動(dòng)填充失效的原因分析及解決方案,感興趣的朋友一起看看吧
    2025-06-06
  • SpringBoot中集成Redis進(jìn)行緩存的實(shí)現(xiàn)

    SpringBoot中集成Redis進(jìn)行緩存的實(shí)現(xiàn)

    本文主要介紹了SpringBoot中集成Redis進(jìn)行緩存的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-06-06

最新評(píng)論

泾阳县| 金门县| 平乡县| 平南县| 蓬莱市| 庆城县| 绩溪县| 会东县| 东阳市| 龙南县| 甘泉县| 且末县| 乌兰浩特市| 尖扎县| 沧州市| 容城县| 梅河口市| 阳西县| 武宣县| 织金县| 平昌县| 水城县| 大埔县| 分宜县| 江津市| 三明市| 无棣县| 临猗县| 合作市| 遵化市| 南川市| 蕲春县| 公主岭市| 屯留县| 腾冲县| 镇江市| 汾阳市| 平南县| 任丘市| 佛山市| 金湖县|