Request 代表网络请求的对象,通过 Request.Builder 来构建。默认 GET 请求。
1 2 3 4 5 6 7 8 9 10 11 12
/** * An HTTP request. Instances of this class are immutable if their [body] is null or itself * immutable. */ classRequestinternalconstructor( val url: HttpUrl, val method: String, val headers: Headers, val body: RequestBody?, internalval tags: Map<Class<*>, Any>) {
classMultipartBodyinternalconstructor( privateval boundaryByteString: ByteString, val type: MediaType, val parts: List<Part>) : RequestBody() {
companionobject { val MIXED = "multipart/mixed".toMediaType() val ALTERNATIVE = "multipart/alternative".toMediaType() val DIGEST = "multipart/digest".toMediaType() val PARALLEL = "multipart/parallel".toMediaType() val FORM = "multipart/form-data".toMediaType() } }
/** * An HTTP response. Instances of this class are not immutable: the response body is a one-shot * value that may be consumed only once and then closed. All other properties are immutable. * * This class implements [Closeable]. Closing it simply closes its response body. See * [ResponseBody] for an explanation and examples. */ classResponseinternalconstructor(val request: Request, ..., val body: ResponseBody?, ...){ openclassBuilder{} }
使用 Builder 模式设置参数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
/** A one-shot stream from the origin server to the client application with the raw bytes of the response body. The response body can be consumed only once. */ abstractclassResponseBody : Closeable { funstring(): String = source().use { source -> source.readString(charset = source.readBomAsCharset(charset())) } privatefuncharset() = contentType()?.charset(UTF_8) ?: UTF_8 overridefunclose() = source().closeQuietly() companionobject { fun String.toResponseBody(contentType: MediaType? = null): ResponseBody {} } }
/** * A call is a request that has been prepared for execution. A call can be canceled. As this object * represents a single request/response pair (stream), it cannot be executed twice. */ interfaceCall : Cloneable { funrequest(): Request funexecute(): Response funenqueue(responseCallback: Callback) funcancel() funisExecuted(): Boolean funisCanceled(): Boolean funtimeout(): Timeout publicoverridefunclone(): Call
/** * Attempt to enqueue this async call on [executorService]. This will attempt to clean up * if the executor has been shut down by reporting the call as failed. */ funexecuteOn(executorService: ExecutorService) { var success = false try { executorService.execute(this) success = true } catch (e: RejectedExecutionException) { responseCallback.onFailure(this@RealCall, ioException) } finally { if (!success) { client.dispatcher.finished(this) // This call is no longer running! } } }
/** * Bridge between OkHttp's application and network layers. This class exposes high-level application * layer primitives: connections, requests, responses, and streams. */ classRealCall(val client: OkHttpClient, val originalRequest: Request, val forWebSocket: Boolean) : Call {
internalfungetResponseWithInterceptorChain(): Response { // Build a full stack of interceptors. val interceptors = mutableListOf<Interceptor>() interceptors += client.interceptors interceptors += RetryAndFollowUpInterceptor(client) interceptors += BridgeInterceptor(client.cookieJar) interceptors += CacheInterceptor(client.cache) interceptors += ConnectInterceptor if (!forWebSocket) { interceptors += client.networkInterceptors } interceptors += CallServerInterceptor(forWebSocket)
val chain = RealInterceptorChain( call = this, interceptors = interceptors, index = 0, //... )
val response = chain.proceed(originalRequest) return response } }
/** * A concrete interceptor chain that carries the entire interceptor chain: all application * interceptors, the OkHttp core, all network interceptors, and finally the network caller. */ classRealInterceptorChain( internalval call: RealCall, privateval interceptors: List<Interceptor>, privateval index: Int, //... ) : Interceptor.Chain { overridefunproceed(request: Request): Response {
// 记录当前拦截器执行的次数 calls++
// exchange 不为空说明连接已建立 if (exchange != null) { // 已建立连接后不允许修改域名和端口号 check(exchange.finder.sameHostAndPort(request.url)) { "network interceptor ${interceptors[index - 1]} must retain the same host and port" } // 网络拦截器只允许运行一次 check(calls == 1) { "network interceptor ${interceptors[index - 1]} must call proceed() exactly once" } }
// 创建下一个拦截器的 RealInterceptorChain // Call the next interceptor in the chain. val next = copy(index = index + 1, request = request) val interceptor = interceptors[index]
// 调用下一个拦截器的 intercept() 方法,并传入 Chain val response = interceptor.intercept(next) ?: throw NullPointerException( "interceptor $interceptor returned null")
/** * This interceptor recovers from failures and follows redirects as necessary. It may throw an * [IOException] if the call was canceled. */ classRetryAndFollowUpInterceptor(privateval client: OkHttpClient) : Interceptor { overridefunintercept(chain: Interceptor.Chain): Response { var followUpCount = 0 while (true) { var response: Response try { if (call.isCanceled()) { throw IOException("Canceled") } try { response = realChain.proceed(request) } catch (e: RouteException) { // The attempt to connect via a route failed. The request will not have been sent. //如果不能恢复抛出异常,否则把异常信息保存到集合中 continue } catch (e: IOException) { // An attempt to communicate with a server failed. The request may have been sent. //如果不能恢复抛出异常,否则把异常信息保存到集合中 continue }
// 根据响应码创建新的 Request 或 null val followUp = followUpRequest(response, exchange) if (++followUpCount > MAX_FOLLOW_UPS) { throw ProtocolException("Too many follow-up requests: $followUpCount") } } } }
companionobject { /** * How many redirects and auth challenges should we attempt? Chrome follows 21 redirects; Firefox, * curl, and wget follow 20; Safari follows 16; and HTTP/1.0 recommends 5. */ privateconstval MAX_FOLLOW_UPS = 20 } }
/** * Bridges from application code to network code. First it builds a network request from a user * request. Then it proceeds to call the network. Finally it builds a user response from the network * response. */ classBridgeInterceptor(privateval cookieJar: CookieJar) : Interceptor { overridefunintercept(chain: Interceptor.Chain): Response { val userRequest = chain.request() val requestBuilder = userRequest.newBuilder()
/** Serves requests from the cache and writes responses to the cache. */ classCacheInterceptor(internalval cache: Cache?) : Interceptor { overridefunintercept(chain: Interceptor.Chain): Response { val strategy = CacheStrategy.Factory(now, chain.request(), cacheCandidate).compute() val networkRequest = strategy.networkRequest val cacheResponse = strategy.cacheResponse
// If we're forbidden from using the network and the cache is insufficient, fail. if (networkRequest == null && cacheResponse == null) { //返回 504 错误 }
/** * Opens a connection to the target server and proceeds to the next interceptor. The network might * be used for the returned response, or to validate a cached response with a conditional GET. */ object ConnectInterceptor : Interceptor { val realChain = chain as RealInterceptorChain val exchange = realChain.call.initExchange(chain) val connectedChain = realChain.copy(exchange = exchange) return connectedChain.proceed(realChain.request) }
CallServerInterceptor
负责向服务器发送请求,获取数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/** This is the last interceptor in the chain. It makes a network call to the server. */ classCallServerInterceptor(privateval forWebSocket: Boolean) : Interceptor { overridefunintercept(chain: Interceptor.Chain): Response {
if (!call.call.forWebSocket) { val existingCall = findExistingCallWithHost(call.host) if (existingCall != null) call.reuseCallsPerHostFrom(existingCall) } } promoteAndExecute() }
/** * Promotes eligible calls from [readyAsyncCalls] to [runningAsyncCalls] and runs them on the * executor service. Must not be called with synchronization because executing calls can call * into user code. * * @return true if the dispatcher is currently running calls. */ privatefunpromoteAndExecute(): Boolean { this.assertThreadDoesntHoldLock()
val executableCalls = mutableListOf<AsyncCall>() val isRunning: Boolean synchronized(this) { val i = readyAsyncCalls.iterator() while (i.hasNext()) { val asyncCall = i.next()
// 判断是否达到最大并发数 if (runningAsyncCalls.size >= this.maxRequests) break// Max capacity. // 判断是否达到每个域名最大并发数 if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue// Host max capacity.
/** * Manages reuse of HTTP and HTTP/2 connections for reduced network latency. HTTP requests that * share the same [Address] may share a [Connection]. This class implements the policy * of which connections to keep open for future use. * * @constructor Create a new connection pool with tuning parameters appropriate for a single-user * application. The tuning parameters in this pool are subject to change in future OkHttp releases. * Currently this pool holds up to 5 idle connections which will be evicted after 5 minutes of * inactivity. */ classConnectionPoolinternalconstructor( internalval delegate: RealConnectionPool) {}
/** * Transmits a single HTTP request and a response pair. This layers connection management and events * on [ExchangeCodec], which handles the actual I/O. */ classExchange( internalval call: RealCall, internalval eventListener: EventListener, internalval finder: ExchangeFinder, privateval codec: ExchangeCodec ) {}
/** Encodes HTTP requests and decodes HTTP responses. */ interfaceExchangeCodec{}
/* * 1. Send request headers. * 2. Open a sink to write the request body. Either known or chunked. * 3. Write to and then close that sink. * 4. Read response headers. * 5. Open a source to read the response body. Either fixed-length, chunked or unknown. * 6. Read from and close that source. */ classHttp1ExchangeCodec(...) : ExchangeCodec {}
/** Encode requests and responses using HTTP/2 frames. */ classHttp2ExchangeCodec(...) : ExchangeCodec {}