摘要:序本文主要研究一下的。提供了及方法,前者添加,后者使用反射實例化。其中是按順序執行,而則取的是,逆序執行
序
本文主要研究一下jdk http的HeaderFilter。
FilterFactoryjava.net.http/jdk/internal/net/http/FilterFactory.java
class FilterFactory { // Strictly-ordered list of filters. final LinkedList> filterClasses = new LinkedList<>(); public void addFilter(Class extends HeaderFilter> type) { filterClasses.add(type); } LinkedList getFilterChain() { LinkedList l = new LinkedList<>(); for (Class extends HeaderFilter> clazz : filterClasses) { try { // Requires a public no arg constructor. HeaderFilter headerFilter = clazz.getConstructor().newInstance(); l.add(headerFilter); } catch (ReflectiveOperationException e) { throw new InternalError(e); } } return l; } }
提供了addFilter及getFilterChain方法,前者添加filter class,后者使用反射實例化filter。
HttpClientImpljava.net.http/jdk/internal/net/http/HttpClientImpl.java
private HttpClientImpl(HttpClientBuilderImpl builder, SingleFacadeFactory facadeFactory) { id = CLIENT_IDS.incrementAndGet(); dbgTag = "HttpClientImpl(" + id +")"; if (builder.sslContext == null) { try { sslContext = SSLContext.getDefault(); } catch (NoSuchAlgorithmException ex) { throw new InternalError(ex); } } else { sslContext = builder.sslContext; } Executor ex = builder.executor; if (ex == null) { ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id)); isDefaultExecutor = true; } else { isDefaultExecutor = false; } delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex); facadeRef = new WeakReference<>(facadeFactory.createFacade(this)); client2 = new Http2ClientImpl(this); cookieHandler = builder.cookieHandler; connectTimeout = builder.connectTimeout; followRedirects = builder.followRedirects == null ? Redirect.NEVER : builder.followRedirects; this.userProxySelector = Optional.ofNullable(builder.proxy); this.proxySelector = userProxySelector .orElseGet(HttpClientImpl::getDefaultProxySelector); if (debug.on()) debug.log("proxySelector is %s (user-supplied=%s)", this.proxySelector, userProxySelector.isPresent()); authenticator = builder.authenticator; if (builder.version == null) { version = HttpClient.Version.HTTP_2; } else { version = builder.version; } if (builder.sslParams == null) { sslParams = getDefaultParams(sslContext); } else { sslParams = builder.sslParams; } connections = new ConnectionPool(id); connections.start(); timeouts = new TreeSet<>(); try { selmgr = new SelectorManager(this); } catch (IOException e) { // unlikely throw new InternalError(e); } selmgr.setDaemon(true); filters = new FilterFactory(); initFilters(); assert facadeRef.get() != null; } private void initFilters() { addFilter(AuthenticationFilter.class); addFilter(RedirectFilter.class); if (this.cookieHandler != null) { addFilter(CookieFilter.class); } } private void addFilter(Class extends HeaderFilter> f) { filters.addFilter(f); } final LinkedListfilterChain() { return filters.getFilterChain(); }
HttpClientImpl的構造器創建了FilterFactory,并調用addFilter添加默認的filter
filterChain方法則調用了FilterFactory的getFilterChain()方法,使用反射實例化這些filter
MultiExchangejava.net.http/jdk/internal/net/http/MultiExchange.java
/** * MultiExchange with one final response. */ MultiExchange(HttpRequest userRequest, HttpRequestImpl requestImpl, HttpClientImpl client, HttpResponse.BodyHandlerresponseHandler, PushPromiseHandler pushPromiseHandler, AccessControlContext acc) { this.previous = null; this.userRequest = userRequest; this.request = requestImpl; this.currentreq = request; this.previousreq = null; this.client = client; this.filters = client.filterChain(); this.acc = acc; this.executor = client.theExecutor(); this.responseHandler = responseHandler; if (pushPromiseHandler != null) { Executor executor = acc == null ? this.executor.delegate() : new PrivilegedExecutor(this.executor.delegate(), acc); this.pushGroup = new PushGroup<>(pushPromiseHandler, request, executor); } else { pushGroup = null; } this.exchange = new Exchange<>(request, this); } private CompletableFuture responseAsyncImpl() { CompletableFuture cf; if (attempts.incrementAndGet() > max_attempts) { cf = failedFuture(new IOException("Too many retries", retryCause)); } else { if (currentreq.timeout().isPresent()) { responseTimerEvent = ResponseTimerEvent.of(this); client.registerTimer(responseTimerEvent); } try { // 1. apply request filters // if currentreq == previousreq the filters have already // been applied once. Applying them a second time might // cause some headers values to be added twice: for // instance, the same cookie might be added again. if (currentreq != previousreq) { requestFilters(currentreq); } } catch (IOException e) { return failedFuture(e); } Exchange exch = getExchange(); // 2. get response cf = exch.responseAsync() .thenCompose((Response response) -> { HttpRequestImpl newrequest; try { // 3. apply response filters newrequest = responseFilters(response); } catch (IOException e) { return failedFuture(e); } // 4. check filter result and repeat or continue if (newrequest == null) { if (attempts.get() > 1) { Log.logError("Succeeded on attempt: " + attempts); } return completedFuture(response); } else { this.response = new HttpResponseImpl<>(currentreq, response, this.response, null, exch); Exchange oldExch = exch; return exch.ignoreBody().handle((r,t) -> { previousreq = currentreq; currentreq = newrequest; expiredOnce = false; setExchange(new Exchange<>(currentreq, this, acc)); return responseAsyncImpl(); }).thenCompose(Function.identity()); } }) .handle((response, ex) -> { // 5. handle errors and cancel any timer set cancelTimer(); if (ex == null) { assert response != null; return completedFuture(response); } // all exceptions thrown are handled here CompletableFuture errorCF = getExceptionalCF(ex); if (errorCF == null) { return responseAsyncImpl(); } else { return errorCF; } }) .thenCompose(Function.identity()); } return cf; } private void requestFilters(HttpRequestImpl r) throws IOException { Log.logTrace("Applying request filters"); for (HeaderFilter filter : filters) { Log.logTrace("Applying {0}", filter); filter.request(r, this); } Log.logTrace("All filters applied"); } private HttpRequestImpl responseFilters(Response response) throws IOException { Log.logTrace("Applying response filters"); Iterator reverseItr = filters.descendingIterator(); while (reverseItr.hasNext()) { HeaderFilter filter = reverseItr.next(); Log.logTrace("Applying {0}", filter); HttpRequestImpl newreq = filter.response(response); if (newreq != null) { Log.logTrace("New request: stopping filters"); return newreq; } } Log.logTrace("All filters applied"); return null; }
MultiExchange在構造器里頭調用了client.filterChain(),完成filters的初始化
在responseAsyncImpl方法里頭,執行請求之前調用requestFilters,得到response之后調用responseFilters
requestFilters是按順序執行,而responseFilters則取的是descendingIterator,逆序執行
HeaderFilterjava.net.http/jdk/internal/net/http/HeaderFilter.java
/** * A header filter that can examine or modify, typically system headers for * requests before they are sent, and responses before they are returned to the * user. Some ability to resend requests is provided. */ interface HeaderFilter { void request(HttpRequestImpl r, MultiExchange> e) throws IOException; /** * Returns null if response ok to be given to user. Non null is a request * that must be resent and its response given to user. If impl throws an * exception that is returned to user instead. */ HttpRequestImpl response(Response r) throws IOException; }
可以看到HeaderFilter接口定義了request以及response方法
對于response方法,如果對header處理沒問題就返回null,有異常拋異常,需要重新發送的則會返回HttpRequestImpl
HeaderFilter有三個實現類,分別是AuthenticationFilter、RedirectFilter、CookieFilter
AuthenticationFilterjava.net.http/jdk/internal/net/http/AuthenticationFilter.java
@Override public void request(HttpRequestImpl r, MultiExchange> e) throws IOException { // use preemptive authentication if an entry exists. Cache cache = getCache(e); this.exchange = e; // Proxy if (exchange.proxyauth == null) { URI proxyURI = getProxyURI(r); if (proxyURI != null) { CacheEntry ca = cache.get(proxyURI, true); if (ca != null) { exchange.proxyauth = new AuthInfo(true, ca.scheme, null, ca); addBasicCredentials(r, true, ca.value); } } } // Server if (exchange.serverauth == null) { CacheEntry ca = cache.get(r.uri(), false); if (ca != null) { exchange.serverauth = new AuthInfo(true, ca.scheme, null, ca); addBasicCredentials(r, false, ca.value); } } } // TODO: refactor into per auth scheme class private static void addBasicCredentials(HttpRequestImpl r, boolean proxy, PasswordAuthentication pw) { String hdrname = proxy ? "Proxy-Authorization" : "Authorization"; StringBuilder sb = new StringBuilder(128); sb.append(pw.getUserName()).append(":").append(pw.getPassword()); String s = encoder.encodeToString(sb.toString().getBytes(ISO_8859_1)); String value = "Basic " + s; if (proxy) { if (r.isConnect()) { if (!Utils.PROXY_TUNNEL_FILTER.test(hdrname, value)) { Log.logError("{0} disabled", hdrname); return; } } else if (r.proxy() != null) { if (!Utils.PROXY_FILTER.test(hdrname, value)) { Log.logError("{0} disabled", hdrname); return; } } } r.setSystemHeader(hdrname, value); } @Override public HttpRequestImpl response(Response r) throws IOException { Cache cache = getCache(exchange); int status = r.statusCode(); HttpHeaders hdrs = r.headers(); HttpRequestImpl req = r.request(); if (status != UNAUTHORIZED && status != PROXY_UNAUTHORIZED) { // check if any authentication succeeded for first time if (exchange.serverauth != null && !exchange.serverauth.fromcache) { AuthInfo au = exchange.serverauth; cache.store(au.scheme, req.uri(), false, au.credentials); } if (exchange.proxyauth != null && !exchange.proxyauth.fromcache) { AuthInfo au = exchange.proxyauth; URI proxyURI = getProxyURI(req); if (proxyURI != null) { cache.store(au.scheme, proxyURI, true, au.credentials); } } return null; } //...... }
可以用于添加basic authentication的header
RedirectFilterjava.net.http/jdk/internal/net/http/RedirectFilter.java
@Override public synchronized void request(HttpRequestImpl r, MultiExchange> e) throws IOException { this.request = r; this.client = e.client(); this.policy = client.followRedirects(); this.method = r.method(); this.uri = r.uri(); this.exchange = e; } @Override public synchronized HttpRequestImpl response(Response r) throws IOException { return handleResponse(r); } /** * Checks to see if a new request is needed and returns it. * Null means response is ok to return to user. */ private HttpRequestImpl handleResponse(Response r) { int rcode = r.statusCode(); if (rcode == 200 || policy == HttpClient.Redirect.NEVER) { return null; } if (rcode == HTTP_NOT_MODIFIED) return null; if (rcode >= 300 && rcode <= 399) { URI redir = getRedirectedURI(r.headers()); String newMethod = redirectedMethod(rcode, method); Log.logTrace("response code: {0}, redirected URI: {1}", rcode, redir); if (canRedirect(redir) && ++exchange.numberOfRedirects < max_redirects) { Log.logTrace("redirect to: {0} with method: {1}", redir, newMethod); return HttpRequestImpl.newInstanceForRedirection(redir, newMethod, request); } else { Log.logTrace("not redirecting"); return null; } } return null; }
主要用于處理3xx跳轉,這個時候滿足條件的話會返回新的HttpRequestImpl實例
CookieFilterjava.net.http/jdk/internal/net/http/CookieFilter.java
@Override public void request(HttpRequestImpl r, MultiExchange> e) throws IOException { HttpClientImpl client = e.client(); OptionalcookieHandlerOpt = client.cookieHandler(); if (cookieHandlerOpt.isPresent()) { CookieHandler cookieHandler = cookieHandlerOpt.get(); Map > userheaders = r.getUserHeaders().map(); Map > cookies = cookieHandler.get(r.uri(), userheaders); // add the returned cookies HttpHeadersBuilder systemHeadersBuilder = r.getSystemHeadersBuilder(); if (cookies.isEmpty()) { Log.logTrace("Request: no cookie to add for {0}", r.uri()); } else { Log.logTrace("Request: adding cookies for {0}", r.uri()); } for (Map.Entry > entry : cookies.entrySet()) { final String hdrname = entry.getKey(); if (!hdrname.equalsIgnoreCase("Cookie") && !hdrname.equalsIgnoreCase("Cookie2")) continue; List values = entry.getValue(); if (values == null || values.isEmpty()) continue; for (String val : values) { if (Utils.isValidValue(val)) { systemHeadersBuilder.addHeader(hdrname, val); } } } } else { Log.logTrace("Request: No cookie manager found for {0}", r.uri()); } } @Override public HttpRequestImpl response(Response r) throws IOException { HttpHeaders hdrs = r.headers(); HttpRequestImpl request = r.request(); Exchange> e = r.exchange; Log.logTrace("Response: processing cookies for {0}", request.uri()); Optional cookieHandlerOpt = e.client().cookieHandler(); if (cookieHandlerOpt.isPresent()) { CookieHandler cookieHandler = cookieHandlerOpt.get(); Log.logTrace("Response: parsing cookies from {0}", hdrs.map()); cookieHandler.put(request.uri(), hdrs.map()); } else { Log.logTrace("Response: No cookie manager found for {0}", request.uri()); } return null; }
用于請求以及響應的cookie相關的處理
小結FilterFactory使用了簡單的責任鏈模式,getFilterChain方法使用反射實例化各種filter
HeaderFilter定義了request及response兩個方法,分別作用于請求前及獲得響應之后
HeaderFilter有三個實現類,分別是AuthenticationFilter、RedirectFilter、CookieFilter
MultiExchange在responseAsyncImpl方法里頭,執行請求之前調用requestFilters,得到response之后調用responseFilters。其中requestFilters是按順序執行,而responseFilters則取的是descendingIterator,逆序執行
docjava.net.http javadoc
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/77323.html
摘要:序本文主要研究一下的異常實例代碼異常日志如下最后調用這里調用獲取連接如果沒有連接會新創建一個,走的是這里先是調用了獲取連接,然后調用進行連接這里委托給這里如果有設置的話,則會創建一個調用進行連接,如果連接未 序 本文主要研究一下httpclient的connect timeout異常 實例代碼 @Test public void testConnectTimeout()...
摘要:序本文主要研究一下的這里如果的為,則會創建這里如果是的話,參數傳遞的是如果是同步的方法,則傳的值是這里創建了一個,然后調用,這里使用了可以看到這里使用的是的方法注意這個方法是才有的,也是在這里使用的由于默認是使用創建的, 序 本文主要研究一下jdk httpclient的executor HttpClientImpl java.net.http/jdk/internal/net/htt...
摘要:序本文主要研究一下的參數這里有一個類型的變量,用來記錄請求次數另外還有一個,讀取的是值,讀取不到默認取,為進入該方法的時候,調用,遞增請求次數,然后判斷有無超出限制,有則返回帶有異常的,即通過返回如果沒有超出限制,但是執行請求失敗,則 序 本文主要研究一下jdk httpclient的retry參數 DEFAULT_MAX_ATTEMPTS java.net.http/jdk/inte...
摘要:調用計算的時間,這個方法會清理移除并過期的連接除了清理過期的連接外,還通過間接觸發,去清理關閉或異常的連接 序 本文主要研究一下jdk httpclient的ConnectionPool HttpConnection HttpConnection.getConnection java.net.http/jdk/internal/net/http/HttpConnection.java ...
摘要:于是抽時間看了看以后各個版本的特性,做了一個總結。年和公開版本發布,取名為。此后對應版本就是,。發布,是一個重大版本更新。在此之后,就是每六個月發布一次新版本。以上和參考資料聊了一些關于的歷史,下面我們看看各個版本有那些新特性。 【這是 ZY 第 11 篇原創技術文章】 某天在網上閑逛,突然看到有篇介紹 Java 11 新特性的文章,頓時心里一驚,畢竟我對于 Java 的版本認識...
閱讀 1319·2021-11-24 09:38
閱讀 3256·2021-11-22 12:03
閱讀 4158·2021-11-11 10:59
閱讀 2317·2021-09-28 09:36
閱讀 1032·2021-09-09 09:32
閱讀 3412·2021-08-05 10:00
閱讀 2528·2021-07-23 15:30
閱讀 2973·2019-08-30 13:12