├── .gitignore ├── .idea ├── .name ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── git │ │ └── dzc │ │ └── okhttputils │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── git │ │ │ └── dzc │ │ │ └── okhttputils │ │ │ ├── DateModule.java │ │ │ ├── MainActivity.java │ │ │ └── Point.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── git │ └── dzc │ └── okhttputils │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── okhttp ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── main │ ├── AndroidManifest.xml │ └── java │ │ └── okhttp3 │ │ ├── Address.java │ │ ├── Authenticator.java │ │ ├── Cache.java │ │ ├── CacheControl.java │ │ ├── Call.java │ │ ├── Callback.java │ │ ├── CertificatePinner.java │ │ ├── Challenge.java │ │ ├── CipherSuite.java │ │ ├── Connection.java │ │ ├── ConnectionPool.java │ │ ├── ConnectionSpec.java │ │ ├── Cookie.java │ │ ├── CookieJar.java │ │ ├── Credentials.java │ │ ├── Dispatcher.java │ │ ├── Dns.java │ │ ├── FormBody.java │ │ ├── Handshake.java │ │ ├── Headers.java │ │ ├── HttpUrl.java │ │ ├── Interceptor.java │ │ ├── MediaType.java │ │ ├── MultipartBody.java │ │ ├── OkHttpClient.java │ │ ├── Protocol.java │ │ ├── RealCall.java │ │ ├── Request.java │ │ ├── RequestBody.java │ │ ├── Response.java │ │ ├── ResponseBody.java │ │ ├── Route.java │ │ ├── TlsVersion.java │ │ └── internal │ │ ├── ConnectionSpecSelector.java │ │ ├── DiskLruCache.java │ │ ├── FaultHidingSink.java │ │ ├── Internal.java │ │ ├── InternalCache.java │ │ ├── NamedRunnable.java │ │ ├── OptionalMethod.java │ │ ├── Platform.java │ │ ├── RouteDatabase.java │ │ ├── Util.java │ │ ├── Version.java │ │ ├── framed │ │ ├── ErrorCode.java │ │ ├── FrameReader.java │ │ ├── FrameWriter.java │ │ ├── FramedConnection.java │ │ ├── FramedStream.java │ │ ├── Header.java │ │ ├── HeadersMode.java │ │ ├── Hpack.java │ │ ├── Http2.java │ │ ├── Huffman.java │ │ ├── NameValueBlockReader.java │ │ ├── Ping.java │ │ ├── PushObserver.java │ │ ├── Settings.java │ │ ├── Spdy3.java │ │ └── Variant.java │ │ ├── http │ │ ├── CacheRequest.java │ │ ├── CacheStrategy.java │ │ ├── HeaderParser.java │ │ ├── Http1xStream.java │ │ ├── Http2xStream.java │ │ ├── HttpDate.java │ │ ├── HttpEngine.java │ │ ├── HttpMethod.java │ │ ├── HttpStream.java │ │ ├── OkHeaders.java │ │ ├── RealResponseBody.java │ │ ├── RequestException.java │ │ ├── RequestLine.java │ │ ├── RetryableSink.java │ │ ├── RouteException.java │ │ ├── RouteSelector.java │ │ ├── StatusLine.java │ │ └── StreamAllocation.java │ │ ├── io │ │ ├── FileSystem.java │ │ └── RealConnection.java │ │ └── tls │ │ ├── DistinguishedNameParser.java │ │ └── OkHostnameVerifier.java │ └── test │ └── java │ └── git │ └── dzc │ └── okhttp │ └── ExampleUnitTest.java ├── okhttputilslib ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── project.properties └── src │ ├── androidTest │ └── java │ │ └── git │ │ └── dzc │ │ └── okhttputilslib │ │ └── ApplicationTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── git │ │ │ └── dzc │ │ │ └── okhttputilslib │ │ │ ├── CacheType.java │ │ │ ├── Callback.java │ │ │ ├── JsonCallback.java │ │ │ ├── OKHttpUtils.java │ │ │ └── UploadListener.java │ └── res │ │ └── values │ │ └── strings.xml │ └── test │ └── java │ └── git │ └── dzc │ └── okhttputilslib │ └── ExampleUnitTest.java └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /okhttputilslib/project.properties 2 | *.iml 3 | .gradle 4 | /local.properties 5 | /.idea/workspace.xml 6 | /.idea/libraries 7 | .DS_Store 8 | /build 9 | /captures 10 | /.idea 11 | /okhttputilslib/local.properties 12 | -------------------------------------------------------------------------------- /.idea/.name: -------------------------------------------------------------------------------- 1 | OKHttpUtils -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 27 | 28 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # # OKHttpUtils 2 | 依赖于okhttp,修改了小部分的okhttp源码,将Cache的部分方法改成public来查询缓存 3 | # 如果需要文件下载,请看这个库[DownloadManager](https://github.com/duzechao/DownloadManager) 4 | 5 | 对OkHttp进行封装,实现了只查询缓存,网络请求失败自动查询本地缓存等功能,结果用Gson解析 6 | 支持文件上传进度回调 7 |
支持gzip,可通过gzip(isOpen)来开启或移除,也可通过在Builder自定义的时候开启(由于okhttp默认开启了gzip, 8 |
所以此选项是对发送到服务器的数据进行gzip,如果服务器不支持,请勿开启) 9 | 支持4种不同的查询方式 10 | 11 | *ONLY_NETWORK 只查询网络数据 12 | 13 | *ONLY_CACHED 只查询本地缓存 14 | 15 | *CACHED_ELSE_NETWORK 先查询本地缓存,如果本地没有,再查询网络数据 16 | 17 | *NETWORK_ELSE_CACHED 先查询网络数据,如果没有,再查询本地缓存 18 | 19 | 20 | # 简单使用方法: 21 | 1. 22 | 23 | okHttpUtils = new OKHttpUtils.Builder(this).build(); 24 | private JsonCallback jsonCallback = new JsonCallback() { 25 | @Override 26 | public void onFailure(Call call, Exception e) { 27 | onFail(e); 28 | } 29 | 30 | @Override 31 | public void onResponse(Call call, final DateModule object) throws IOException { 32 | if(object!=null){ 33 | tv5.post(new Runnable() { 34 | @Override 35 | public void run() { 36 | tv5.setText(object.getResult().getDatetime_1()); 37 | } 38 | 39 | }); 40 | } 41 | } 42 | }; 43 | Request request = new Request.Builder().url(url).build(); 44 | okHttpUtils.request(request, cacheType, jsonCallback); 45 | 46 | 47 | 2.上传文件 48 | 49 | uploadFile(String url, File file, Headers headers, UploadListener uploadListener)//heads如果没有 可传null 50 | 51 | 3.自定义client 52 | 53 | okHttpUtils = new OKHttpUtils.Builder(this).cachedDir(cacheDir).cacheType(CacheType.ONLY_NETWORK).gzip(true).maxCachedSize(1024*10).build(); 54 | 55 | 4.同步请求 56 | 57 | ` 58 | requestAsync()方法,同步请求 59 | ` 60 | 61 | # 可添加拦截器 62 | 通过interceptors()和networkInterceptors()可添加拦截器 63 | 64 | # 添加回调 65 | 调用的时候传入CallBack或JsonCallBack,JsonCallBack使用了Gson解析,JsonCallBack或JsonCallBack>来解析当个module或一个list,支持List等 66 | 67 | # more 68 | 如果所提供的功能不满足需求,可通过getClient()获取到OKHttpClient来使用原生okhttp的功能 69 | 70 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | applicationId "git.dzc.okhttputils" 9 | minSdkVersion 8 10 | targetSdkVersion 22 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.android.support:appcompat-v7:22.2.0' 26 | compile project(':okhttputilslib') 27 | } 28 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/dzc/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/git/dzc/okhttputils/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputils; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/git/dzc/okhttputils/DateModule.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputils; 2 | 3 | /** 4 | * Created by zajo on 15/12/10. 5 | */ 6 | public class DateModule { 7 | /** 8 | * success : 1 9 | * result : {"timestamp":"1449734277","datetime_1":"2015-12-10 15:57:57","datetime_2":"2015年12月10日 15时57分57秒","week_1":"4","week_2":"星期四","week_3":"周四","week_4":"Wednesday"} 10 | */ 11 | 12 | private String success; 13 | /** 14 | * timestamp : 1449734277 15 | * datetime_1 : 2015-12-10 15:57:57 16 | * datetime_2 : 2015年12月10日 15时57分57秒 17 | * week_1 : 4 18 | * week_2 : 星期四 19 | * week_3 : 周四 20 | * week_4 : Wednesday 21 | */ 22 | 23 | private ResultEntity result; 24 | 25 | public void setSuccess(String success) { 26 | this.success = success; 27 | } 28 | 29 | public void setResult(ResultEntity result) { 30 | this.result = result; 31 | } 32 | 33 | public String getSuccess() { 34 | return success; 35 | } 36 | 37 | public ResultEntity getResult() { 38 | return result; 39 | } 40 | 41 | public static class ResultEntity { 42 | private String timestamp; 43 | private String datetime_1; 44 | private String datetime_2; 45 | private String week_1; 46 | private String week_2; 47 | private String week_3; 48 | private String week_4; 49 | 50 | public void setTimestamp(String timestamp) { 51 | this.timestamp = timestamp; 52 | } 53 | 54 | public void setDatetime_1(String datetime_1) { 55 | this.datetime_1 = datetime_1; 56 | } 57 | 58 | public void setDatetime_2(String datetime_2) { 59 | this.datetime_2 = datetime_2; 60 | } 61 | 62 | public void setWeek_1(String week_1) { 63 | this.week_1 = week_1; 64 | } 65 | 66 | public void setWeek_2(String week_2) { 67 | this.week_2 = week_2; 68 | } 69 | 70 | public void setWeek_3(String week_3) { 71 | this.week_3 = week_3; 72 | } 73 | 74 | public void setWeek_4(String week_4) { 75 | this.week_4 = week_4; 76 | } 77 | 78 | public String getTimestamp() { 79 | return timestamp; 80 | } 81 | 82 | public String getDatetime_1() { 83 | return datetime_1; 84 | } 85 | 86 | public String getDatetime_2() { 87 | return datetime_2; 88 | } 89 | 90 | public String getWeek_1() { 91 | return week_1; 92 | } 93 | 94 | public String getWeek_2() { 95 | return week_2; 96 | } 97 | 98 | public String getWeek_3() { 99 | return week_3; 100 | } 101 | 102 | public String getWeek_4() { 103 | return week_4; 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/git/dzc/okhttputils/MainActivity.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputils; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | 8 | 9 | import java.io.IOException; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | import git.dzc.okhttputilslib.CacheType; 13 | import git.dzc.okhttputilslib.JsonCallback; 14 | import git.dzc.okhttputilslib.OKHttpUtils; 15 | import okhttp3.CacheControl; 16 | import okhttp3.Call; 17 | import okhttp3.Request; 18 | 19 | public class MainActivity extends AppCompatActivity { 20 | private String TAG = MainActivity.this.getClass().getSimpleName(); 21 | 22 | private TextView tv1; 23 | private TextView tv2; 24 | private TextView tv3; 25 | private TextView tv4; 26 | private TextView tv5; 27 | private TextView tv6; 28 | 29 | private OKHttpUtils okHttpUtils; 30 | 31 | 32 | @Override 33 | protected void onCreate(Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | setContentView(R.layout.activity_main); 36 | 37 | okHttpUtils = new OKHttpUtils.Builder(this).build(); 38 | 39 | tv1 = (TextView) findViewById(R.id.tv1); 40 | tv2 = (TextView) findViewById(R.id.tv2); 41 | tv3 = (TextView) findViewById(R.id.tv3); 42 | tv4 = (TextView) findViewById(R.id.tv4); 43 | tv5 = (TextView) findViewById(R.id.tv5); 44 | tv6 = (TextView) findViewById(R.id.tv6); 45 | 46 | tv1.setOnClickListener(new View.OnClickListener() { 47 | @Override 48 | public void onClick(View v) { 49 | getData(CacheType.ONLY_NETWORK); 50 | } 51 | }); 52 | 53 | tv2.setOnClickListener(new View.OnClickListener() { 54 | @Override 55 | public void onClick(View v) { 56 | getData(CacheType.ONLY_CACHED); 57 | 58 | } 59 | }); 60 | 61 | tv3.setOnClickListener(new View.OnClickListener() { 62 | @Override 63 | public void onClick(View v) { 64 | getData(CacheType.NETWORK_ELSE_CACHED); 65 | } 66 | }); 67 | 68 | tv4.setOnClickListener(new View.OnClickListener() { 69 | @Override 70 | public void onClick(View v) { 71 | getData(CacheType.CACHED_ELSE_NETWORK); 72 | } 73 | }); 74 | tv6.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | Request request = new Request.Builder().url(url).cacheControl(new CacheControl.Builder().maxAge(5, TimeUnit.SECONDS) 78 | .maxStale(5,TimeUnit.SECONDS).build()).build(); 79 | okHttpUtils.request(request, CacheType.ONLY_NETWORK, jsonCallback); 80 | 81 | } 82 | }); 83 | } 84 | 85 | private String url = "http://api.k780.com:88/?app=life.time&appkey=10003&sign=b59bc3ef6191eb9f747dd4e83c99f2a4&format=json"; 86 | 87 | 88 | private void getData(@CacheType int cacheType){ 89 | tv5.setText(""); 90 | Request request = new Request.Builder().url(url).build(); 91 | okHttpUtils.request(request, cacheType, jsonCallback); 92 | } 93 | private JsonCallback jsonCallback = new JsonCallback() { 94 | @Override 95 | public void onFailure(Call call, Exception e) { 96 | onFail(e); 97 | } 98 | 99 | @Override 100 | public void onResponse(Call call, final DateModule object) throws IOException { 101 | if(object!=null){ 102 | tv5.post(new Runnable() { 103 | @Override 104 | public void run() { 105 | tv5.setText(object.getResult().getDatetime_1()); 106 | } 107 | 108 | }); 109 | } 110 | } 111 | }; 112 | 113 | private void onFail(final Exception e){ 114 | tv5.post(new Runnable() { 115 | @Override 116 | public void run() { 117 | tv5.setText(e.toString()); 118 | } 119 | }); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /app/src/main/java/git/dzc/okhttputils/Point.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputils; 2 | 3 | /** 4 | * Created by dzc on 15/12/11. 5 | */ 6 | public class Point { 7 | private int x; 8 | private int y; 9 | 10 | public Point(int x, int y) { 11 | this.x = x; 12 | this.y = y; 13 | } 14 | 15 | public int getX() { 16 | return x; 17 | } 18 | 19 | public void setX(int x) { 20 | this.x = x; 21 | } 22 | 23 | public int getY() { 24 | return y; 25 | } 26 | 27 | public void setY(int y) { 28 | this.y = y; 29 | } 30 | 31 | @Override 32 | public String toString() { 33 | return "Point [x=" + x + ", y=" + y + "]"; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 17 | 18 | 24 | 25 | 31 | 32 | 38 | 39 | 45 | 46 | 47 | 48 | 53 | 54 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | OKHttpUtils 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/git/dzc/okhttputils/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputils; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | // classpath 'com.android.tools.build:gradle:2.0.0-alpha1' 9 | classpath 'com.android.tools.build:gradle:1.3.0' 10 | 11 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.2' 12 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 13 | 14 | // NOTE: Do not place your application dependencies here; they belong 15 | // in the individual module build.gradle files 16 | } 17 | } 18 | 19 | allprojects { 20 | repositories { 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/duzechao/OKHttpUtils/1c1ee3667737c67d0ff523658bb9acad769030f7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /okhttp/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /okhttp/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 22 5 | buildToolsVersion "22.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 8 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile 'com.android.support:appcompat-v7:22.+' 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | testCompile 'junit:junit:4.12' 25 | compile 'com.squareup.okio:okio:1.6.0' 26 | } 27 | -------------------------------------------------------------------------------- /okhttp/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/dzc/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /okhttp/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Address.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.net.Proxy; 19 | import java.net.ProxySelector; 20 | import java.util.List; 21 | import javax.net.SocketFactory; 22 | import javax.net.ssl.HostnameVerifier; 23 | import javax.net.ssl.SSLSocketFactory; 24 | import okhttp3.internal.Util; 25 | 26 | import static okhttp3.internal.Util.equal; 27 | 28 | /** 29 | * A specification for a connection to an origin server. For simple connections, this is the 30 | * server's hostname and port. If an explicit proxy is requested (or {@linkplain Proxy#NO_PROXY no 31 | * proxy} is explicitly requested), this also includes that proxy information. For secure 32 | * connections the address also includes the SSL socket factory, hostname verifier, and certificate 33 | * pinner. 34 | * 35 | *

HTTP requests that share the same {@code Address} may also share the same {@link Connection}. 36 | */ 37 | public final class Address { 38 | final HttpUrl url; 39 | final Dns dns; 40 | final SocketFactory socketFactory; 41 | final Authenticator proxyAuthenticator; 42 | final List protocols; 43 | final List connectionSpecs; 44 | final ProxySelector proxySelector; 45 | final Proxy proxy; 46 | final SSLSocketFactory sslSocketFactory; 47 | final HostnameVerifier hostnameVerifier; 48 | final CertificatePinner certificatePinner; 49 | 50 | public Address(String uriHost, int uriPort, Dns dns, SocketFactory socketFactory, 51 | SSLSocketFactory sslSocketFactory, HostnameVerifier hostnameVerifier, 52 | CertificatePinner certificatePinner, Authenticator proxyAuthenticator, Proxy proxy, 53 | List protocols, List connectionSpecs, ProxySelector proxySelector) { 54 | this.url = new HttpUrl.Builder() 55 | .scheme(sslSocketFactory != null ? "https" : "http") 56 | .host(uriHost) 57 | .port(uriPort) 58 | .build(); 59 | 60 | if (dns == null) throw new IllegalArgumentException("dns == null"); 61 | this.dns = dns; 62 | 63 | if (socketFactory == null) throw new IllegalArgumentException("socketFactory == null"); 64 | this.socketFactory = socketFactory; 65 | 66 | if (proxyAuthenticator == null) { 67 | throw new IllegalArgumentException("proxyAuthenticator == null"); 68 | } 69 | this.proxyAuthenticator = proxyAuthenticator; 70 | 71 | if (protocols == null) throw new IllegalArgumentException("protocols == null"); 72 | this.protocols = Util.immutableList(protocols); 73 | 74 | if (connectionSpecs == null) throw new IllegalArgumentException("connectionSpecs == null"); 75 | this.connectionSpecs = Util.immutableList(connectionSpecs); 76 | 77 | if (proxySelector == null) throw new IllegalArgumentException("proxySelector == null"); 78 | this.proxySelector = proxySelector; 79 | 80 | this.proxy = proxy; 81 | this.sslSocketFactory = sslSocketFactory; 82 | this.hostnameVerifier = hostnameVerifier; 83 | this.certificatePinner = certificatePinner; 84 | } 85 | 86 | /** 87 | * Returns a URL with the hostname and port of the origin server. The path, query, and fragment of 88 | * this URL are always empty, since they are not significant for planning a route. 89 | */ 90 | public HttpUrl url() { 91 | return url; 92 | } 93 | 94 | /** Returns the service that will be used to resolve IP addresses for hostnames. */ 95 | public Dns dns() { 96 | return dns; 97 | } 98 | 99 | /** Returns the socket factory for new connections. */ 100 | public SocketFactory socketFactory() { 101 | return socketFactory; 102 | } 103 | 104 | /** Returns the client's proxy authenticator. */ 105 | public Authenticator proxyAuthenticator() { 106 | return proxyAuthenticator; 107 | } 108 | 109 | /** 110 | * Returns the protocols the client supports. This method always returns a non-null list that 111 | * contains minimally {@link Protocol#HTTP_1_1}. 112 | */ 113 | public List protocols() { 114 | return protocols; 115 | } 116 | 117 | public List connectionSpecs() { 118 | return connectionSpecs; 119 | } 120 | 121 | /** 122 | * Returns this address's proxy selector. Only used if the proxy is null. If none of this 123 | * selector's proxies are reachable, a direct connection will be attempted. 124 | */ 125 | public ProxySelector proxySelector() { 126 | return proxySelector; 127 | } 128 | 129 | /** 130 | * Returns this address's explicitly-specified HTTP proxy, or null to delegate to the {@linkplain 131 | * #proxySelector proxy selector}. 132 | */ 133 | public Proxy proxy() { 134 | return proxy; 135 | } 136 | 137 | /** Returns the SSL socket factory, or null if this is not an HTTPS address. */ 138 | public SSLSocketFactory sslSocketFactory() { 139 | return sslSocketFactory; 140 | } 141 | 142 | /** Returns the hostname verifier, or null if this is not an HTTPS address. */ 143 | public HostnameVerifier hostnameVerifier() { 144 | return hostnameVerifier; 145 | } 146 | 147 | /** Returns this address's certificate pinner, or null if this is not an HTTPS address. */ 148 | public CertificatePinner certificatePinner() { 149 | return certificatePinner; 150 | } 151 | 152 | @Override public boolean equals(Object other) { 153 | if (other instanceof Address) { 154 | Address that = (Address) other; 155 | return this.url.equals(that.url) 156 | && this.dns.equals(that.dns) 157 | && this.proxyAuthenticator.equals(that.proxyAuthenticator) 158 | && this.protocols.equals(that.protocols) 159 | && this.connectionSpecs.equals(that.connectionSpecs) 160 | && this.proxySelector.equals(that.proxySelector) 161 | && equal(this.proxy, that.proxy) 162 | && equal(this.sslSocketFactory, that.sslSocketFactory) 163 | && equal(this.hostnameVerifier, that.hostnameVerifier) 164 | && equal(this.certificatePinner, that.certificatePinner); 165 | } 166 | return false; 167 | } 168 | 169 | @Override public int hashCode() { 170 | int result = 17; 171 | result = 31 * result + url.hashCode(); 172 | result = 31 * result + dns.hashCode(); 173 | result = 31 * result + proxyAuthenticator.hashCode(); 174 | result = 31 * result + protocols.hashCode(); 175 | result = 31 * result + connectionSpecs.hashCode(); 176 | result = 31 * result + proxySelector.hashCode(); 177 | result = 31 * result + (proxy != null ? proxy.hashCode() : 0); 178 | result = 31 * result + (sslSocketFactory != null ? sslSocketFactory.hashCode() : 0); 179 | result = 31 * result + (hostnameVerifier != null ? hostnameVerifier.hashCode() : 0); 180 | result = 31 * result + (certificatePinner != null ? certificatePinner.hashCode() : 0); 181 | return result; 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Authenticator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Responds to an authentication challenge from either a remote web server or a proxy server. 22 | * Implementations may either attempt to satisfy the challenge by returning a request that includes 23 | * an authorization header, or they may refuse the challenge by returning null. In this case the 24 | * unauthenticated response will be returned to the caller that triggered it. 25 | * 26 | *

When authentication is requested by an origin server, the response code is 401 and the 27 | * implementation should respond with a new request that sets the "Authorization" header. 28 | *

   {@code
29 |  *
30 |  *    String credential = Credentials.basic(...)
31 |  *    return response.request().newBuilder()
32 |  *        .header("Authorization", credential)
33 |  *        .build();
34 |  * }
35 | * 36 | *

Whn authentication is requested by a proxy server, the response code is 407 and the 37 | * implementation should respond with a new request that sets the "Proxy-Authorization" header. 38 | *

   {@code
39 |  *
40 |  *    String credential = Credentials.basic(...)
41 |  *    return response.request().newBuilder()
42 |  *        .header("Proxy-Authorization", credential)
43 |  *        .build();
44 |  * }
45 | * 46 | *

Applications may configure OkHttp with an authenticator for origin servers, or proxy servers, 47 | * or both. 48 | */ 49 | public interface Authenticator { 50 | /** An authenticator that knows no credentials and makes no attempt to authenticate. */ 51 | Authenticator NONE = new Authenticator() { 52 | @Override public Request authenticate(Route route, Response response) { 53 | return null; 54 | } 55 | }; 56 | 57 | /** 58 | * Returns a request that includes a credential to satisfy an authentication challenge in {@code 59 | * response}. Returns null if the challenge cannot be satisfied. 60 | */ 61 | Request authenticate(Route route, Response response) throws IOException; 62 | } 63 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Call.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * A call is a request that has been prepared for execution. A call can be canceled. As this object 22 | * represents a single request/response pair (stream), it cannot be executed twice. 23 | */ 24 | public interface Call { 25 | /** Returns the original request that initiated this call. */ 26 | Request request(); 27 | 28 | /** 29 | * Invokes the request immediately, and blocks until the response can be processed or is in 30 | * error. 31 | * 32 | *

The caller may read the response body with the response's {@link Response#body} method. To 33 | * facilitate connection recycling, callers should always {@link ResponseBody#close() close the 34 | * response body}. 35 | * 36 | *

Note that transport-layer success (receiving a HTTP response code, headers and body) does 37 | * not necessarily indicate application-layer success: {@code response} may still indicate an 38 | * unhappy HTTP response code like 404 or 500. 39 | * 40 | * @throws IOException if the request could not be executed due to cancellation, a connectivity 41 | * problem or timeout. Because networks can fail during an exchange, it is possible that the 42 | * remote server accepted the request before the failure. 43 | * @throws IllegalStateException when the call has already been executed. 44 | */ 45 | Response execute() throws IOException; 46 | 47 | /** 48 | * Schedules the request to be executed at some point in the future. 49 | * 50 | *

The {@link OkHttpClient#dispatcher dispatcher} defines when the request will run: usually 51 | * immediately unless there are several other requests currently being executed. 52 | * 53 | *

This client will later call back {@code responseCallback} with either an HTTP response or a 54 | * failure exception. If you {@link #cancel} a request before it completes the callback will not 55 | * be invoked. 56 | * 57 | * @throws IllegalStateException when the call has already been executed. 58 | */ 59 | void enqueue(Callback responseCallback); 60 | 61 | /** Cancels the request, if possible. Requests that are already complete cannot be canceled. */ 62 | void cancel(); 63 | 64 | /** 65 | * Returns true if this call has been either {@linkplain #execute() executed} or {@linkplain 66 | * #enqueue(Callback) enqueued}. It is an error to execute a call more than once. 67 | */ 68 | boolean isExecuted(); 69 | 70 | boolean isCanceled(); 71 | 72 | interface Factory { 73 | Call newCall(Request request); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Callback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | 20 | public interface Callback { 21 | /** 22 | * Called when the request could not be executed due to cancellation, a connectivity problem or 23 | * timeout. Because networks can fail during an exchange, it is possible that the remote server 24 | * accepted the request before the failure. 25 | */ 26 | void onFailure(Call call, IOException e); 27 | 28 | /** 29 | * Called when the HTTP response was successfully returned by the remote server. The callback may 30 | * proceed to read the response body with {@link Response#body}. The response is still live until 31 | * its response body is closed with {@code response.body().close()}. The recipient of the callback 32 | * may even consume the response body on another thread. 33 | * 34 | *

Note that transport-layer success (receiving a HTTP response code, headers and body) does 35 | * not necessarily indicate application-layer success: {@code response} may still indicate an 36 | * unhappy HTTP response code like 404 or 500. 37 | */ 38 | void onResponse(Call call, Response response) throws IOException; 39 | } 40 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Challenge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import okhttp3.internal.Util; 19 | 20 | /** An RFC 2617 challenge. */ 21 | public final class Challenge { 22 | private final String scheme; 23 | private final String realm; 24 | 25 | public Challenge(String scheme, String realm) { 26 | this.scheme = scheme; 27 | this.realm = realm; 28 | } 29 | 30 | /** Returns the authentication scheme, like {@code Basic}. */ 31 | public String scheme() { 32 | return scheme; 33 | } 34 | 35 | /** Returns the protection space. */ 36 | public String realm() { 37 | return realm; 38 | } 39 | 40 | @Override public boolean equals(Object o) { 41 | return o instanceof Challenge 42 | && Util.equal(scheme, ((Challenge) o).scheme) 43 | && Util.equal(realm, ((Challenge) o).realm); 44 | } 45 | 46 | @Override public int hashCode() { 47 | int result = 29; 48 | result = 31 * result + (realm != null ? realm.hashCode() : 0); 49 | result = 31 * result + (scheme != null ? scheme.hashCode() : 0); 50 | return result; 51 | } 52 | 53 | @Override public String toString() { 54 | return scheme + " realm=\"" + realm + "\""; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Connection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package okhttp3; 18 | 19 | import java.net.Socket; 20 | 21 | /** 22 | * The sockets and streams of an HTTP, HTTPS, or HTTPS+SPDY connection. May be used for multiple 23 | * HTTP request/response exchanges. Connections may be direct to the origin server or via a proxy. 24 | * 25 | *

Typically instances of this class are created, connected and exercised automatically by the 26 | * HTTP client. Applications may use this class to monitor HTTP connections as members of a 27 | * {@linkplain ConnectionPool connection pool}. 28 | * 29 | *

Do not confuse this class with the misnamed {@code HttpURLConnection}, which isn't so much a 30 | * connection as a single request/response exchange. 31 | * 32 | *

Modern TLS

33 | * 34 | *

There are tradeoffs when selecting which options to include when negotiating a secure 35 | * connection to a remote host. Newer TLS options are quite useful: 36 | * 37 | *

    38 | *
  • Server Name Indication (SNI) enables one IP address to negotiate secure connections for 39 | * multiple domain names. 40 | *
  • Application Layer Protocol Negotiation (ALPN) enables the HTTPS port (443) to be used for 41 | * different HTTP and SPDY protocols. 42 | *
43 | * 44 | *

Unfortunately, older HTTPS servers refuse to connect when such options are presented. Rather 45 | * than avoiding these options entirely, this class allows a connection to be attempted with modern 46 | * options and then retried without them should the attempt fail. 47 | * 48 | *

Connection Reuse

49 | * 50 | *

Each connection can carry a varying number streams, depending on the underlying protocol being 51 | * used. HTTP/1.x connections can carry either zero or one streams. HTTP/2 connections can carry any 52 | * number of streams, dynamically configured with {@code SETTINGS_MAX_CONCURRENT_STREAMS}. A 53 | * connection currently carrying zero streams is an idle stream. We keep it alive because reusing an 54 | * existing connection is typically faster than establishing a new one. 55 | * 56 | *

When a single logical call requires multiple streams due to redirects or authorization 57 | * challenges, we prefer to use the same physical connection for all streams in the sequence. There 58 | * are potential performance and behavior consequences to this preference. To support this feature, 59 | * this class separates allocations from streams. An allocation is created by a call, 60 | * used for one or more streams, and then released. An allocated connection won't be stolen by other 61 | * calls while a redirect or authorization challenge is being handled. 62 | * 63 | *

When the maximum concurrent streams limit is reduced, some allocations will be rescinded. 64 | * Attempting to create new streams on these allocations will fail. 65 | * 66 | *

Note that an allocation may be released before its stream is completed. This is intended to 67 | * make bookkeeping easier for the caller: releasing the allocation as soon as the terminal stream 68 | * has been found. But only complete the stream once its data stream has been exhausted. 69 | */ 70 | public interface Connection { 71 | /** Returns the route used by this connection. */ 72 | Route route(); 73 | 74 | /** 75 | * Returns the socket that this connection is using. Returns an {@linkplain 76 | * javax.net.ssl.SSLSocket SSL socket} if this connection is HTTPS. If this is an HTTP/2 or SPDY 77 | * connection the socket may be shared by multiple concurrent calls. 78 | */ 79 | Socket socket(); 80 | 81 | /** 82 | * Returns the TLS handshake used to establish this connection, or null if the connection is not 83 | * HTTPS. 84 | */ 85 | Handshake handshake(); 86 | 87 | /** 88 | * Returns the protocol negotiated by this connection, or {@link Protocol#HTTP_1_1} if no protocol 89 | * has been negotiated. This method returns {@link Protocol#HTTP_1_1} even if the remote peer is 90 | * using {@link Protocol#HTTP_1_0}. 91 | */ 92 | Protocol protocol(); 93 | } 94 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/CookieJar.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.util.Collections; 19 | import java.util.List; 20 | 21 | /** 22 | * Provides policy and persistence for HTTP cookies. 23 | * 24 | *

As policy, implementations of this interface are responsible for selecting which cookies to 25 | * accept and which to reject. A reasonable policy is to reject all cookies, though that may be 26 | * interfere with session-based authentication schemes that require cookies. 27 | * 28 | *

As persistence, implementations of this interface must also provide storage of cookies. Simple 29 | * implementations may store cookies in memory; sophisticated ones may use the file system or 30 | * database to hold accepted cookies. The cookie storage model specifies 32 | * policies for updating and expiring cookies. 33 | */ 34 | public interface CookieJar { 35 | /** A cookie jar that never accepts any cookies. */ 36 | CookieJar NO_COOKIES = new CookieJar() { 37 | @Override public void saveFromResponse(HttpUrl url, List cookies) { 38 | } 39 | 40 | @Override public List loadForRequest(HttpUrl url) { 41 | return Collections.emptyList(); 42 | } 43 | }; 44 | 45 | /** 46 | * Saves {@code cookies} from an HTTP response to this store according to this jar's policy. 47 | * 48 | *

Note that this method may be called a second time for a single HTTP response if the response 49 | * includes a trailer. For this obscure HTTP feature, {@code cookies} contains only the trailer's 50 | * cookies. 51 | */ 52 | void saveFromResponse(HttpUrl url, List cookies); 53 | 54 | /** 55 | * Load cookies from the jar for an HTTP request to {@code url}. This method returns a possibly 56 | * empty list of cookies for the network request. 57 | * 58 | *

Simple implementations will return the accepted cookies that have not yet expired and that 59 | * {@linkplain Cookie#matches match} {@code url}. 60 | */ 61 | List loadForRequest(HttpUrl url); 62 | } 63 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Credentials.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.UnsupportedEncodingException; 19 | import okio.ByteString; 20 | 21 | /** Factory for HTTP authorization credentials. */ 22 | public final class Credentials { 23 | private Credentials() { 24 | } 25 | 26 | /** Returns an auth credential for the Basic scheme. */ 27 | public static String basic(String userName, String password) { 28 | try { 29 | String usernameAndPassword = userName + ":" + password; 30 | byte[] bytes = usernameAndPassword.getBytes("ISO-8859-1"); 31 | String encoded = ByteString.of(bytes).base64(); 32 | return "Basic " + encoded; 33 | } catch (UnsupportedEncodingException e) { 34 | throw new AssertionError(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Dispatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.util.ArrayDeque; 19 | import java.util.ArrayList; 20 | import java.util.Collections; 21 | import java.util.Deque; 22 | import java.util.Iterator; 23 | import java.util.List; 24 | import java.util.concurrent.ExecutorService; 25 | import java.util.concurrent.SynchronousQueue; 26 | import java.util.concurrent.ThreadPoolExecutor; 27 | import java.util.concurrent.TimeUnit; 28 | import okhttp3.RealCall.AsyncCall; 29 | import okhttp3.internal.Util; 30 | 31 | /** 32 | * Policy on when async requests are executed. 33 | * 34 | *

Each dispatcher uses an {@link ExecutorService} to run calls internally. If you supply your 35 | * own executor, it should be able to run {@linkplain #getMaxRequests the configured maximum} number 36 | * of calls concurrently. 37 | */ 38 | public final class Dispatcher { 39 | private int maxRequests = 64; 40 | private int maxRequestsPerHost = 5; 41 | 42 | /** Executes calls. Created lazily. */ 43 | private ExecutorService executorService; 44 | 45 | /** Ready async calls in the order they'll be run. */ 46 | private final Deque readyAsyncCalls = new ArrayDeque<>(); 47 | 48 | /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */ 49 | private final Deque runningAsyncCalls = new ArrayDeque<>(); 50 | 51 | /** Running synchronous calls. Includes canceled calls that haven't finished yet. */ 52 | private final Deque runningSyncCalls = new ArrayDeque<>(); 53 | 54 | public Dispatcher(ExecutorService executorService) { 55 | this.executorService = executorService; 56 | } 57 | 58 | public Dispatcher() { 59 | } 60 | 61 | public synchronized ExecutorService executorService() { 62 | if (executorService == null) { 63 | executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS, 64 | new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false)); 65 | } 66 | return executorService; 67 | } 68 | 69 | /** 70 | * Set the maximum number of requests to execute concurrently. Above this requests queue in 71 | * memory, waiting for the running calls to complete. 72 | * 73 | *

If more than {@code maxRequests} requests are in flight when this is invoked, those requests 74 | * will remain in flight. 75 | */ 76 | public synchronized void setMaxRequests(int maxRequests) { 77 | if (maxRequests < 1) { 78 | throw new IllegalArgumentException("max < 1: " + maxRequests); 79 | } 80 | this.maxRequests = maxRequests; 81 | promoteCalls(); 82 | } 83 | 84 | public synchronized int getMaxRequests() { 85 | return maxRequests; 86 | } 87 | 88 | /** 89 | * Set the maximum number of requests for each host to execute concurrently. This limits requests 90 | * by the URL's host name. Note that concurrent requests to a single IP address may still exceed 91 | * this limit: multiple hostnames may share an IP address or be routed through the same HTTP 92 | * proxy. 93 | * 94 | *

If more than {@code maxRequestsPerHost} requests are in flight when this is invoked, those 95 | * requests will remain in flight. 96 | */ 97 | public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) { 98 | if (maxRequestsPerHost < 1) { 99 | throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost); 100 | } 101 | this.maxRequestsPerHost = maxRequestsPerHost; 102 | promoteCalls(); 103 | } 104 | 105 | public synchronized int getMaxRequestsPerHost() { 106 | return maxRequestsPerHost; 107 | } 108 | 109 | synchronized void enqueue(AsyncCall call) { 110 | if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) { 111 | runningAsyncCalls.add(call); 112 | executorService().execute(call); 113 | } else { 114 | readyAsyncCalls.add(call); 115 | } 116 | } 117 | 118 | /** 119 | * Cancel all calls currently enqueued or executing. Includes calls executed both {@linkplain 120 | * Call#execute() synchronously} and {@linkplain Call#enqueue asynchronously}. 121 | */ 122 | public synchronized void cancelAll() { 123 | for (AsyncCall call : readyAsyncCalls) { 124 | call.cancel(); 125 | } 126 | 127 | for (AsyncCall call : runningAsyncCalls) { 128 | call.cancel(); 129 | } 130 | 131 | for (RealCall call : runningSyncCalls) { 132 | call.cancel(); 133 | } 134 | } 135 | 136 | /** Used by {@code AsyncCall#run} to signal completion. */ 137 | synchronized void finished(AsyncCall call) { 138 | if (!runningAsyncCalls.remove(call)) throw new AssertionError("AsyncCall wasn't running!"); 139 | promoteCalls(); 140 | } 141 | 142 | private void promoteCalls() { 143 | if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity. 144 | if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote. 145 | 146 | for (Iterator i = readyAsyncCalls.iterator(); i.hasNext(); ) { 147 | AsyncCall call = i.next(); 148 | 149 | if (runningCallsForHost(call) < maxRequestsPerHost) { 150 | i.remove(); 151 | runningAsyncCalls.add(call); 152 | executorService().execute(call); 153 | } 154 | 155 | if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity. 156 | } 157 | } 158 | 159 | /** Returns the number of running calls that share a host with {@code call}. */ 160 | private int runningCallsForHost(AsyncCall call) { 161 | int result = 0; 162 | for (AsyncCall c : runningAsyncCalls) { 163 | if (c.host().equals(call.host())) result++; 164 | } 165 | return result; 166 | } 167 | 168 | /** Used by {@code Call#execute} to signal it is in-flight. */ 169 | synchronized void executed(RealCall call) { 170 | runningSyncCalls.add(call); 171 | } 172 | 173 | /** Used by {@code Call#execute} to signal completion. */ 174 | synchronized void finished(Call call) { 175 | if (!runningSyncCalls.remove(call)) throw new AssertionError("Call wasn't in-flight!"); 176 | } 177 | 178 | /** Returns a snapshot of the calls currently awaiting execution. */ 179 | public synchronized List queuedCalls() { 180 | List result = new ArrayList<>(); 181 | for (AsyncCall asyncCall : readyAsyncCalls) { 182 | result.add(asyncCall.get()); 183 | } 184 | return Collections.unmodifiableList(result); 185 | } 186 | 187 | /** Returns a snapshot of the calls currently being executed. */ 188 | public synchronized List runningCalls() { 189 | List result = new ArrayList<>(); 190 | result.addAll(runningSyncCalls); 191 | for (AsyncCall asyncCall : runningAsyncCalls) { 192 | result.add(asyncCall.get()); 193 | } 194 | return Collections.unmodifiableList(result); 195 | } 196 | 197 | public synchronized int queuedCallsCount() { 198 | return readyAsyncCalls.size(); 199 | } 200 | 201 | public synchronized int runningCallsCount() { 202 | return runningAsyncCalls.size() + runningSyncCalls.size(); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Dns.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.net.InetAddress; 19 | import java.net.UnknownHostException; 20 | import java.util.Arrays; 21 | import java.util.List; 22 | 23 | /** 24 | * A domain name service that resolves IP addresses for host names. Most applications will use the 25 | * {@linkplain #SYSTEM system DNS service}, which is the default. Some applications may provide 26 | * their own implementation to use a different DNS server, to prefer IPv6 addresses, to prefer IPv4 27 | * addresses, or to force a specific known IP address. 28 | * 29 | *

Implementations of this interface must be safe for concurrent use. 30 | */ 31 | public interface Dns { 32 | /** 33 | * A DNS that uses {@link InetAddress#getAllByName} to ask the underlying operating system to 34 | * lookup IP addresses. Most custom {@link Dns} implementations should delegate to this instance. 35 | */ 36 | Dns SYSTEM = new Dns() { 37 | @Override public List lookup(String hostname) throws UnknownHostException { 38 | if (hostname == null) throw new UnknownHostException("hostname == null"); 39 | return Arrays.asList(InetAddress.getAllByName(hostname)); 40 | } 41 | }; 42 | 43 | /** 44 | * Returns the IP addresses of {@code hostname}, in the order they will be attempted by OkHttp. If 45 | * a connection to an address fails, OkHttp will retry the connection with the next address until 46 | * either a connection is made, the set of IP addresses is exhausted, or a limit is exceeded. 47 | */ 48 | List lookup(String hostname) throws UnknownHostException; 49 | } 50 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/FormBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import okhttp3.internal.Util; 22 | import okio.Buffer; 23 | import okio.BufferedSink; 24 | 25 | import static okhttp3.HttpUrl.FORM_ENCODE_SET; 26 | import static okhttp3.HttpUrl.percentDecode; 27 | 28 | public final class FormBody extends RequestBody { 29 | private static final MediaType CONTENT_TYPE = 30 | MediaType.parse("application/x-www-form-urlencoded"); 31 | 32 | private final List encodedNames; 33 | private final List encodedValues; 34 | 35 | private FormBody(List encodedNames, List encodedValues) { 36 | this.encodedNames = Util.immutableList(encodedNames); 37 | this.encodedValues = Util.immutableList(encodedValues); 38 | } 39 | 40 | /** The number of key-value pairs in this form-encoded body. */ 41 | public int size() { 42 | return encodedNames.size(); 43 | } 44 | 45 | public String encodedName(int index) { 46 | return encodedNames.get(index); 47 | } 48 | 49 | public String name(int index) { 50 | return percentDecode(encodedName(index), true); 51 | } 52 | 53 | public String encodedValue(int index) { 54 | return encodedValues.get(index); 55 | } 56 | 57 | public String value(int index) { 58 | return percentDecode(encodedValue(index), true); 59 | } 60 | 61 | @Override public MediaType contentType() { 62 | return CONTENT_TYPE; 63 | } 64 | 65 | @Override public long contentLength() { 66 | return writeOrCountBytes(null, true); 67 | } 68 | 69 | @Override public void writeTo(BufferedSink sink) throws IOException { 70 | writeOrCountBytes(sink, false); 71 | } 72 | 73 | /** 74 | * Either writes this request to {@code sink} or measures its content length. We have one method 75 | * do double-duty to make sure the counting and content are consistent, particularly when it comes 76 | * to awkward operations like measuring the encoded length of header strings, or the 77 | * length-in-digits of an encoded integer. 78 | */ 79 | private long writeOrCountBytes(BufferedSink sink, boolean countBytes) { 80 | long byteCount = 0L; 81 | 82 | Buffer buffer; 83 | if (countBytes) { 84 | buffer = new Buffer(); 85 | } else { 86 | buffer = sink.buffer(); 87 | } 88 | 89 | for (int i = 0, size = encodedNames.size(); i < size; i++) { 90 | if (i > 0) buffer.writeByte('&'); 91 | buffer.writeUtf8(encodedNames.get(i)); 92 | buffer.writeByte('='); 93 | buffer.writeUtf8(encodedValues.get(i)); 94 | } 95 | 96 | if (countBytes) { 97 | byteCount = buffer.size(); 98 | buffer.clear(); 99 | } 100 | 101 | return byteCount; 102 | } 103 | 104 | public static final class Builder { 105 | private final List names = new ArrayList<>(); 106 | private final List values = new ArrayList<>(); 107 | 108 | public Builder add(String name, String value) { 109 | names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, false, false, true, true)); 110 | values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, false, false, true, true)); 111 | return this; 112 | } 113 | 114 | public Builder addEncoded(String name, String value) { 115 | names.add(HttpUrl.canonicalize(name, FORM_ENCODE_SET, true, false, true, true)); 116 | values.add(HttpUrl.canonicalize(value, FORM_ENCODE_SET, true, false, true, true)); 117 | return this; 118 | } 119 | 120 | public FormBody build() { 121 | return new FormBody(names, values); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Handshake.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3; 18 | 19 | import java.security.Principal; 20 | import java.security.cert.Certificate; 21 | import java.security.cert.X509Certificate; 22 | import java.util.Collections; 23 | import java.util.List; 24 | import javax.net.ssl.SSLPeerUnverifiedException; 25 | import javax.net.ssl.SSLSession; 26 | import okhttp3.internal.Util; 27 | 28 | /** 29 | * A record of a TLS handshake. For HTTPS clients, the client is local and the remote server 30 | * is its peer. 31 | * 32 | *

This value object describes a completed handshake. Use {@link ConnectionSpec} to set policy 33 | * for new handshakes. 34 | */ 35 | public final class Handshake { 36 | private final TlsVersion tlsVersion; 37 | private final CipherSuite cipherSuite; 38 | private final List peerCertificates; 39 | private final List localCertificates; 40 | 41 | private Handshake(TlsVersion tlsVersion, CipherSuite cipherSuite, 42 | List peerCertificates, List localCertificates) { 43 | this.tlsVersion = tlsVersion; 44 | this.cipherSuite = cipherSuite; 45 | this.peerCertificates = peerCertificates; 46 | this.localCertificates = localCertificates; 47 | } 48 | 49 | public static Handshake get(SSLSession session) { 50 | String cipherSuiteString = session.getCipherSuite(); 51 | if (cipherSuiteString == null) throw new IllegalStateException("cipherSuite == null"); 52 | CipherSuite cipherSuite = CipherSuite.forJavaName(cipherSuiteString); 53 | 54 | String tlsVersionString = session.getProtocol(); 55 | if (tlsVersionString == null) throw new IllegalStateException("tlsVersion == null"); 56 | TlsVersion tlsVersion = TlsVersion.forJavaName(tlsVersionString); 57 | 58 | Certificate[] peerCertificates; 59 | try { 60 | peerCertificates = session.getPeerCertificates(); 61 | } catch (SSLPeerUnverifiedException ignored) { 62 | peerCertificates = null; 63 | } 64 | List peerCertificatesList = peerCertificates != null 65 | ? Util.immutableList(peerCertificates) 66 | : Collections.emptyList(); 67 | 68 | Certificate[] localCertificates = session.getLocalCertificates(); 69 | List localCertificatesList = localCertificates != null 70 | ? Util.immutableList(localCertificates) 71 | : Collections.emptyList(); 72 | 73 | return new Handshake(tlsVersion, cipherSuite, peerCertificatesList, localCertificatesList); 74 | } 75 | 76 | public static Handshake get(TlsVersion tlsVersion, CipherSuite cipherSuite, 77 | List peerCertificates, List localCertificates) { 78 | if (cipherSuite == null) throw new IllegalArgumentException("cipherSuite == null"); 79 | return new Handshake(tlsVersion, cipherSuite, Util.immutableList(peerCertificates), 80 | Util.immutableList(localCertificates)); 81 | } 82 | 83 | /** 84 | * Returns the TLS version used for this connection. May return null if the response was cached 85 | * with a version of OkHttp prior to 3.0. 86 | */ 87 | public TlsVersion tlsVersion() { 88 | return tlsVersion; 89 | } 90 | 91 | /** Returns the cipher suite used for the connection. */ 92 | public CipherSuite cipherSuite() { 93 | return cipherSuite; 94 | } 95 | 96 | /** Returns a possibly-empty list of certificates that identify the remote peer. */ 97 | public List peerCertificates() { 98 | return peerCertificates; 99 | } 100 | 101 | /** Returns the remote peer's principle, or null if that peer is anonymous. */ 102 | public Principal peerPrincipal() { 103 | return !peerCertificates.isEmpty() 104 | ? ((X509Certificate) peerCertificates.get(0)).getSubjectX500Principal() 105 | : null; 106 | } 107 | 108 | /** Returns a possibly-empty list of certificates that identify this peer. */ 109 | public List localCertificates() { 110 | return localCertificates; 111 | } 112 | 113 | /** Returns the local principle, or null if this peer is anonymous. */ 114 | public Principal localPrincipal() { 115 | return !localCertificates.isEmpty() 116 | ? ((X509Certificate) localCertificates.get(0)).getSubjectX500Principal() 117 | : null; 118 | } 119 | 120 | @Override public boolean equals(Object other) { 121 | if (!(other instanceof Handshake)) return false; 122 | Handshake that = (Handshake) other; 123 | return Util.equal(cipherSuite, that.cipherSuite) 124 | && cipherSuite.equals(that.cipherSuite) 125 | && peerCertificates.equals(that.peerCertificates) 126 | && localCertificates.equals(that.localCertificates); 127 | } 128 | 129 | @Override public int hashCode() { 130 | int result = 17; 131 | result = 31 * result + (tlsVersion != null ? tlsVersion.hashCode() : 0); 132 | result = 31 * result + cipherSuite.hashCode(); 133 | result = 31 * result + peerCertificates.hashCode(); 134 | result = 31 * result + localCertificates.hashCode(); 135 | return result; 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Interceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Observes, modifies, and potentially short-circuits requests going out and the corresponding 22 | * requests coming back in. Typically interceptors will be used to add, remove, or transform headers 23 | * on the request or response. 24 | */ 25 | public interface Interceptor { 26 | Response intercept(Chain chain) throws IOException; 27 | 28 | interface Chain { 29 | Request request(); 30 | 31 | Response proceed(Request request) throws IOException; 32 | 33 | Connection connection(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/MediaType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.nio.charset.Charset; 19 | import java.util.Locale; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | /** 24 | * An RFC 2045 Media Type, appropriate to describe 25 | * the content type of an HTTP request or response body. 26 | */ 27 | public final class MediaType { 28 | private static final String TOKEN = "([a-zA-Z0-9-!#$%&'*+.^_`{|}~]+)"; 29 | private static final String QUOTED = "\"([^\"]*)\""; 30 | private static final Pattern TYPE_SUBTYPE = Pattern.compile(TOKEN + "/" + TOKEN); 31 | private static final Pattern PARAMETER = Pattern.compile( 32 | ";\\s*(?:" + TOKEN + "=(?:" + TOKEN + "|" + QUOTED + "))?"); 33 | 34 | private final String mediaType; 35 | private final String type; 36 | private final String subtype; 37 | private final String charset; 38 | 39 | private MediaType(String mediaType, String type, String subtype, String charset) { 40 | this.mediaType = mediaType; 41 | this.type = type; 42 | this.subtype = subtype; 43 | this.charset = charset; 44 | } 45 | 46 | /** 47 | * Returns a media type for {@code string}, or null if {@code string} is not a well-formed media 48 | * type. 49 | */ 50 | public static MediaType parse(String string) { 51 | Matcher typeSubtype = TYPE_SUBTYPE.matcher(string); 52 | if (!typeSubtype.lookingAt()) return null; 53 | String type = typeSubtype.group(1).toLowerCase(Locale.US); 54 | String subtype = typeSubtype.group(2).toLowerCase(Locale.US); 55 | 56 | String charset = null; 57 | Matcher parameter = PARAMETER.matcher(string); 58 | for (int s = typeSubtype.end(); s < string.length(); s = parameter.end()) { 59 | parameter.region(s, string.length()); 60 | if (!parameter.lookingAt()) return null; // This is not a well-formed media type. 61 | 62 | String name = parameter.group(1); 63 | if (name == null || !name.equalsIgnoreCase("charset")) continue; 64 | String charsetParameter = parameter.group(2) != null 65 | ? parameter.group(2) // Value is a token. 66 | : parameter.group(3); // Value is a quoted string. 67 | if (charset != null && !charsetParameter.equalsIgnoreCase(charset)) { 68 | throw new IllegalArgumentException("Multiple different charsets: " + string); 69 | } 70 | charset = charsetParameter; 71 | } 72 | 73 | return new MediaType(string, type, subtype, charset); 74 | } 75 | 76 | /** 77 | * Returns the high-level media type, such as "text", "image", "audio", "video", or 78 | * "application". 79 | */ 80 | public String type() { 81 | return type; 82 | } 83 | 84 | /** 85 | * Returns a specific media subtype, such as "plain" or "png", "mpeg", "mp4" or "xml". 86 | */ 87 | public String subtype() { 88 | return subtype; 89 | } 90 | 91 | /** 92 | * Returns the charset of this media type, or null if this media type doesn't specify a charset. 93 | */ 94 | public Charset charset() { 95 | return charset != null ? Charset.forName(charset) : null; 96 | } 97 | 98 | /** 99 | * Returns the charset of this media type, or {@code defaultValue} if this media type doesn't 100 | * specify a charset. 101 | */ 102 | public Charset charset(Charset defaultValue) { 103 | return charset != null ? Charset.forName(charset) : defaultValue; 104 | } 105 | 106 | /** 107 | * Returns the encoded media type, like "text/plain; charset=utf-8", appropriate for use in a 108 | * Content-Type header. 109 | */ 110 | @Override public String toString() { 111 | return mediaType; 112 | } 113 | 114 | @Override public boolean equals(Object o) { 115 | return o instanceof MediaType && ((MediaType) o).mediaType.equals(mediaType); 116 | } 117 | 118 | @Override public int hashCode() { 119 | return mediaType.hashCode(); 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Protocol.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Protocols that OkHttp implements for ALPN selection. 23 | * 24 | *

Protocol vs Scheme

Despite its name, {@link java.net.URL#getProtocol()} returns the 25 | * {@linkplain java.net.URI#getScheme() scheme} (http, https, etc.) of the URL, not the protocol 26 | * (http/1.1, spdy/3.1, etc.). OkHttp uses the word protocol to identify how HTTP messages 27 | * are framed. 28 | */ 29 | public enum Protocol { 30 | /** 31 | * An obsolete plaintext framing that does not use persistent sockets by default. 32 | */ 33 | HTTP_1_0("http/1.0"), 34 | 35 | /** 36 | * A plaintext framing that includes persistent connections. 37 | * 38 | *

This version of OkHttp implements RFC 39 | * 2616, and tracks revisions to that spec. 40 | */ 41 | HTTP_1_1("http/1.1"), 42 | 43 | /** 44 | * Chromium's binary-framed protocol that includes header compression, multiplexing multiple 45 | * requests on the same socket, and server-push. HTTP/1.1 semantics are layered on SPDY/3. 46 | * 47 | *

This version of OkHttp implements SPDY 3 draft 3.1. Future 49 | * releases of OkHttp may use this identifier for a newer draft of the SPDY spec. 50 | */ 51 | SPDY_3("spdy/3.1"), 52 | 53 | /** 54 | * The IETF's binary-framed protocol that includes header compression, multiplexing multiple 55 | * requests on the same socket, and server-push. HTTP/1.1 semantics are layered on HTTP/2. 56 | * 57 | *

HTTP/2 requires deployments of HTTP/2 that use TLS 1.2 support {@linkplain 58 | * CipherSuite#TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256} , present in Java 8+ and Android 5+. Servers 59 | * that enforce this may send an exception message including the string {@code 60 | * INADEQUATE_SECURITY}. 61 | */ 62 | HTTP_2("h2"); 63 | 64 | private final String protocol; 65 | 66 | Protocol(String protocol) { 67 | this.protocol = protocol; 68 | } 69 | 70 | /** 71 | * Returns the protocol identified by {@code protocol}. 72 | * 73 | * @throws IOException if {@code protocol} is unknown. 74 | */ 75 | public static Protocol get(String protocol) throws IOException { 76 | // Unroll the loop over values() to save an allocation. 77 | if (protocol.equals(HTTP_1_0.protocol)) return HTTP_1_0; 78 | if (protocol.equals(HTTP_1_1.protocol)) return HTTP_1_1; 79 | if (protocol.equals(HTTP_2.protocol)) return HTTP_2; 80 | if (protocol.equals(SPDY_3.protocol)) return SPDY_3; 81 | throw new IOException("Unexpected protocol: " + protocol); 82 | } 83 | 84 | /** 85 | * Returns the string used to identify this protocol for ALPN, like "http/1.1", "spdy/3.1" or 86 | * "h2". 87 | */ 88 | @Override public String toString() { 89 | return protocol; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.net.URI; 19 | import java.net.URL; 20 | import java.util.List; 21 | import okhttp3.internal.http.HttpMethod; 22 | 23 | /** 24 | * An HTTP request. Instances of this class are immutable if their {@link #body} is null or itself 25 | * immutable. 26 | */ 27 | public final class Request { 28 | private final HttpUrl url; 29 | private final String method; 30 | private final Headers headers; 31 | private final RequestBody body; 32 | private final Object tag; 33 | 34 | private volatile URI javaNetUri; // Lazily initialized. 35 | private volatile CacheControl cacheControl; // Lazily initialized. 36 | 37 | private Request(Builder builder) { 38 | this.url = builder.url; 39 | this.method = builder.method; 40 | this.headers = builder.headers.build(); 41 | this.body = builder.body; 42 | this.tag = builder.tag != null ? builder.tag : this; 43 | } 44 | 45 | public HttpUrl url() { 46 | return url; 47 | } 48 | 49 | public String method() { 50 | return method; 51 | } 52 | 53 | public Headers headers() { 54 | return headers; 55 | } 56 | 57 | public String header(String name) { 58 | return headers.get(name); 59 | } 60 | 61 | public List headers(String name) { 62 | return headers.values(name); 63 | } 64 | 65 | public RequestBody body() { 66 | return body; 67 | } 68 | 69 | public Object tag() { 70 | return tag; 71 | } 72 | 73 | public Builder newBuilder() { 74 | return new Builder(this); 75 | } 76 | 77 | /** 78 | * Returns the cache control directives for this response. This is never null, even if this 79 | * response contains no {@code Cache-Control} header. 80 | */ 81 | public CacheControl cacheControl() { 82 | CacheControl result = cacheControl; 83 | return result != null ? result : (cacheControl = CacheControl.parse(headers)); 84 | } 85 | 86 | public boolean isHttps() { 87 | return url.isHttps(); 88 | } 89 | 90 | @Override public String toString() { 91 | return "Request{method=" 92 | + method 93 | + ", url=" 94 | + url 95 | + ", tag=" 96 | + (tag != this ? tag : null) 97 | + '}'; 98 | } 99 | 100 | public static class Builder { 101 | private HttpUrl url; 102 | private String method; 103 | private Headers.Builder headers; 104 | private RequestBody body; 105 | private Object tag; 106 | 107 | public Builder() { 108 | this.method = "GET"; 109 | this.headers = new Headers.Builder(); 110 | } 111 | 112 | private Builder(Request request) { 113 | this.url = request.url; 114 | this.method = request.method; 115 | this.body = request.body; 116 | this.tag = request.tag; 117 | this.headers = request.headers.newBuilder(); 118 | } 119 | 120 | public Builder url(HttpUrl url) { 121 | if (url == null) throw new IllegalArgumentException("url == null"); 122 | this.url = url; 123 | return this; 124 | } 125 | 126 | /** 127 | * Sets the URL target of this request. 128 | * 129 | * @throws IllegalArgumentException if {@code url} is not a valid HTTP or HTTPS URL. Avoid this 130 | * exception by calling {@link HttpUrl#parse}; it returns null for invalid URLs. 131 | */ 132 | public Builder url(String url) { 133 | if (url == null) throw new IllegalArgumentException("url == null"); 134 | 135 | // Silently replace websocket URLs with HTTP URLs. 136 | if (url.regionMatches(true, 0, "ws:", 0, 3)) { 137 | url = "http:" + url.substring(3); 138 | } else if (url.regionMatches(true, 0, "wss:", 0, 4)) { 139 | url = "https:" + url.substring(4); 140 | } 141 | 142 | HttpUrl parsed = HttpUrl.parse(url); 143 | if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url); 144 | return url(parsed); 145 | } 146 | 147 | /** 148 | * Sets the URL target of this request. 149 | * 150 | * @throws IllegalArgumentException if the scheme of {@code url} is not {@code http} or {@code 151 | * https}. 152 | */ 153 | public Builder url(URL url) { 154 | if (url == null) throw new IllegalArgumentException("url == null"); 155 | HttpUrl parsed = HttpUrl.get(url); 156 | if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url); 157 | return url(parsed); 158 | } 159 | 160 | /** 161 | * Sets the header named {@code name} to {@code value}. If this request already has any headers 162 | * with that name, they are all replaced. 163 | */ 164 | public Builder header(String name, String value) { 165 | headers.set(name, value); 166 | return this; 167 | } 168 | 169 | /** 170 | * Adds a header with {@code name} and {@code value}. Prefer this method for multiply-valued 171 | * headers like "Cookie". 172 | * 173 | *

Note that for some headers including {@code Content-Length} and {@code Content-Encoding}, 174 | * OkHttp may replace {@code value} with a header derived from the request body. 175 | */ 176 | public Builder addHeader(String name, String value) { 177 | headers.add(name, value); 178 | return this; 179 | } 180 | 181 | public Builder removeHeader(String name) { 182 | headers.removeAll(name); 183 | return this; 184 | } 185 | 186 | /** Removes all headers on this builder and adds {@code headers}. */ 187 | public Builder headers(Headers headers) { 188 | this.headers = headers.newBuilder(); 189 | return this; 190 | } 191 | 192 | /** 193 | * Sets this request's {@code Cache-Control} header, replacing any cache control headers already 194 | * present. If {@code cacheControl} doesn't define any directives, this clears this request's 195 | * cache-control headers. 196 | */ 197 | public Builder cacheControl(CacheControl cacheControl) { 198 | String value = cacheControl.toString(); 199 | if (value.isEmpty()) return removeHeader("Cache-Control"); 200 | return header("Cache-Control", value); 201 | } 202 | 203 | public Builder get() { 204 | return method("GET", null); 205 | } 206 | 207 | public Builder head() { 208 | return method("HEAD", null); 209 | } 210 | 211 | public Builder post(RequestBody body) { 212 | return method("POST", body); 213 | } 214 | 215 | public Builder delete(RequestBody body) { 216 | return method("DELETE", body); 217 | } 218 | 219 | public Builder delete() { 220 | return delete(RequestBody.create(null, new byte[0])); 221 | } 222 | 223 | public Builder put(RequestBody body) { 224 | return method("PUT", body); 225 | } 226 | 227 | public Builder patch(RequestBody body) { 228 | return method("PATCH", body); 229 | } 230 | 231 | public Builder method(String method, RequestBody body) { 232 | if (method == null || method.length() == 0) { 233 | throw new IllegalArgumentException("method == null || method.length() == 0"); 234 | } 235 | if (body != null && !HttpMethod.permitsRequestBody(method)) { 236 | throw new IllegalArgumentException("method " + method + " must not have a request body."); 237 | } 238 | if (body == null && HttpMethod.requiresRequestBody(method)) { 239 | throw new IllegalArgumentException("method " + method + " must have a request body."); 240 | } 241 | this.method = method; 242 | this.body = body; 243 | return this; 244 | } 245 | 246 | /** 247 | * Attaches {@code tag} to the request. It can be used later to cancel the request. If the tag 248 | * is unspecified or null, the request is canceled by using the request itself as the tag. 249 | */ 250 | public Builder tag(Object tag) { 251 | this.tag = tag; 252 | return this; 253 | } 254 | 255 | public Request build() { 256 | if (url == null) throw new IllegalStateException("url == null"); 257 | return new Request(this); 258 | } 259 | } 260 | } 261 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/RequestBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.File; 19 | import java.io.IOException; 20 | import java.nio.charset.Charset; 21 | import okhttp3.internal.Util; 22 | import okio.BufferedSink; 23 | import okio.ByteString; 24 | import okio.Okio; 25 | import okio.Source; 26 | 27 | public abstract class RequestBody { 28 | /** Returns the Content-Type header for this body. */ 29 | public abstract MediaType contentType(); 30 | 31 | /** 32 | * Returns the number of bytes that will be written to {@code out} in a call to {@link #writeTo}, 33 | * or -1 if that count is unknown. 34 | */ 35 | public long contentLength() throws IOException { 36 | return -1; 37 | } 38 | 39 | /** Writes the content of this request to {@code out}. */ 40 | public abstract void writeTo(BufferedSink sink) throws IOException; 41 | 42 | /** 43 | * Returns a new request body that transmits {@code content}. If {@code contentType} is non-null 44 | * and lacks a charset, this will use UTF-8. 45 | */ 46 | public static RequestBody create(MediaType contentType, String content) { 47 | Charset charset = Util.UTF_8; 48 | if (contentType != null) { 49 | charset = contentType.charset(); 50 | if (charset == null) { 51 | charset = Util.UTF_8; 52 | contentType = MediaType.parse(contentType + "; charset=utf-8"); 53 | } 54 | } 55 | byte[] bytes = content.getBytes(charset); 56 | return create(contentType, bytes); 57 | } 58 | 59 | /** Returns a new request body that transmits {@code content}. */ 60 | public static RequestBody create(final MediaType contentType, final ByteString content) { 61 | return new RequestBody() { 62 | @Override public MediaType contentType() { 63 | return contentType; 64 | } 65 | 66 | @Override public long contentLength() throws IOException { 67 | return content.size(); 68 | } 69 | 70 | @Override public void writeTo(BufferedSink sink) throws IOException { 71 | sink.write(content); 72 | } 73 | }; 74 | } 75 | 76 | /** Returns a new request body that transmits {@code content}. */ 77 | public static RequestBody create(final MediaType contentType, final byte[] content) { 78 | return create(contentType, content, 0, content.length); 79 | } 80 | 81 | /** Returns a new request body that transmits {@code content}. */ 82 | public static RequestBody create(final MediaType contentType, final byte[] content, 83 | final int offset, final int byteCount) { 84 | if (content == null) throw new NullPointerException("content == null"); 85 | Util.checkOffsetAndCount(content.length, offset, byteCount); 86 | return new RequestBody() { 87 | @Override public MediaType contentType() { 88 | return contentType; 89 | } 90 | 91 | @Override public long contentLength() { 92 | return byteCount; 93 | } 94 | 95 | @Override public void writeTo(BufferedSink sink) throws IOException { 96 | sink.write(content, offset, byteCount); 97 | } 98 | }; 99 | } 100 | 101 | /** Returns a new request body that transmits the content of {@code file}. */ 102 | public static RequestBody create(final MediaType contentType, final File file) { 103 | if (file == null) throw new NullPointerException("content == null"); 104 | 105 | return new RequestBody() { 106 | @Override public MediaType contentType() { 107 | return contentType; 108 | } 109 | 110 | @Override public long contentLength() { 111 | return file.length(); 112 | } 113 | 114 | @Override public void writeTo(BufferedSink sink) throws IOException { 115 | Source source = null; 116 | try { 117 | source = Okio.source(file); 118 | sink.writeAll(source); 119 | } finally { 120 | Util.closeQuietly(source); 121 | } 122 | } 123 | }; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/ResponseBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.io.Closeable; 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.io.InputStreamReader; 22 | import java.io.Reader; 23 | import java.nio.charset.Charset; 24 | import okhttp3.internal.Util; 25 | import okio.Buffer; 26 | import okio.BufferedSource; 27 | 28 | import static okhttp3.internal.Util.UTF_8; 29 | 30 | /** 31 | * A one-shot stream from the origin server to the client application with the raw bytes of the 32 | * response body. Each response body is supported by an active connection to the webserver. This 33 | * imposes both obligations and limits on the client application. 34 | * 35 | *

The response body must be closed.

36 | * 37 | *

Each response body is backed by a limited resource like a socket (live network responses) or 38 | * an open file (for cached responses). Failing to close the response body will leak these resources 39 | * and may ultimately cause the application to slow down or crash. Close the response body by 40 | * calling either {@link ResponseBody#close close()}, {@link InputStream#close() 41 | * byteStream().close()}, or {@link Reader#close() reader().close()}. The {@link #bytes()} and 42 | * {@link #string()} methods both close the response body automatically. 43 | * 44 | *

The response body can be consumed only once.

45 | * 46 | *

This class may be used to stream very large responses. For example, it is possible to use this 47 | * class to read a response that is larger than the entire memory allocated to the current process. 48 | * It can even stream a response larger than the total storage on the current device, which is a 49 | * common requirement for video streaming applications. 50 | * 51 | *

Because this class does not buffer the full response in memory, the application may not 52 | * re-read the bytes of the response. Use this one shot to read the entire response into memory with 53 | * {@link #bytes()} or {@link #string()}. Or stream the response with either {@link #source()}, 54 | * {@link #byteStream()}, or {@link #charStream()}. 55 | */ 56 | public abstract class ResponseBody implements Closeable { 57 | /** Multiple calls to {@link #charStream()} must return the same instance. */ 58 | private Reader reader; 59 | 60 | public abstract MediaType contentType(); 61 | 62 | /** 63 | * Returns the number of bytes in that will returned by {@link #bytes}, or {@link #byteStream}, or 64 | * -1 if unknown. 65 | */ 66 | public abstract long contentLength(); 67 | 68 | public final InputStream byteStream() { 69 | return source().inputStream(); 70 | } 71 | 72 | public abstract BufferedSource source(); 73 | 74 | public final byte[] bytes() throws IOException { 75 | long contentLength = contentLength(); 76 | if (contentLength > Integer.MAX_VALUE) { 77 | throw new IOException("Cannot buffer entire body for content length: " + contentLength); 78 | } 79 | 80 | BufferedSource source = source(); 81 | byte[] bytes; 82 | try { 83 | bytes = source.readByteArray(); 84 | } finally { 85 | Util.closeQuietly(source); 86 | } 87 | if (contentLength != -1 && contentLength != bytes.length) { 88 | throw new IOException("Content-Length and stream length disagree"); 89 | } 90 | return bytes; 91 | } 92 | 93 | /** 94 | * Returns the response as a character stream decoded with the charset of the Content-Type header. 95 | * If that header is either absent or lacks a charset, this will attempt to decode the response 96 | * body as UTF-8. 97 | */ 98 | public final Reader charStream() { 99 | Reader r = reader; 100 | return r != null ? r : (reader = new InputStreamReader(byteStream(), charset())); 101 | } 102 | 103 | /** 104 | * Returns the response as a string decoded with the charset of the Content-Type header. If that 105 | * header is either absent or lacks a charset, this will attempt to decode the response body as 106 | * UTF-8. 107 | */ 108 | public final String string() throws IOException { 109 | return new String(bytes(), charset().name()); 110 | } 111 | 112 | private Charset charset() { 113 | MediaType contentType = contentType(); 114 | return contentType != null ? contentType.charset(UTF_8) : UTF_8; 115 | } 116 | 117 | @Override public void close() { 118 | Util.closeQuietly(source()); 119 | } 120 | 121 | /** 122 | * Returns a new response body that transmits {@code content}. If {@code contentType} is non-null 123 | * and lacks a charset, this will use UTF-8. 124 | */ 125 | public static ResponseBody create(MediaType contentType, String content) { 126 | Charset charset = UTF_8; 127 | if (contentType != null) { 128 | charset = contentType.charset(); 129 | if (charset == null) { 130 | charset = UTF_8; 131 | contentType = MediaType.parse(contentType + "; charset=utf-8"); 132 | } 133 | } 134 | Buffer buffer = new Buffer().writeString(content, charset); 135 | return create(contentType, buffer.size(), buffer); 136 | } 137 | 138 | /** Returns a new response body that transmits {@code content}. */ 139 | public static ResponseBody create(final MediaType contentType, byte[] content) { 140 | Buffer buffer = new Buffer().write(content); 141 | return create(contentType, content.length, buffer); 142 | } 143 | 144 | /** Returns a new response body that transmits {@code content}. */ 145 | public static ResponseBody create( 146 | final MediaType contentType, final long contentLength, final BufferedSource content) { 147 | if (content == null) throw new NullPointerException("source == null"); 148 | return new ResponseBody() { 149 | @Override public MediaType contentType() { 150 | return contentType; 151 | } 152 | 153 | @Override public long contentLength() { 154 | return contentLength; 155 | } 156 | 157 | @Override public BufferedSource source() { 158 | return content; 159 | } 160 | }; 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/Route.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | import java.net.InetSocketAddress; 19 | import java.net.Proxy; 20 | 21 | /** 22 | * The concrete route used by a connection to reach an abstract origin server. When creating a 23 | * connection the client has many options: 24 | * 25 | *

    26 | *
  • HTTP proxy: a proxy server may be explicitly configured for the client. 27 | * Otherwise the {@linkplain java.net.ProxySelector proxy selector} is used. It may return 28 | * multiple proxies to attempt. 29 | *
  • IP address: whether connecting directly to an origin server or a proxy, 30 | * opening a socket requires an IP address. The DNS server may return multiple IP addresses 31 | * to attempt. 32 | *
33 | * 34 | *

Each route is a specific selection of these options. 35 | */ 36 | public final class Route { 37 | final Address address; 38 | final Proxy proxy; 39 | final InetSocketAddress inetSocketAddress; 40 | 41 | public Route(Address address, Proxy proxy, InetSocketAddress inetSocketAddress) { 42 | if (address == null) { 43 | throw new NullPointerException("address == null"); 44 | } 45 | if (proxy == null) { 46 | throw new NullPointerException("proxy == null"); 47 | } 48 | if (inetSocketAddress == null) { 49 | throw new NullPointerException("inetSocketAddress == null"); 50 | } 51 | this.address = address; 52 | this.proxy = proxy; 53 | this.inetSocketAddress = inetSocketAddress; 54 | } 55 | 56 | public Address address() { 57 | return address; 58 | } 59 | 60 | /** 61 | * Returns the {@link Proxy} of this route. 62 | * 63 | * Warning: This may disagree with {@link Address#proxy} when it is null. When 64 | * the address's proxy is null, the proxy selector is used. 65 | */ 66 | public Proxy proxy() { 67 | return proxy; 68 | } 69 | 70 | public InetSocketAddress socketAddress() { 71 | return inetSocketAddress; 72 | } 73 | 74 | /** 75 | * Returns true if this route tunnels HTTPS through an HTTP proxy. See RFC 2817, Section 5.2. 77 | */ 78 | public boolean requiresTunnel() { 79 | return address.sslSocketFactory != null && proxy.type() == Proxy.Type.HTTP; 80 | } 81 | 82 | @Override public boolean equals(Object obj) { 83 | if (obj instanceof Route) { 84 | Route other = (Route) obj; 85 | return address.equals(other.address) 86 | && proxy.equals(other.proxy) 87 | && inetSocketAddress.equals(other.inetSocketAddress); 88 | } 89 | return false; 90 | } 91 | 92 | @Override public int hashCode() { 93 | int result = 17; 94 | result = 31 * result + address.hashCode(); 95 | result = 31 * result + proxy.hashCode(); 96 | result = 31 * result + inetSocketAddress.hashCode(); 97 | return result; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/TlsVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3; 17 | 18 | /** 19 | * Versions of TLS that can be offered when negotiating a secure socket. See {@link 20 | * javax.net.ssl.SSLSocket#setEnabledProtocols}. 21 | */ 22 | public enum TlsVersion { 23 | TLS_1_2("TLSv1.2"), // 2008. 24 | TLS_1_1("TLSv1.1"), // 2006. 25 | TLS_1_0("TLSv1"), // 1999. 26 | SSL_3_0("SSLv3"), // 1996. 27 | ; 28 | 29 | final String javaName; 30 | 31 | TlsVersion(String javaName) { 32 | this.javaName = javaName; 33 | } 34 | 35 | public static TlsVersion forJavaName(String javaName) { 36 | switch (javaName) { 37 | case "TLSv1.2": 38 | return TLS_1_2; 39 | case "TLSv1.1": 40 | return TLS_1_1; 41 | case "TLSv1": 42 | return TLS_1_0; 43 | case "SSLv3": 44 | return SSL_3_0; 45 | } 46 | throw new IllegalArgumentException("Unexpected TLS version: " + javaName); 47 | } 48 | 49 | public String javaName() { 50 | return javaName; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/ConnectionSpecSelector.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal; 18 | 19 | import java.io.IOException; 20 | import java.io.InterruptedIOException; 21 | import java.net.ProtocolException; 22 | import java.net.UnknownServiceException; 23 | import java.security.cert.CertificateException; 24 | import java.util.Arrays; 25 | import java.util.List; 26 | import javax.net.ssl.SSLHandshakeException; 27 | import javax.net.ssl.SSLPeerUnverifiedException; 28 | import javax.net.ssl.SSLProtocolException; 29 | import javax.net.ssl.SSLSocket; 30 | import okhttp3.ConnectionSpec; 31 | 32 | /** 33 | * Handles the connection spec fallback strategy: When a secure socket connection fails due to a 34 | * handshake / protocol problem the connection may be retried with different protocols. Instances 35 | * are stateful and should be created and used for a single connection attempt. 36 | */ 37 | public final class ConnectionSpecSelector { 38 | 39 | private final List connectionSpecs; 40 | private int nextModeIndex; 41 | private boolean isFallbackPossible; 42 | private boolean isFallback; 43 | 44 | public ConnectionSpecSelector(List connectionSpecs) { 45 | this.nextModeIndex = 0; 46 | this.connectionSpecs = connectionSpecs; 47 | } 48 | 49 | /** 50 | * Configures the supplied {@link SSLSocket} to connect to the specified host using an appropriate 51 | * {@link ConnectionSpec}. Returns the chosen {@link ConnectionSpec}, never {@code null}. 52 | * 53 | * @throws IOException if the socket does not support any of the TLS modes available 54 | */ 55 | public ConnectionSpec configureSecureSocket(SSLSocket sslSocket) throws IOException { 56 | ConnectionSpec tlsConfiguration = null; 57 | for (int i = nextModeIndex, size = connectionSpecs.size(); i < size; i++) { 58 | ConnectionSpec connectionSpec = connectionSpecs.get(i); 59 | if (connectionSpec.isCompatible(sslSocket)) { 60 | tlsConfiguration = connectionSpec; 61 | nextModeIndex = i + 1; 62 | break; 63 | } 64 | } 65 | 66 | if (tlsConfiguration == null) { 67 | // This may be the first time a connection has been attempted and the socket does not support 68 | // any the required protocols, or it may be a retry (but this socket supports fewer 69 | // protocols than was suggested by a prior socket). 70 | throw new UnknownServiceException( 71 | "Unable to find acceptable protocols. isFallback=" + isFallback 72 | + ", modes=" + connectionSpecs 73 | + ", supported protocols=" + Arrays.toString(sslSocket.getEnabledProtocols())); 74 | } 75 | 76 | isFallbackPossible = isFallbackPossible(sslSocket); 77 | 78 | Internal.instance.apply(tlsConfiguration, sslSocket, isFallback); 79 | 80 | return tlsConfiguration; 81 | } 82 | 83 | /** 84 | * Reports a failure to complete a connection. Determines the next {@link ConnectionSpec} to try, 85 | * if any. 86 | * 87 | * @return {@code true} if the connection should be retried using {@link 88 | * #configureSecureSocket(SSLSocket)} or {@code false} if not 89 | */ 90 | public boolean connectionFailed(IOException e) { 91 | // Any future attempt to connect using this strategy will be a fallback attempt. 92 | isFallback = true; 93 | 94 | if (!isFallbackPossible) { 95 | return false; 96 | } 97 | 98 | // If there was a protocol problem, don't recover. 99 | if (e instanceof ProtocolException) { 100 | return false; 101 | } 102 | 103 | // If there was an interruption or timeout (SocketTimeoutException), don't recover. 104 | // For the socket connect timeout case we do not try the same host with a different 105 | // ConnectionSpec: we assume it is unreachable. 106 | if (e instanceof InterruptedIOException) { 107 | return false; 108 | } 109 | 110 | // Look for known client-side or negotiation errors that are unlikely to be fixed by trying 111 | // again with a different connection spec. 112 | if (e instanceof SSLHandshakeException) { 113 | // If the problem was a CertificateException from the X509TrustManager, 114 | // do not retry. 115 | if (e.getCause() instanceof CertificateException) { 116 | return false; 117 | } 118 | } 119 | if (e instanceof SSLPeerUnverifiedException) { 120 | // e.g. a certificate pinning error. 121 | return false; 122 | } 123 | 124 | // On Android, SSLProtocolExceptions can be caused by TLS_FALLBACK_SCSV failures, which means we 125 | // retry those when we probably should not. 126 | return (e instanceof SSLHandshakeException || e instanceof SSLProtocolException); 127 | } 128 | 129 | /** 130 | * Returns {@code true} if any later {@link ConnectionSpec} in the fallback strategy looks 131 | * possible based on the supplied {@link SSLSocket}. It assumes that a future socket will have the 132 | * same capabilities as the supplied socket. 133 | */ 134 | private boolean isFallbackPossible(SSLSocket socket) { 135 | for (int i = nextModeIndex; i < connectionSpecs.size(); i++) { 136 | if (connectionSpecs.get(i).isCompatible(socket)) { 137 | return true; 138 | } 139 | } 140 | return false; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/FaultHidingSink.java: -------------------------------------------------------------------------------- 1 | package okhttp3.internal; 2 | 3 | import java.io.IOException; 4 | import okio.Buffer; 5 | import okio.ForwardingSink; 6 | import okio.Sink; 7 | 8 | /** A sink that never throws IOExceptions, even if the underlying sink does. */ 9 | class FaultHidingSink extends ForwardingSink { 10 | private boolean hasErrors; 11 | 12 | public FaultHidingSink(Sink delegate) { 13 | super(delegate); 14 | } 15 | 16 | @Override public void write(Buffer source, long byteCount) throws IOException { 17 | if (hasErrors) { 18 | source.skip(byteCount); 19 | return; 20 | } 21 | try { 22 | super.write(source, byteCount); 23 | } catch (IOException e) { 24 | hasErrors = true; 25 | onException(e); 26 | } 27 | } 28 | 29 | @Override public void flush() throws IOException { 30 | if (hasErrors) return; 31 | try { 32 | super.flush(); 33 | } catch (IOException e) { 34 | hasErrors = true; 35 | onException(e); 36 | } 37 | } 38 | 39 | @Override public void close() throws IOException { 40 | if (hasErrors) return; 41 | try { 42 | super.close(); 43 | } catch (IOException e) { 44 | hasErrors = true; 45 | onException(e); 46 | } 47 | } 48 | 49 | protected void onException(IOException e) { 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/Internal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal; 17 | 18 | import java.net.MalformedURLException; 19 | import java.net.UnknownHostException; 20 | import java.util.logging.Logger; 21 | import javax.net.ssl.SSLSocket; 22 | import okhttp3.Address; 23 | import okhttp3.Call; 24 | import okhttp3.Callback; 25 | import okhttp3.ConnectionPool; 26 | import okhttp3.ConnectionSpec; 27 | import okhttp3.Headers; 28 | import okhttp3.HttpUrl; 29 | import okhttp3.OkHttpClient; 30 | import okhttp3.internal.http.StreamAllocation; 31 | import okhttp3.internal.io.RealConnection; 32 | 33 | /** 34 | * Escalate internal APIs in {@code okhttp3} so they can be used from OkHttp's implementation 35 | * packages. The only implementation of this interface is in {@link OkHttpClient}. 36 | */ 37 | public abstract class Internal { 38 | public static final Logger logger = Logger.getLogger(OkHttpClient.class.getName()); 39 | 40 | public static void initializeInstanceForTests() { 41 | // Needed in tests to ensure that the instance is actually pointing to something. 42 | new OkHttpClient(); 43 | } 44 | 45 | public static Internal instance; 46 | 47 | public abstract void addLenient(Headers.Builder builder, String line); 48 | 49 | public abstract void addLenient(Headers.Builder builder, String name, String value); 50 | 51 | public abstract void setCache(OkHttpClient.Builder builder, InternalCache internalCache); 52 | 53 | public abstract InternalCache internalCache(OkHttpClient client); 54 | 55 | public abstract RealConnection get( 56 | ConnectionPool pool, Address address, StreamAllocation streamAllocation); 57 | 58 | public abstract void put(ConnectionPool pool, RealConnection connection); 59 | 60 | public abstract boolean connectionBecameIdle(ConnectionPool pool, RealConnection connection); 61 | 62 | public abstract RouteDatabase routeDatabase(ConnectionPool connectionPool); 63 | 64 | public abstract void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, 65 | boolean isFallback); 66 | 67 | public abstract HttpUrl getHttpUrlChecked(String url) 68 | throws MalformedURLException, UnknownHostException; 69 | 70 | // TODO delete the following when web sockets move into the main package. 71 | public abstract void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket); 72 | 73 | public abstract StreamAllocation callEngineGetStreamAllocation(Call call); 74 | } 75 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/InternalCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal; 17 | 18 | import java.io.IOException; 19 | import okhttp3.Request; 20 | import okhttp3.Response; 21 | import okhttp3.internal.http.CacheRequest; 22 | import okhttp3.internal.http.CacheStrategy; 23 | 24 | /** 25 | * OkHttp's internal cache interface. Applications shouldn't implement this: instead use {@link 26 | * okhttp3.Cache}. 27 | */ 28 | public interface InternalCache { 29 | Response get(Request request) throws IOException; 30 | 31 | CacheRequest put(Response response) throws IOException; 32 | 33 | /** 34 | * Remove any cache entries for the supplied {@code request}. This is invoked when the client 35 | * invalidates the cache, such as when making POST requests. 36 | */ 37 | void remove(Request request) throws IOException; 38 | 39 | /** 40 | * Handles a conditional request hit by updating the stored cache response with the headers from 41 | * {@code network}. The cached response body is not updated. If the stored response has changed 42 | * since {@code cached} was returned, this does nothing. 43 | */ 44 | void update(Response cached, Response network) throws IOException; 45 | 46 | /** Track an conditional GET that was satisfied by this cache. */ 47 | void trackConditionalCacheHit(); 48 | 49 | /** Track an HTTP response being satisfied with {@code cacheStrategy}. */ 50 | void trackResponse(CacheStrategy cacheStrategy); 51 | } 52 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/NamedRunnable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal; 18 | 19 | /** 20 | * Runnable implementation which always sets its thread name. 21 | */ 22 | public abstract class NamedRunnable implements Runnable { 23 | protected final String name; 24 | 25 | public NamedRunnable(String format, Object... args) { 26 | this.name = String.format(format, args); 27 | } 28 | 29 | @Override public final void run() { 30 | String oldName = Thread.currentThread().getName(); 31 | Thread.currentThread().setName(name); 32 | try { 33 | execute(); 34 | } finally { 35 | Thread.currentThread().setName(oldName); 36 | } 37 | } 38 | 39 | protected abstract void execute(); 40 | } 41 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/OptionalMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package okhttp3.internal; 19 | 20 | import java.lang.reflect.InvocationTargetException; 21 | import java.lang.reflect.Method; 22 | import java.lang.reflect.Modifier; 23 | 24 | /** 25 | * Duck-typing for methods: Represents a method that may or may not be present on an object. 26 | * 27 | * @param the type of the object the method might be on, typically an interface or base class 28 | */ 29 | class OptionalMethod { 30 | 31 | /** The return type of the method. null means "don't care". */ 32 | private final Class returnType; 33 | 34 | private final String methodName; 35 | 36 | private final Class[] methodParams; 37 | 38 | /** 39 | * Creates an optional method. 40 | * 41 | * @param returnType the return type to required, null if it does not matter 42 | * @param methodName the name of the method 43 | * @param methodParams the method parameter types 44 | */ 45 | public OptionalMethod(Class returnType, String methodName, Class... methodParams) { 46 | this.returnType = returnType; 47 | this.methodName = methodName; 48 | this.methodParams = methodParams; 49 | } 50 | 51 | /** 52 | * Returns true if the method exists on the supplied {@code target}. 53 | */ 54 | public boolean isSupported(T target) { 55 | return getMethod(target.getClass()) != null; 56 | } 57 | 58 | /** 59 | * Invokes the method on {@code target} with {@code args}. If the method does not exist or is not 60 | * public then {@code null} is returned. See also {@link #invokeOptionalWithoutCheckedException}. 61 | * 62 | * @throws IllegalArgumentException if the arguments are invalid 63 | * @throws InvocationTargetException if the invocation throws an exception 64 | */ 65 | public Object invokeOptional(T target, Object... args) throws InvocationTargetException { 66 | Method m = getMethod(target.getClass()); 67 | if (m == null) { 68 | return null; 69 | } 70 | try { 71 | return m.invoke(target, args); 72 | } catch (IllegalAccessException e) { 73 | return null; 74 | } 75 | } 76 | 77 | /** 78 | * Invokes the method on {@code target}. If the method does not exist or is not public then 79 | * {@code null} is returned. Any RuntimeException thrown by the method is thrown, checked 80 | * exceptions are wrapped in an {@link AssertionError}. 81 | * 82 | * @throws IllegalArgumentException if the arguments are invalid 83 | */ 84 | public Object invokeOptionalWithoutCheckedException(T target, Object... args) { 85 | try { 86 | return invokeOptional(target, args); 87 | } catch (InvocationTargetException e) { 88 | Throwable targetException = e.getTargetException(); 89 | if (targetException instanceof RuntimeException) { 90 | throw (RuntimeException) targetException; 91 | } 92 | AssertionError error = new AssertionError("Unexpected exception"); 93 | error.initCause(targetException); 94 | throw error; 95 | } 96 | } 97 | 98 | /** 99 | * Invokes the method on {@code target} with {@code args}. Throws an error if the method is not 100 | * supported. See also {@link #invokeWithoutCheckedException(Object, Object...)}. 101 | * 102 | * @throws IllegalArgumentException if the arguments are invalid 103 | * @throws InvocationTargetException if the invocation throws an exception 104 | */ 105 | public Object invoke(T target, Object... args) throws InvocationTargetException { 106 | Method m = getMethod(target.getClass()); 107 | if (m == null) { 108 | throw new AssertionError("Method " + methodName + " not supported for object " + target); 109 | } 110 | try { 111 | return m.invoke(target, args); 112 | } catch (IllegalAccessException e) { 113 | // Method should be public: we checked. 114 | AssertionError error = new AssertionError("Unexpectedly could not call: " + m); 115 | error.initCause(e); 116 | throw error; 117 | } 118 | } 119 | 120 | /** 121 | * Invokes the method on {@code target}. Throws an error if the method is not supported. Any 122 | * RuntimeException thrown by the method is thrown, checked exceptions are wrapped in an {@link 123 | * AssertionError}. 124 | * 125 | * @throws IllegalArgumentException if the arguments are invalid 126 | */ 127 | public Object invokeWithoutCheckedException(T target, Object... args) { 128 | try { 129 | return invoke(target, args); 130 | } catch (InvocationTargetException e) { 131 | Throwable targetException = e.getTargetException(); 132 | if (targetException instanceof RuntimeException) { 133 | throw (RuntimeException) targetException; 134 | } 135 | AssertionError error = new AssertionError("Unexpected exception"); 136 | error.initCause(targetException); 137 | throw error; 138 | } 139 | } 140 | 141 | /** 142 | * Perform a lookup for the method. No caching. In order to return a method the method name and 143 | * arguments must match those specified when the {@link OptionalMethod} was created. If the return 144 | * type is specified (i.e. non-null) it must also be compatible. The method must also be public. 145 | */ 146 | private Method getMethod(Class clazz) { 147 | Method method = null; 148 | if (methodName != null) { 149 | method = getPublicMethod(clazz, methodName, methodParams); 150 | if (method != null 151 | && returnType != null 152 | && !returnType.isAssignableFrom(method.getReturnType())) { 153 | 154 | // If the return type is non-null it must be compatible. 155 | method = null; 156 | } 157 | } 158 | return method; 159 | } 160 | 161 | private static Method getPublicMethod(Class clazz, String methodName, Class[] parameterTypes) { 162 | Method method = null; 163 | try { 164 | method = clazz.getMethod(methodName, parameterTypes); 165 | if ((method.getModifiers() & Modifier.PUBLIC) == 0) { 166 | method = null; 167 | } 168 | } catch (NoSuchMethodException e) { 169 | // None. 170 | } 171 | return method; 172 | } 173 | } 174 | 175 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/RouteDatabase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal; 17 | 18 | import java.util.LinkedHashSet; 19 | import java.util.Set; 20 | import okhttp3.Route; 21 | 22 | /** 23 | * A blacklist of failed routes to avoid when creating a new connection to a target address. This is 24 | * used so that OkHttp can learn from its mistakes: if there was a failure attempting to connect to 25 | * a specific IP address or proxy server, that failure is remembered and alternate routes are 26 | * preferred. 27 | */ 28 | public final class RouteDatabase { 29 | private final Set failedRoutes = new LinkedHashSet<>(); 30 | 31 | /** Records a failure connecting to {@code failedRoute}. */ 32 | public synchronized void failed(Route failedRoute) { 33 | failedRoutes.add(failedRoute); 34 | } 35 | 36 | /** Records success connecting to {@code failedRoute}. */ 37 | public synchronized void connected(Route route) { 38 | failedRoutes.remove(route); 39 | } 40 | 41 | /** Returns true if {@code route} has failed recently and should be avoided. */ 42 | public synchronized boolean shouldPostpone(Route route) { 43 | return failedRoutes.contains(route); 44 | } 45 | 46 | public synchronized int failedRoutesCount() { 47 | return failedRoutes.size(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/Version.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal; 17 | 18 | public final class Version { 19 | public static String userAgent() { 20 | return "okhttp/${project.version}"; 21 | } 22 | 23 | private Version() { 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/ErrorCode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | // http://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-7 19 | public enum ErrorCode { 20 | /** Not an error! For SPDY stream resets, prefer null over NO_ERROR. */ 21 | NO_ERROR(0, -1, 0), 22 | 23 | PROTOCOL_ERROR(1, 1, 1), 24 | 25 | /** A subtype of PROTOCOL_ERROR used by SPDY. */ 26 | INVALID_STREAM(1, 2, -1), 27 | 28 | /** A subtype of PROTOCOL_ERROR used by SPDY. */ 29 | UNSUPPORTED_VERSION(1, 4, -1), 30 | 31 | /** A subtype of PROTOCOL_ERROR used by SPDY. */ 32 | STREAM_IN_USE(1, 8, -1), 33 | 34 | /** A subtype of PROTOCOL_ERROR used by SPDY. */ 35 | STREAM_ALREADY_CLOSED(1, 9, -1), 36 | 37 | INTERNAL_ERROR(2, 6, 2), 38 | 39 | FLOW_CONTROL_ERROR(3, 7, -1), 40 | 41 | STREAM_CLOSED(5, -1, -1), 42 | 43 | FRAME_TOO_LARGE(6, 11, -1), 44 | 45 | REFUSED_STREAM(7, 3, -1), 46 | 47 | CANCEL(8, 5, -1), 48 | 49 | COMPRESSION_ERROR(9, -1, -1), 50 | 51 | CONNECT_ERROR(10, -1, -1), 52 | 53 | ENHANCE_YOUR_CALM(11, -1, -1), 54 | 55 | INADEQUATE_SECURITY(12, -1, -1), 56 | 57 | HTTP_1_1_REQUIRED(13, -1, -1), 58 | 59 | INVALID_CREDENTIALS(-1, 10, -1); 60 | 61 | public final int httpCode; 62 | public final int spdyRstCode; 63 | public final int spdyGoAwayCode; 64 | 65 | private ErrorCode(int httpCode, int spdyRstCode, int spdyGoAwayCode) { 66 | this.httpCode = httpCode; 67 | this.spdyRstCode = spdyRstCode; 68 | this.spdyGoAwayCode = spdyGoAwayCode; 69 | } 70 | 71 | public static ErrorCode fromSpdy3Rst(int code) { 72 | for (ErrorCode errorCode : ErrorCode.values()) { 73 | if (errorCode.spdyRstCode == code) return errorCode; 74 | } 75 | return null; 76 | } 77 | 78 | public static ErrorCode fromHttp2(int code) { 79 | for (ErrorCode errorCode : ErrorCode.values()) { 80 | if (errorCode.httpCode == code) return errorCode; 81 | } 82 | return null; 83 | } 84 | 85 | public static ErrorCode fromSpdyGoAway(int code) { 86 | for (ErrorCode errorCode : ErrorCode.values()) { 87 | if (errorCode.spdyGoAwayCode == code) return errorCode; 88 | } 89 | return null; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/FrameReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.framed; 18 | 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | import java.util.List; 22 | import okio.BufferedSource; 23 | import okio.ByteString; 24 | 25 | /** Reads transport frames for SPDY/3 or HTTP/2. */ 26 | public interface FrameReader extends Closeable { 27 | void readConnectionPreface() throws IOException; 28 | 29 | boolean nextFrame(Handler handler) throws IOException; 30 | 31 | interface Handler { 32 | void data(boolean inFinished, int streamId, BufferedSource source, int length) 33 | throws IOException; 34 | 35 | /** 36 | * Create or update incoming headers, creating the corresponding streams if necessary. Frames 37 | * that trigger this are SPDY SYN_STREAM, HEADERS, and SYN_REPLY, and HTTP/2 HEADERS and 38 | * PUSH_PROMISE. 39 | * 40 | * @param outFinished true if the receiver should not send further frames. 41 | * @param inFinished true if the sender will not send further frames. 42 | * @param streamId the stream owning these headers. 43 | * @param associatedStreamId the stream that triggered the sender to create this stream. 44 | */ 45 | void headers(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId, 46 | List

headerBlock, HeadersMode headersMode); 47 | 48 | void rstStream(int streamId, ErrorCode errorCode); 49 | 50 | void settings(boolean clearPrevious, Settings settings); 51 | 52 | /** HTTP/2 only. */ 53 | void ackSettings(); 54 | 55 | /** 56 | * Read a connection-level ping from the peer. {@code ack} indicates this is a reply. Payload 57 | * parameters are different between SPDY/3 and HTTP/2. 58 | * 59 | *

In SPDY/3, only the first {@code payload1} parameter is set. If the reader is a client, 60 | * it is an unsigned even number. Likewise, a server will receive an odd number. 61 | * 62 | *

In HTTP/2, both {@code payload1} and {@code payload2} parameters are set. The data is 63 | * opaque binary, and there are no rules on the content. 64 | */ 65 | void ping(boolean ack, int payload1, int payload2); 66 | 67 | /** 68 | * The peer tells us to stop creating streams. It is safe to replay streams with {@code ID > 69 | * lastGoodStreamId} on a new connection. In- flight streams with {@code ID <= 70 | * lastGoodStreamId} can only be replayed on a new connection if they are idempotent. 71 | * 72 | * @param lastGoodStreamId the last stream ID the peer processed before sending this message. If 73 | * {@code lastGoodStreamId} is zero, the peer processed no frames. 74 | * @param errorCode reason for closing the connection. 75 | * @param debugData only valid for HTTP/2; opaque debug data to send. 76 | */ 77 | void goAway(int lastGoodStreamId, ErrorCode errorCode, ByteString debugData); 78 | 79 | /** 80 | * Notifies that an additional {@code windowSizeIncrement} bytes can be sent on {@code 81 | * streamId}, or the connection if {@code streamId} is zero. 82 | */ 83 | void windowUpdate(int streamId, long windowSizeIncrement); 84 | 85 | /** 86 | * Called when reading a headers or priority frame. This may be used to change the stream's 87 | * weight from the default (16) to a new value. 88 | * 89 | * @param streamId stream which has a priority change. 90 | * @param streamDependency the stream ID this stream is dependent on. 91 | * @param weight relative proportion of priority in [1..256]. 92 | * @param exclusive inserts this stream ID as the sole child of {@code streamDependency}. 93 | */ 94 | void priority(int streamId, int streamDependency, int weight, boolean exclusive); 95 | 96 | /** 97 | * HTTP/2 only. Receive a push promise header block.

A push promise contains all the headers 98 | * that pertain to a server-initiated request, and a {@code promisedStreamId} to which response 99 | * frames will be delivered. Push promise frames are sent as a part of the response to {@code 100 | * streamId}. 101 | * 102 | * @param streamId client-initiated stream ID. Must be an odd number. 103 | * @param promisedStreamId server-initiated stream ID. Must be an even number. 104 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code 105 | * :authority}, and (@code :path}. 106 | */ 107 | void pushPromise(int streamId, int promisedStreamId, List

requestHeaders) 108 | throws IOException; 109 | 110 | /** 111 | * HTTP/2 only. Expresses that resources for the connection or a client- initiated stream are 112 | * available from a different network location or protocol configuration. 113 | * 114 | *

See alt-svc 115 | * 116 | * @param streamId when a client-initiated stream ID (odd number), the origin of this alternate 117 | * service is the origin of the stream. When zero, the origin is specified in the {@code origin} 118 | * parameter. 119 | * @param origin when present, the origin is 120 | * typically represented as a combination of scheme, host and port. When empty, the origin is 121 | * that of the {@code streamId}. 122 | * @param protocol an ALPN protocol, such as {@code h2}. 123 | * @param host an IP address or hostname. 124 | * @param port the IP port associated with the service. 125 | * @param maxAge time in seconds that this alternative is considered fresh. 126 | */ 127 | void alternateService(int streamId, String origin, ByteString protocol, String host, int port, 128 | long maxAge); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/FrameWriter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.framed; 18 | 19 | import java.io.Closeable; 20 | import java.io.IOException; 21 | import java.util.List; 22 | import okio.Buffer; 23 | 24 | /** Writes transport frames for SPDY/3 or HTTP/2. */ 25 | public interface FrameWriter extends Closeable { 26 | /** HTTP/2 only. */ 27 | void connectionPreface() throws IOException; 28 | 29 | /** Informs the peer that we've applied its latest settings. */ 30 | void ackSettings(Settings peerSettings) throws IOException; 31 | 32 | /** 33 | * HTTP/2 only. Send a push promise header block. 34 | * 35 | *

A push promise contains all the headers that pertain to a server-initiated request, and a 36 | * {@code promisedStreamId} to which response frames will be delivered. Push promise frames are 37 | * sent as a part of the response to {@code streamId}. The {@code promisedStreamId} has a priority 38 | * of one greater than {@code streamId}. 39 | * 40 | * @param streamId client-initiated stream ID. Must be an odd number. 41 | * @param promisedStreamId server-initiated stream ID. Must be an even number. 42 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code :authority}, 43 | * and (@code :path}. 44 | */ 45 | void pushPromise(int streamId, int promisedStreamId, List

requestHeaders) 46 | throws IOException; 47 | 48 | /** SPDY/3 only. */ 49 | void flush() throws IOException; 50 | 51 | void synStream(boolean outFinished, boolean inFinished, int streamId, int associatedStreamId, 52 | List
headerBlock) throws IOException; 53 | 54 | void synReply(boolean outFinished, int streamId, List
headerBlock) 55 | throws IOException; 56 | 57 | void headers(int streamId, List
headerBlock) throws IOException; 58 | 59 | void rstStream(int streamId, ErrorCode errorCode) throws IOException; 60 | 61 | /** The maximum size of bytes that may be sent in a single call to {@link #data}. */ 62 | int maxDataLength(); 63 | 64 | /** 65 | * {@code source.length} may be longer than the max length of the variant's data frame. 66 | * Implementations must send multiple frames as necessary. 67 | * 68 | * @param source the buffer to draw bytes from. May be null if byteCount is 0. 69 | * @param byteCount must be between 0 and the minimum of {code source.length} and {@link 70 | * #maxDataLength}. 71 | */ 72 | void data(boolean outFinished, int streamId, Buffer source, int byteCount) throws IOException; 73 | 74 | /** Write okhttp's settings to the peer. */ 75 | void settings(Settings okHttpSettings) throws IOException; 76 | 77 | /** 78 | * Send a connection-level ping to the peer. {@code ack} indicates this is a reply. Payload 79 | * parameters are different between SPDY/3 and HTTP/2. 80 | * 81 | *

In SPDY/3, only the first {@code payload1} parameter is sent. If the sender is a client, it 82 | * is an unsigned odd number. Likewise, a server will send an even number. 83 | * 84 | *

In HTTP/2, both {@code payload1} and {@code payload2} parameters are sent. The data is 85 | * opaque binary, and there are no rules on the content. 86 | */ 87 | void ping(boolean ack, int payload1, int payload2) throws IOException; 88 | 89 | /** 90 | * Tell the peer to stop creating streams and that we last processed {@code lastGoodStreamId}, or 91 | * zero if no streams were processed. 92 | * 93 | * @param lastGoodStreamId the last stream ID processed, or zero if no streams were processed. 94 | * @param errorCode reason for closing the connection. 95 | * @param debugData only valid for HTTP/2; opaque debug data to send. 96 | */ 97 | void goAway(int lastGoodStreamId, ErrorCode errorCode, byte[] debugData) throws IOException; 98 | 99 | /** 100 | * Inform peer that an additional {@code windowSizeIncrement} bytes can be sent on {@code 101 | * streamId}, or the connection if {@code streamId} is zero. 102 | */ 103 | void windowUpdate(int streamId, long windowSizeIncrement) throws IOException; 104 | } 105 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/Header.java: -------------------------------------------------------------------------------- 1 | package okhttp3.internal.framed; 2 | 3 | import okio.ByteString; 4 | 5 | /** HTTP header: the name is an ASCII string, but the value can be UTF-8. */ 6 | public final class Header { 7 | // Special header names defined in the SPDY and HTTP/2 specs. 8 | public static final ByteString RESPONSE_STATUS = ByteString.encodeUtf8(":status"); 9 | public static final ByteString TARGET_METHOD = ByteString.encodeUtf8(":method"); 10 | public static final ByteString TARGET_PATH = ByteString.encodeUtf8(":path"); 11 | public static final ByteString TARGET_SCHEME = ByteString.encodeUtf8(":scheme"); 12 | public static final ByteString TARGET_AUTHORITY = ByteString.encodeUtf8(":authority"); // HTTP/2 13 | public static final ByteString TARGET_HOST = ByteString.encodeUtf8(":host"); // spdy/3 14 | public static final ByteString VERSION = ByteString.encodeUtf8(":version"); // spdy/3 15 | 16 | /** Name in case-insensitive ASCII encoding. */ 17 | public final ByteString name; 18 | /** Value in UTF-8 encoding. */ 19 | public final ByteString value; 20 | final int hpackSize; 21 | 22 | // TODO: search for toLowerCase and consider moving logic here. 23 | public Header(String name, String value) { 24 | this(ByteString.encodeUtf8(name), ByteString.encodeUtf8(value)); 25 | } 26 | 27 | public Header(ByteString name, String value) { 28 | this(name, ByteString.encodeUtf8(value)); 29 | } 30 | 31 | public Header(ByteString name, ByteString value) { 32 | this.name = name; 33 | this.value = value; 34 | this.hpackSize = 32 + name.size() + value.size(); 35 | } 36 | 37 | @Override public boolean equals(Object other) { 38 | if (other instanceof Header) { 39 | Header that = (Header) other; 40 | return this.name.equals(that.name) 41 | && this.value.equals(that.value); 42 | } 43 | return false; 44 | } 45 | 46 | @Override public int hashCode() { 47 | int result = 17; 48 | result = 31 * result + name.hashCode(); 49 | result = 31 * result + value.hashCode(); 50 | return result; 51 | } 52 | 53 | @Override public String toString() { 54 | return String.format("%s: %s", name.utf8(), value.utf8()); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/HeadersMode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | public enum HeadersMode { 19 | SPDY_SYN_STREAM, 20 | SPDY_REPLY, 21 | SPDY_HEADERS, 22 | HTTP_20_HEADERS; 23 | 24 | /** Returns true if it is an error these headers to create a new stream. */ 25 | public boolean failIfStreamAbsent() { 26 | return this == SPDY_REPLY || this == SPDY_HEADERS; 27 | } 28 | 29 | /** Returns true if it is an error these headers to update an existing stream. */ 30 | public boolean failIfStreamPresent() { 31 | return this == SPDY_SYN_STREAM; 32 | } 33 | 34 | /** 35 | * Returns true if it is an error these headers to be the initial headers of a response. 36 | */ 37 | public boolean failIfHeadersAbsent() { 38 | return this == SPDY_HEADERS; 39 | } 40 | 41 | /** 42 | * Returns true if it is an error these headers to be update existing headers of a response. 43 | */ 44 | public boolean failIfHeadersPresent() { 45 | return this == SPDY_REPLY; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/NameValueBlockReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | import java.io.IOException; 19 | import java.util.ArrayList; 20 | import java.util.List; 21 | import java.util.zip.DataFormatException; 22 | import java.util.zip.Inflater; 23 | import okio.Buffer; 24 | import okio.BufferedSource; 25 | import okio.ByteString; 26 | import okio.ForwardingSource; 27 | import okio.InflaterSource; 28 | import okio.Okio; 29 | import okio.Source; 30 | 31 | /** 32 | * Reads a SPDY/3 Name/Value header block. This class is made complicated by the requirement that 33 | * we're strict with which bytes we put in the compressed bytes buffer. We need to put all 34 | * compressed bytes into that buffer -- but no other bytes. 35 | */ 36 | class NameValueBlockReader { 37 | /** This source transforms compressed bytes into uncompressed bytes. */ 38 | private final InflaterSource inflaterSource; 39 | 40 | /** 41 | * How many compressed bytes must be read into inflaterSource before {@link #readNameValueBlock} 42 | * returns. 43 | */ 44 | private int compressedLimit; 45 | 46 | /** This source holds inflated bytes. */ 47 | private final BufferedSource source; 48 | 49 | public NameValueBlockReader(BufferedSource source) { 50 | // Limit the inflater input stream to only those bytes in the Name/Value 51 | // block. We cut the inflater off at its source because we can't predict the 52 | // ratio of compressed bytes to uncompressed bytes. 53 | Source throttleSource = new ForwardingSource(source) { 54 | @Override public long read(Buffer sink, long byteCount) throws IOException { 55 | if (compressedLimit == 0) return -1; // Out of data for the current block. 56 | long read = super.read(sink, Math.min(byteCount, compressedLimit)); 57 | if (read == -1) return -1; 58 | compressedLimit -= read; 59 | return read; 60 | } 61 | }; 62 | 63 | // Subclass inflater to install a dictionary when it's needed. 64 | Inflater inflater = new Inflater() { 65 | @Override public int inflate(byte[] buffer, int offset, int count) 66 | throws DataFormatException { 67 | int result = super.inflate(buffer, offset, count); 68 | if (result == 0 && needsDictionary()) { 69 | setDictionary(Spdy3.DICTIONARY); 70 | result = super.inflate(buffer, offset, count); 71 | } 72 | return result; 73 | } 74 | }; 75 | 76 | this.inflaterSource = new InflaterSource(throttleSource, inflater); 77 | this.source = Okio.buffer(inflaterSource); 78 | } 79 | 80 | public List

readNameValueBlock(int length) throws IOException { 81 | this.compressedLimit += length; 82 | 83 | int numberOfPairs = source.readInt(); 84 | if (numberOfPairs < 0) throw new IOException("numberOfPairs < 0: " + numberOfPairs); 85 | if (numberOfPairs > 1024) throw new IOException("numberOfPairs > 1024: " + numberOfPairs); 86 | 87 | List
entries = new ArrayList<>(numberOfPairs); 88 | for (int i = 0; i < numberOfPairs; i++) { 89 | ByteString name = readByteString().toAsciiLowercase(); 90 | ByteString values = readByteString(); 91 | if (name.size() == 0) throw new IOException("name.size == 0"); 92 | entries.add(new Header(name, values)); 93 | } 94 | 95 | doneReading(); 96 | return entries; 97 | } 98 | 99 | private ByteString readByteString() throws IOException { 100 | int length = source.readInt(); 101 | return source.readByteString(length); 102 | } 103 | 104 | private void doneReading() throws IOException { 105 | // Move any outstanding unread bytes into the inflater. One side-effect of 106 | // deflate compression is that sometimes there are bytes remaining in the 107 | // stream after we've consumed all of the content. 108 | if (compressedLimit > 0) { 109 | inflaterSource.refill(); 110 | if (compressedLimit != 0) throw new IOException("compressedLimit > 0: " + compressedLimit); 111 | } 112 | } 113 | 114 | public void close() throws IOException { 115 | source.close(); 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/Ping.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | import java.util.concurrent.CountDownLatch; 19 | import java.util.concurrent.TimeUnit; 20 | 21 | /** 22 | * A locally-originated ping. 23 | */ 24 | public final class Ping { 25 | private final CountDownLatch latch = new CountDownLatch(1); 26 | private long sent = -1; 27 | private long received = -1; 28 | 29 | Ping() { 30 | } 31 | 32 | void send() { 33 | if (sent != -1) throw new IllegalStateException(); 34 | sent = System.nanoTime(); 35 | } 36 | 37 | void receive() { 38 | if (received != -1 || sent == -1) throw new IllegalStateException(); 39 | received = System.nanoTime(); 40 | latch.countDown(); 41 | } 42 | 43 | void cancel() { 44 | if (received != -1 || sent == -1) throw new IllegalStateException(); 45 | received = sent - 1; 46 | latch.countDown(); 47 | } 48 | 49 | /** 50 | * Returns the round trip time for this ping in nanoseconds, waiting for the response to arrive if 51 | * necessary. Returns -1 if the response was canceled. 52 | */ 53 | public long roundTripTime() throws InterruptedException { 54 | latch.await(); 55 | return received - sent; 56 | } 57 | 58 | /** 59 | * Returns the round trip time for this ping in nanoseconds, or -1 if the response was canceled, 60 | * or -2 if the timeout elapsed before the round trip completed. 61 | */ 62 | public long roundTripTime(long timeout, TimeUnit unit) throws InterruptedException { 63 | if (latch.await(timeout, unit)) { 64 | return received - sent; 65 | } else { 66 | return -2; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/PushObserver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | import java.io.IOException; 19 | import java.util.List; 20 | import okhttp3.Protocol; 21 | import okio.BufferedSource; 22 | 23 | /** 24 | * {@link Protocol#HTTP_2 HTTP/2} only. Processes server-initiated HTTP requests on the client. 25 | * Implementations must quickly dispatch callbacks to avoid creating a bottleneck. 26 | * 27 | *

While {@link #onReset} may occur at any time, the following callbacks are expected in order, 28 | * correlated by stream ID. 29 | * 30 | *

    31 | *
  • {@link #onRequest}
  • {@link #onHeaders} (unless canceled) 32 | *
  • {@link #onData} (optional sequence of data frames) 33 | *
34 | * 35 | *

As a stream ID is scoped to a single HTTP/2 connection, implementations which target multiple 36 | * connections should expect repetition of stream IDs. 37 | * 38 | *

Return true to request cancellation of a pushed stream. Note that this does not guarantee 39 | * future frames won't arrive on the stream ID. 40 | */ 41 | public interface PushObserver { 42 | /** 43 | * Describes the request that the server intends to push a response for. 44 | * 45 | * @param streamId server-initiated stream ID: an even number. 46 | * @param requestHeaders minimally includes {@code :method}, {@code :scheme}, {@code :authority}, 47 | * and (@code :path}. 48 | */ 49 | boolean onRequest(int streamId, List

requestHeaders); 50 | 51 | /** 52 | * The response headers corresponding to a pushed request. When {@code last} is true, there are 53 | * no data frames to follow. 54 | * 55 | * @param streamId server-initiated stream ID: an even number. 56 | * @param responseHeaders minimally includes {@code :status}. 57 | * @param last when true, there is no response data. 58 | */ 59 | boolean onHeaders(int streamId, List
responseHeaders, boolean last); 60 | 61 | /** 62 | * A chunk of response data corresponding to a pushed request. This data must either be read or 63 | * skipped. 64 | * 65 | * @param streamId server-initiated stream ID: an even number. 66 | * @param source location of data corresponding with this stream ID. 67 | * @param byteCount number of bytes to read or skip from the source. 68 | * @param last when true, there are no data frames to follow. 69 | */ 70 | boolean onData(int streamId, BufferedSource source, int byteCount, boolean last) 71 | throws IOException; 72 | 73 | /** Indicates the reason why this stream was canceled. */ 74 | void onReset(int streamId, ErrorCode errorCode); 75 | 76 | PushObserver CANCEL = new PushObserver() { 77 | 78 | @Override public boolean onRequest(int streamId, List
requestHeaders) { 79 | return true; 80 | } 81 | 82 | @Override public boolean onHeaders(int streamId, List
responseHeaders, boolean last) { 83 | return true; 84 | } 85 | 86 | @Override public boolean onData(int streamId, BufferedSource source, int byteCount, 87 | boolean last) throws IOException { 88 | source.skip(byteCount); 89 | return true; 90 | } 91 | 92 | @Override public void onReset(int streamId, ErrorCode errorCode) { 93 | } 94 | }; 95 | } 96 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/framed/Variant.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.framed; 17 | 18 | import okhttp3.Protocol; 19 | import okio.BufferedSink; 20 | import okio.BufferedSource; 21 | 22 | /** A version and dialect of the framed socket protocol. */ 23 | public interface Variant { 24 | 25 | /** The protocol as selected using ALPN. */ 26 | Protocol getProtocol(); 27 | 28 | /** 29 | * @param client true if this is the HTTP client's reader, reading frames from a server. 30 | */ 31 | FrameReader newReader(BufferedSource source, boolean client); 32 | 33 | /** 34 | * @param client true if this is the HTTP client's writer, writing frames to a server. 35 | */ 36 | FrameWriter newWriter(BufferedSink sink, boolean client); 37 | } 38 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/CacheRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | import java.io.IOException; 19 | import okio.Sink; 20 | 21 | public interface CacheRequest { 22 | Sink body() throws IOException; 23 | 24 | void abort(); 25 | } 26 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/HeaderParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.http; 18 | 19 | public final class HeaderParser { 20 | /** 21 | * Returns the next index in {@code input} at or after {@code pos} that contains a character from 22 | * {@code characters}. Returns the input length if none of the requested characters can be found. 23 | */ 24 | public static int skipUntil(String input, int pos, String characters) { 25 | for (; pos < input.length(); pos++) { 26 | if (characters.indexOf(input.charAt(pos)) != -1) { 27 | break; 28 | } 29 | } 30 | return pos; 31 | } 32 | 33 | /** 34 | * Returns the next non-whitespace character in {@code input} that is white space. Result is 35 | * undefined if input contains newline characters. 36 | */ 37 | public static int skipWhitespace(String input, int pos) { 38 | for (; pos < input.length(); pos++) { 39 | char c = input.charAt(pos); 40 | if (c != ' ' && c != '\t') { 41 | break; 42 | } 43 | } 44 | return pos; 45 | } 46 | 47 | /** 48 | * Returns {@code value} as a positive integer, or 0 if it is negative, or {@code defaultValue} if 49 | * it cannot be parsed. 50 | */ 51 | public static int parseSeconds(String value, int defaultValue) { 52 | try { 53 | long seconds = Long.parseLong(value); 54 | if (seconds > Integer.MAX_VALUE) { 55 | return Integer.MAX_VALUE; 56 | } else if (seconds < 0) { 57 | return 0; 58 | } else { 59 | return (int) seconds; 60 | } 61 | } catch (NumberFormatException e) { 62 | return defaultValue; 63 | } 64 | } 65 | 66 | private HeaderParser() { 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/HttpDate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.http; 18 | 19 | import java.text.DateFormat; 20 | import java.text.ParsePosition; 21 | import java.text.SimpleDateFormat; 22 | import java.util.Date; 23 | import java.util.Locale; 24 | 25 | import static okhttp3.internal.Util.UTC; 26 | 27 | /** 28 | * Best-effort parser for HTTP dates. 29 | */ 30 | public final class HttpDate { 31 | /** The last four-digit year: "Fri, 31 Dec 9999 23:59:59 GMT". */ 32 | public static final long MAX_DATE = 253402300799999L; 33 | 34 | /** 35 | * Most websites serve cookies in the blessed format. Eagerly create the parser to ensure such 36 | * cookies are on the fast path. 37 | */ 38 | private static final ThreadLocal STANDARD_DATE_FORMAT = 39 | new ThreadLocal() { 40 | @Override protected DateFormat initialValue() { 41 | // RFC 2616 specified: RFC 822, updated by RFC 1123 format with fixed GMT. 42 | DateFormat rfc1123 = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US); 43 | rfc1123.setLenient(false); 44 | rfc1123.setTimeZone(UTC); 45 | return rfc1123; 46 | } 47 | }; 48 | 49 | /** If we fail to parse a date in a non-standard format, try each of these formats in sequence. */ 50 | private static final String[] BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS = new String[] { 51 | // HTTP formats required by RFC2616 but with any timezone. 52 | "EEE, dd MMM yyyy HH:mm:ss zzz", // RFC 822, updated by RFC 1123 with any TZ 53 | "EEEE, dd-MMM-yy HH:mm:ss zzz", // RFC 850, obsoleted by RFC 1036 with any TZ. 54 | "EEE MMM d HH:mm:ss yyyy", // ANSI C's asctime() format 55 | // Alternative formats. 56 | "EEE, dd-MMM-yyyy HH:mm:ss z", 57 | "EEE, dd-MMM-yyyy HH-mm-ss z", 58 | "EEE, dd MMM yy HH:mm:ss z", 59 | "EEE dd-MMM-yyyy HH:mm:ss z", 60 | "EEE dd MMM yyyy HH:mm:ss z", 61 | "EEE dd-MMM-yyyy HH-mm-ss z", 62 | "EEE dd-MMM-yy HH:mm:ss z", 63 | "EEE dd MMM yy HH:mm:ss z", 64 | "EEE,dd-MMM-yy HH:mm:ss z", 65 | "EEE,dd-MMM-yyyy HH:mm:ss z", 66 | "EEE, dd-MM-yyyy HH:mm:ss z", 67 | 68 | /* RI bug 6641315 claims a cookie of this format was once served by www.yahoo.com */ 69 | "EEE MMM d yyyy HH:mm:ss z", 70 | }; 71 | 72 | private static final DateFormat[] BROWSER_COMPATIBLE_DATE_FORMATS = 73 | new DateFormat[BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length]; 74 | 75 | /** Returns the date for {@code value}. Returns null if the value couldn't be parsed. */ 76 | public static Date parse(String value) { 77 | if (value.length() == 0) { 78 | return null; 79 | } 80 | 81 | ParsePosition position = new ParsePosition(0); 82 | Date result = STANDARD_DATE_FORMAT.get().parse(value, position); 83 | if (position.getIndex() == value.length()) { 84 | // STANDARD_DATE_FORMAT must match exactly; all text must be consumed, e.g. no ignored 85 | // non-standard trailing "+01:00". Those cases are covered below. 86 | return result; 87 | } 88 | synchronized (BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS) { 89 | for (int i = 0, count = BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS.length; i < count; i++) { 90 | DateFormat format = BROWSER_COMPATIBLE_DATE_FORMATS[i]; 91 | if (format == null) { 92 | format = new SimpleDateFormat(BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS[i], Locale.US); 93 | // Set the timezone to use when interpreting formats that don't have a timezone. GMT is 94 | // specified by RFC 2616. 95 | format.setTimeZone(UTC); 96 | BROWSER_COMPATIBLE_DATE_FORMATS[i] = format; 97 | } 98 | position.setIndex(0); 99 | result = format.parse(value, position); 100 | if (position.getIndex() != 0) { 101 | // Something was parsed. It's possible the entire string was not consumed but we ignore 102 | // that. If any of the BROWSER_COMPATIBLE_DATE_FORMAT_STRINGS ended in "'GMT'" we'd have 103 | // to also check that position.getIndex() == value.length() otherwise parsing might have 104 | // terminated early, ignoring things like "+01:00". Leaving this as != 0 means that any 105 | // trailing junk is ignored. 106 | return result; 107 | } 108 | } 109 | } 110 | return null; 111 | } 112 | 113 | /** Returns the string for {@code value}. */ 114 | public static String format(Date value) { 115 | return STANDARD_DATE_FORMAT.get().format(value); 116 | } 117 | 118 | private HttpDate() { 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/HttpMethod.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | public final class HttpMethod { 19 | public static boolean invalidatesCache(String method) { 20 | return method.equals("POST") 21 | || method.equals("PATCH") 22 | || method.equals("PUT") 23 | || method.equals("DELETE") 24 | || method.equals("MOVE"); // WebDAV 25 | } 26 | 27 | public static boolean requiresRequestBody(String method) { 28 | return method.equals("POST") 29 | || method.equals("PUT") 30 | || method.equals("PATCH") 31 | || method.equals("PROPPATCH") // WebDAV 32 | || method.equals("REPORT"); // CalDAV/CardDAV (defined in WebDAV Versioning) 33 | } 34 | 35 | public static boolean permitsRequestBody(String method) { 36 | return requiresRequestBody(method) 37 | || method.equals("OPTIONS") 38 | || method.equals("DELETE") // Permitted as spec is ambiguous. 39 | || method.equals("PROPFIND") // (WebDAV) without body: request 40 | || method.equals("MKCOL") // (WebDAV) may contain a body, but behaviour is unspecified 41 | || method.equals("LOCK"); // (WebDAV) body: create lock, without body: refresh lock 42 | } 43 | 44 | public static boolean redirectsToGet(String method) { 45 | // All requests but PROPFIND should redirect to a GET request. 46 | return !method.equals("PROPFIND"); 47 | } 48 | 49 | private HttpMethod() { 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/HttpStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.http; 18 | 19 | import java.io.IOException; 20 | import okhttp3.Request; 21 | import okhttp3.Response; 22 | import okhttp3.ResponseBody; 23 | import okio.Sink; 24 | 25 | public interface HttpStream { 26 | /** 27 | * The timeout to use while discarding a stream of input data. Since this is used for connection 28 | * reuse, this timeout should be significantly less than the time it takes to establish a new 29 | * connection. 30 | */ 31 | int DISCARD_STREAM_TIMEOUT_MILLIS = 100; 32 | 33 | /** Returns an output stream where the request body can be streamed. */ 34 | Sink createRequestBody(Request request, long contentLength) throws IOException; 35 | 36 | /** This should update the HTTP engine's sentRequestMillis field. */ 37 | void writeRequestHeaders(Request request) throws IOException; 38 | 39 | /** 40 | * Sends the request body returned by {@link #createRequestBody} to the remote peer. 41 | */ 42 | void writeRequestBody(RetryableSink requestBody) throws IOException; 43 | 44 | /** Flush the request to the underlying socket. */ 45 | void finishRequest() throws IOException; 46 | 47 | /** Read and return response headers. */ 48 | Response.Builder readResponseHeaders() throws IOException; 49 | 50 | /** Returns a stream that reads the response body. */ 51 | ResponseBody openResponseBody(Response response) throws IOException; 52 | 53 | void setHttpEngine(HttpEngine httpEngine); 54 | 55 | /** 56 | * Cancel this stream. Resources held by this stream will be cleaned up, though not synchronously. 57 | * That may happen later by the connection pool thread. 58 | */ 59 | void cancel(); 60 | } 61 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/OkHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2012 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collections; 20 | import java.util.List; 21 | import java.util.Set; 22 | import java.util.TreeSet; 23 | import okhttp3.Challenge; 24 | import okhttp3.Headers; 25 | import okhttp3.Protocol; 26 | import okhttp3.Request; 27 | import okhttp3.Response; 28 | import okhttp3.internal.Platform; 29 | 30 | import static okhttp3.internal.Util.equal; 31 | 32 | /** Headers and utilities for internal use by OkHttp. */ 33 | public final class OkHeaders { 34 | 35 | static final String PREFIX = Platform.get().getPrefix(); 36 | 37 | /** 38 | * Synthetic response header: the local time when the request was sent. 39 | */ 40 | public static final String SENT_MILLIS = PREFIX + "-Sent-Millis"; 41 | 42 | /** 43 | * Synthetic response header: the local time when the response was received. 44 | */ 45 | public static final String RECEIVED_MILLIS = PREFIX + "-Received-Millis"; 46 | 47 | /** 48 | * Synthetic response header: the selected {@link Protocol protocol} ("spdy/3.1", "http/1.1", 49 | * etc). 50 | */ 51 | public static final String SELECTED_PROTOCOL = PREFIX + "-Selected-Protocol"; 52 | 53 | /** Synthetic response header: the location from which the response was loaded. */ 54 | public static final String RESPONSE_SOURCE = PREFIX + "-Response-Source"; 55 | 56 | private OkHeaders() { 57 | } 58 | 59 | public static long contentLength(Request request) { 60 | return contentLength(request.headers()); 61 | } 62 | 63 | public static long contentLength(Response response) { 64 | return contentLength(response.headers()); 65 | } 66 | 67 | public static long contentLength(Headers headers) { 68 | return stringToLong(headers.get("Content-Length")); 69 | } 70 | 71 | private static long stringToLong(String s) { 72 | if (s == null) return -1; 73 | try { 74 | return Long.parseLong(s); 75 | } catch (NumberFormatException e) { 76 | return -1; 77 | } 78 | } 79 | 80 | /** 81 | * Returns true if none of the Vary headers have changed between {@code cachedRequest} and {@code 82 | * newRequest}. 83 | */ 84 | public static boolean varyMatches( 85 | Response cachedResponse, Headers cachedRequest, Request newRequest) { 86 | for (String field : varyFields(cachedResponse)) { 87 | if (!equal(cachedRequest.values(field), newRequest.headers(field))) return false; 88 | } 89 | return true; 90 | } 91 | 92 | /** 93 | * Returns true if a Vary header contains an asterisk. Such responses cannot be cached. 94 | */ 95 | public static boolean hasVaryAll(Response response) { 96 | return hasVaryAll(response.headers()); 97 | } 98 | 99 | /** 100 | * Returns true if a Vary header contains an asterisk. Such responses cannot be cached. 101 | */ 102 | public static boolean hasVaryAll(Headers responseHeaders) { 103 | return varyFields(responseHeaders).contains("*"); 104 | } 105 | 106 | private static Set varyFields(Response response) { 107 | return varyFields(response.headers()); 108 | } 109 | 110 | /** 111 | * Returns the names of the request headers that need to be checked for equality when caching. 112 | */ 113 | public static Set varyFields(Headers responseHeaders) { 114 | Set result = Collections.emptySet(); 115 | for (int i = 0, size = responseHeaders.size(); i < size; i++) { 116 | if (!"Vary".equalsIgnoreCase(responseHeaders.name(i))) continue; 117 | 118 | String value = responseHeaders.value(i); 119 | if (result.isEmpty()) { 120 | result = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); 121 | } 122 | for (String varyField : value.split(",")) { 123 | result.add(varyField.trim()); 124 | } 125 | } 126 | return result; 127 | } 128 | 129 | /** 130 | * Returns the subset of the headers in {@code response}'s request that impact the content of 131 | * response's body. 132 | */ 133 | public static Headers varyHeaders(Response response) { 134 | // Use the request headers sent over the network, since that's what the 135 | // response varies on. Otherwise OkHttp-supplied headers like 136 | // "Accept-Encoding: gzip" may be lost. 137 | Headers requestHeaders = response.networkResponse().request().headers(); 138 | Headers responseHeaders = response.headers(); 139 | return varyHeaders(requestHeaders, responseHeaders); 140 | } 141 | 142 | /** 143 | * Returns the subset of the headers in {@code requestHeaders} that impact the content of 144 | * response's body. 145 | */ 146 | public static Headers varyHeaders(Headers requestHeaders, Headers responseHeaders) { 147 | Set varyFields = varyFields(responseHeaders); 148 | if (varyFields.isEmpty()) return new Headers.Builder().build(); 149 | 150 | Headers.Builder result = new Headers.Builder(); 151 | for (int i = 0, size = requestHeaders.size(); i < size; i++) { 152 | String fieldName = requestHeaders.name(i); 153 | if (varyFields.contains(fieldName)) { 154 | result.add(fieldName, requestHeaders.value(i)); 155 | } 156 | } 157 | return result.build(); 158 | } 159 | 160 | /** 161 | * Returns true if {@code fieldName} is an end-to-end HTTP header, as defined by RFC 2616, 162 | * 13.5.1. 163 | */ 164 | static boolean isEndToEnd(String fieldName) { 165 | return !"Connection".equalsIgnoreCase(fieldName) 166 | && !"Keep-Alive".equalsIgnoreCase(fieldName) 167 | && !"Proxy-Authenticate".equalsIgnoreCase(fieldName) 168 | && !"Proxy-Authorization".equalsIgnoreCase(fieldName) 169 | && !"TE".equalsIgnoreCase(fieldName) 170 | && !"Trailers".equalsIgnoreCase(fieldName) 171 | && !"Transfer-Encoding".equalsIgnoreCase(fieldName) 172 | && !"Upgrade".equalsIgnoreCase(fieldName); 173 | } 174 | 175 | /** 176 | * Parse RFC 2617 challenges. This API is only interested in the scheme name and realm. 177 | */ 178 | public static List parseChallenges(Headers responseHeaders, String challengeHeader) { 179 | // auth-scheme = token 180 | // auth-param = token "=" ( token | quoted-string ) 181 | // challenge = auth-scheme 1*SP 1#auth-param 182 | // realm = "realm" "=" realm-value 183 | // realm-value = quoted-string 184 | List result = new ArrayList<>(); 185 | for (int i = 0, size = responseHeaders.size(); i < size; i++) { 186 | if (!challengeHeader.equalsIgnoreCase(responseHeaders.name(i))) { 187 | continue; 188 | } 189 | String value = responseHeaders.value(i); 190 | int pos = 0; 191 | while (pos < value.length()) { 192 | int tokenStart = pos; 193 | pos = HeaderParser.skipUntil(value, pos, " "); 194 | 195 | String scheme = value.substring(tokenStart, pos).trim(); 196 | pos = HeaderParser.skipWhitespace(value, pos); 197 | 198 | // TODO: This currently only handles schemes with a 'realm' parameter; 199 | // It needs to be fixed to handle any scheme and any parameters 200 | // http://code.google.com/p/android/issues/detail?id=11140 201 | 202 | if (!value.regionMatches(true, pos, "realm=\"", 0, "realm=\"".length())) { 203 | break; // Unexpected challenge parameter; give up! 204 | } 205 | 206 | pos += "realm=\"".length(); 207 | int realmStart = pos; 208 | pos = HeaderParser.skipUntil(value, pos, "\""); 209 | String realm = value.substring(realmStart, pos); 210 | pos++; // Consume '"' close quote. 211 | pos = HeaderParser.skipUntil(value, pos, ","); 212 | pos++; // Consume ',' comma. 213 | pos = HeaderParser.skipWhitespace(value, pos); 214 | result.add(new Challenge(scheme, realm)); 215 | } 216 | } 217 | return result; 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/RealResponseBody.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2014 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | import okhttp3.Headers; 19 | import okhttp3.MediaType; 20 | import okhttp3.ResponseBody; 21 | import okio.BufferedSource; 22 | 23 | public final class RealResponseBody extends ResponseBody { 24 | private final Headers headers; 25 | private final BufferedSource source; 26 | 27 | public RealResponseBody(Headers headers, BufferedSource source) { 28 | this.headers = headers; 29 | this.source = source; 30 | } 31 | 32 | @Override public MediaType contentType() { 33 | String contentType = headers.get("Content-Type"); 34 | return contentType != null ? MediaType.parse(contentType) : null; 35 | } 36 | 37 | @Override public long contentLength() { 38 | return OkHeaders.contentLength(headers); 39 | } 40 | 41 | @Override public BufferedSource source() { 42 | return source; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/RequestException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | import java.io.IOException; 19 | 20 | /** 21 | * Indicates a problem with interpreting a request. It may indicate there was a problem with the 22 | * request itself, or the environment being used to interpret the request (network failure, etc.). 23 | */ 24 | public final class RequestException extends Exception { 25 | 26 | public RequestException(IOException cause) { 27 | super(cause); 28 | } 29 | 30 | @Override 31 | public IOException getCause() { 32 | return (IOException) super.getCause(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/RequestLine.java: -------------------------------------------------------------------------------- 1 | package okhttp3.internal.http; 2 | 3 | import java.net.HttpURLConnection; 4 | import java.net.Proxy; 5 | import okhttp3.HttpUrl; 6 | import okhttp3.Request; 7 | 8 | public final class RequestLine { 9 | private RequestLine() { 10 | } 11 | 12 | /** 13 | * Returns the request status line, like "GET / HTTP/1.1". This is exposed to the application by 14 | * {@link HttpURLConnection#getHeaderFields}, so it needs to be set even if the transport is 15 | * SPDY. 16 | */ 17 | static String get(Request request, Proxy.Type proxyType) { 18 | StringBuilder result = new StringBuilder(); 19 | result.append(request.method()); 20 | result.append(' '); 21 | 22 | if (includeAuthorityInRequestLine(request, proxyType)) { 23 | result.append(request.url()); 24 | } else { 25 | result.append(requestPath(request.url())); 26 | } 27 | 28 | result.append(" HTTP/1.1"); 29 | return result.toString(); 30 | } 31 | 32 | /** 33 | * Returns true if the request line should contain the full URL with host and port (like "GET 34 | * http://android.com/foo HTTP/1.1") or only the path (like "GET /foo HTTP/1.1"). 35 | */ 36 | private static boolean includeAuthorityInRequestLine(Request request, Proxy.Type proxyType) { 37 | return !request.isHttps() && proxyType == Proxy.Type.HTTP; 38 | } 39 | 40 | /** 41 | * Returns the path to request, like the '/' in 'GET / HTTP/1.1'. Never empty, even if the request 42 | * URL is. Includes the query component if it exists. 43 | */ 44 | public static String requestPath(HttpUrl url) { 45 | String path = url.encodedPath(); 46 | String query = url.encodedQuery(); 47 | return query != null ? (path + '?' + query) : path; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/RetryableSink.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2010 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package okhttp3.internal.http; 18 | 19 | import java.io.IOException; 20 | import java.net.ProtocolException; 21 | import okio.Buffer; 22 | import okio.Sink; 23 | import okio.Timeout; 24 | 25 | import static okhttp3.internal.Util.checkOffsetAndCount; 26 | 27 | /** 28 | * An HTTP request body that's completely buffered in memory. This allows the post body to be 29 | * transparently re-sent if the HTTP request must be sent multiple times. 30 | */ 31 | public final class RetryableSink implements Sink { 32 | private boolean closed; 33 | private final int limit; 34 | private final Buffer content = new Buffer(); 35 | 36 | public RetryableSink(int limit) { 37 | this.limit = limit; 38 | } 39 | 40 | public RetryableSink() { 41 | this(-1); 42 | } 43 | 44 | @Override public void close() throws IOException { 45 | if (closed) return; 46 | closed = true; 47 | if (content.size() < limit) { 48 | throw new ProtocolException( 49 | "content-length promised " + limit + " bytes, but received " + content.size()); 50 | } 51 | } 52 | 53 | @Override public void write(Buffer source, long byteCount) throws IOException { 54 | if (closed) throw new IllegalStateException("closed"); 55 | checkOffsetAndCount(source.size(), 0, byteCount); 56 | if (limit != -1 && content.size() > limit - byteCount) { 57 | throw new ProtocolException("exceeded content-length limit of " + limit + " bytes"); 58 | } 59 | content.write(source, byteCount); 60 | } 61 | 62 | @Override public void flush() throws IOException { 63 | } 64 | 65 | @Override public Timeout timeout() { 66 | return Timeout.NONE; 67 | } 68 | 69 | public long contentLength() throws IOException { 70 | return content.size(); 71 | } 72 | 73 | public void writeToSocket(Sink socketOut) throws IOException { 74 | // Copy the content; otherwise we won't have data to retry. 75 | Buffer buffer = new Buffer(); 76 | content.copyTo(buffer, 0, content.size()); 77 | socketOut.write(buffer, buffer.size()); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/RouteException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.http; 17 | 18 | import java.io.IOException; 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | 22 | /** 23 | * An exception thrown to indicate a problem connecting via a single Route. Multiple attempts may 24 | * have been made with alternative protocols, none of which were successful. 25 | */ 26 | public final class RouteException extends Exception { 27 | private static final Method addSuppressedExceptionMethod; 28 | 29 | static { 30 | Method m; 31 | try { 32 | m = Throwable.class.getDeclaredMethod("addSuppressed", Throwable.class); 33 | } catch (Exception e) { 34 | m = null; 35 | } 36 | addSuppressedExceptionMethod = m; 37 | } 38 | 39 | private IOException lastException; 40 | 41 | public RouteException(IOException cause) { 42 | super(cause); 43 | lastException = cause; 44 | } 45 | 46 | public IOException getLastConnectException() { 47 | return lastException; 48 | } 49 | 50 | public void addConnectException(IOException e) { 51 | addSuppressedIfPossible(e, lastException); 52 | lastException = e; 53 | } 54 | 55 | private void addSuppressedIfPossible(IOException e, IOException suppressed) { 56 | if (addSuppressedExceptionMethod != null) { 57 | try { 58 | addSuppressedExceptionMethod.invoke(e, suppressed); 59 | } catch (InvocationTargetException | IllegalAccessException ignored) { 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/http/StatusLine.java: -------------------------------------------------------------------------------- 1 | package okhttp3.internal.http; 2 | 3 | import java.io.IOException; 4 | import java.net.ProtocolException; 5 | import okhttp3.Protocol; 6 | import okhttp3.Response; 7 | 8 | /** An HTTP response status line like "HTTP/1.1 200 OK". */ 9 | public final class StatusLine { 10 | /** Numeric status code, 307: Temporary Redirect. */ 11 | public static final int HTTP_TEMP_REDIRECT = 307; 12 | public static final int HTTP_PERM_REDIRECT = 308; 13 | public static final int HTTP_CONTINUE = 100; 14 | 15 | public final Protocol protocol; 16 | public final int code; 17 | public final String message; 18 | 19 | public StatusLine(Protocol protocol, int code, String message) { 20 | this.protocol = protocol; 21 | this.code = code; 22 | this.message = message; 23 | } 24 | 25 | public static StatusLine get(Response response) { 26 | return new StatusLine(response.protocol(), response.code(), response.message()); 27 | } 28 | 29 | public static StatusLine parse(String statusLine) throws IOException { 30 | // H T T P / 1 . 1 2 0 0 T e m p o r a r y R e d i r e c t 31 | // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 32 | 33 | // Parse protocol like "HTTP/1.1" followed by a space. 34 | int codeStart; 35 | Protocol protocol; 36 | if (statusLine.startsWith("HTTP/1.")) { 37 | if (statusLine.length() < 9 || statusLine.charAt(8) != ' ') { 38 | throw new ProtocolException("Unexpected status line: " + statusLine); 39 | } 40 | int httpMinorVersion = statusLine.charAt(7) - '0'; 41 | codeStart = 9; 42 | if (httpMinorVersion == 0) { 43 | protocol = Protocol.HTTP_1_0; 44 | } else if (httpMinorVersion == 1) { 45 | protocol = Protocol.HTTP_1_1; 46 | } else { 47 | throw new ProtocolException("Unexpected status line: " + statusLine); 48 | } 49 | } else if (statusLine.startsWith("ICY ")) { 50 | // Shoutcast uses ICY instead of "HTTP/1.0". 51 | protocol = Protocol.HTTP_1_0; 52 | codeStart = 4; 53 | } else { 54 | throw new ProtocolException("Unexpected status line: " + statusLine); 55 | } 56 | 57 | // Parse response code like "200". Always 3 digits. 58 | if (statusLine.length() < codeStart + 3) { 59 | throw new ProtocolException("Unexpected status line: " + statusLine); 60 | } 61 | int code; 62 | try { 63 | code = Integer.parseInt(statusLine.substring(codeStart, codeStart + 3)); 64 | } catch (NumberFormatException e) { 65 | throw new ProtocolException("Unexpected status line: " + statusLine); 66 | } 67 | 68 | // Parse an optional response message like "OK" or "Not Modified". If it 69 | // exists, it is separated from the response code by a space. 70 | String message = ""; 71 | if (statusLine.length() > codeStart + 3) { 72 | if (statusLine.charAt(codeStart + 3) != ' ') { 73 | throw new ProtocolException("Unexpected status line: " + statusLine); 74 | } 75 | message = statusLine.substring(codeStart + 4); 76 | } 77 | 78 | return new StatusLine(protocol, code, message); 79 | } 80 | 81 | @Override public String toString() { 82 | StringBuilder result = new StringBuilder(); 83 | result.append(protocol == Protocol.HTTP_1_0 ? "HTTP/1.0" : "HTTP/1.1"); 84 | result.append(' ').append(code); 85 | if (message != null) { 86 | result.append(' ').append(message); 87 | } 88 | return result.toString(); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /okhttp/src/main/java/okhttp3/internal/io/FileSystem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package okhttp3.internal.io; 17 | 18 | import java.io.File; 19 | import java.io.FileNotFoundException; 20 | import java.io.IOException; 21 | import okio.Okio; 22 | import okio.Sink; 23 | import okio.Source; 24 | 25 | /** 26 | * Access to read and write files on a hierarchical data store. Most callers should use the {@link 27 | * #SYSTEM} implementation, which uses the host machine's local file system. Alternate 28 | * implementations may be used to inject faults (for testing) or to transform stored data (to add 29 | * encryption, for example). 30 | * 31 | *

All operations on a file system are racy. For example, guarding a call to {@link #source} with 32 | * {@link #exists} does not guarantee that {@link FileNotFoundException} will not be thrown. The 33 | * file may be moved between the two calls! 34 | * 35 | *

This interface is less ambitious than {@link java.nio.file.FileSystem} introduced in Java 7. 36 | * It lacks important features like file watching, metadata, permissions, and disk space 37 | * information. In exchange for these limitations, this interface is easier to implement and works 38 | * on all versions of Java and Android. 39 | */ 40 | public interface FileSystem { 41 | /** The host machine's local file system. */ 42 | FileSystem SYSTEM = new FileSystem() { 43 | @Override public Source source(File file) throws FileNotFoundException { 44 | return Okio.source(file); 45 | } 46 | 47 | @Override public Sink sink(File file) throws FileNotFoundException { 48 | try { 49 | return Okio.sink(file); 50 | } catch (FileNotFoundException e) { 51 | // Maybe the parent directory doesn't exist? Try creating it first. 52 | file.getParentFile().mkdirs(); 53 | return Okio.sink(file); 54 | } 55 | } 56 | 57 | @Override public Sink appendingSink(File file) throws FileNotFoundException { 58 | try { 59 | return Okio.appendingSink(file); 60 | } catch (FileNotFoundException e) { 61 | // Maybe the parent directory doesn't exist? Try creating it first. 62 | file.getParentFile().mkdirs(); 63 | return Okio.appendingSink(file); 64 | } 65 | } 66 | 67 | @Override public void delete(File file) throws IOException { 68 | // If delete() fails, make sure it's because the file didn't exist! 69 | if (!file.delete() && file.exists()) { 70 | throw new IOException("failed to delete " + file); 71 | } 72 | } 73 | 74 | @Override public boolean exists(File file) throws IOException { 75 | return file.exists(); 76 | } 77 | 78 | @Override public long size(File file) { 79 | return file.length(); 80 | } 81 | 82 | @Override public void rename(File from, File to) throws IOException { 83 | delete(to); 84 | if (!from.renameTo(to)) { 85 | throw new IOException("failed to rename " + from + " to " + to); 86 | } 87 | } 88 | 89 | @Override public void deleteContents(File directory) throws IOException { 90 | File[] files = directory.listFiles(); 91 | if (files == null) { 92 | throw new IOException("not a readable directory: " + directory); 93 | } 94 | for (File file : files) { 95 | if (file.isDirectory()) { 96 | deleteContents(file); 97 | } 98 | if (!file.delete()) { 99 | throw new IOException("failed to delete " + file); 100 | } 101 | } 102 | } 103 | }; 104 | 105 | /** Reads from {@code file}. */ 106 | Source source(File file) throws FileNotFoundException; 107 | 108 | /** 109 | * Writes to {@code file}, discarding any data already present. Creates parent directories if 110 | * necessary. 111 | */ 112 | Sink sink(File file) throws FileNotFoundException; 113 | 114 | /** 115 | * Writes to {@code file}, appending if data is already present. Creates parent directories if 116 | * necessary. 117 | */ 118 | Sink appendingSink(File file) throws FileNotFoundException; 119 | 120 | /** Deletes {@code file} if it exists. Throws if the file exists and cannot be deleted. */ 121 | void delete(File file) throws IOException; 122 | 123 | /** Returns true if {@code file} exists on the file system. */ 124 | boolean exists(File file) throws IOException; 125 | 126 | /** Returns the number of bytes stored in {@code file}, or 0 if it does not exist. */ 127 | long size(File file); 128 | 129 | /** Renames {@code from} to {@code to}. Throws if the file cannot be renamed. */ 130 | void rename(File from, File to) throws IOException; 131 | 132 | /** 133 | * Recursively delete the contents of {@code directory}. Throws an IOException if any file could 134 | * not be deleted, or if {@code dir} is not a readable directory. 135 | */ 136 | void deleteContents(File directory) throws IOException; 137 | } 138 | -------------------------------------------------------------------------------- /okhttp/src/test/java/git/dzc/okhttp/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttp; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /okhttputilslib/.gitignore: -------------------------------------------------------------------------------- 1 | /local.properties 2 | /project.properties 3 | /build 4 | -------------------------------------------------------------------------------- /okhttputilslib/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | 4 | android { 5 | compileSdkVersion 22 6 | buildToolsVersion "22.0.1" 7 | 8 | defaultConfig { 9 | minSdkVersion 8 10 | targetSdkVersion 22 11 | versionCode 5 12 | versionName "1.0.4" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | compile 'com.google.code.gson:gson:2.5' 25 | compile project(':okhttp') 26 | } 27 | //apply from: "https://raw.githubusercontent.com/xiaopansky/android-library-publish-to-jcenter/master/bintrayUpload.gradle" -------------------------------------------------------------------------------- /okhttputilslib/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/dzc/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /okhttputilslib/project.properties: -------------------------------------------------------------------------------- 1 | project.name=okhttputilslib 2 | project.groupId=git.dzc.okhttputilslib 3 | project.artifactId=okhttputilslib 4 | project.packaging=jar 5 | project.siteUrl=https://github.com/duzechao/OKHttpUtils 6 | project.gitUrl=https://github.com/duzechao/OKHttpUtils -------------------------------------------------------------------------------- /okhttputilslib/src/androidTest/java/git/dzc/okhttputilslib/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /okhttputilslib/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /okhttputilslib/src/main/java/git/dzc/okhttputilslib/CacheType.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | import android.support.annotation.IntDef; 4 | 5 | /** 6 | * Created by dzc on 15/12/5. 7 | */ 8 | @IntDef({CacheType.ONLY_NETWORK,CacheType.ONLY_CACHED,CacheType.CACHED_ELSE_NETWORK,CacheType.NETWORK_ELSE_CACHED}) 9 | public @interface CacheType { 10 | int ONLY_NETWORK = 0; 11 | int ONLY_CACHED = 1; 12 | int CACHED_ELSE_NETWORK =2; 13 | int NETWORK_ELSE_CACHED = 3; 14 | 15 | 16 | } 17 | -------------------------------------------------------------------------------- /okhttputilslib/src/main/java/git/dzc/okhttputilslib/Callback.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | 4 | 5 | import java.io.IOException; 6 | 7 | import okhttp3.Call; 8 | import okhttp3.Request; 9 | import okhttp3.Response; 10 | 11 | /** 12 | * Created by dzc on 15/12/11. 13 | */ 14 | public abstract class Callback implements okhttp3.Callback { 15 | public void onStart(){ 16 | 17 | } 18 | public void onFinish(){ 19 | 20 | } 21 | 22 | public abstract void onFailure(Call call, IOException e); 23 | 24 | public abstract void onResponse(Call call, Response response) throws IOException; 25 | } 26 | -------------------------------------------------------------------------------- /okhttputilslib/src/main/java/git/dzc/okhttputilslib/JsonCallback.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | import com.google.gson.reflect.TypeToken; 4 | 5 | import okhttp3.Call; 6 | import okhttp3.Request; 7 | import okhttp3.Response; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.ParameterizedType; 11 | import java.lang.reflect.Type; 12 | 13 | /** 14 | * Created by dzc on 15/12/10. 15 | */ 16 | public abstract class JsonCallback { 17 | public abstract void onFailure(Call call, Exception e); 18 | public abstract void onResponse(Call call,T object) throws IOException; 19 | 20 | public void onStart(){ 21 | 22 | } 23 | public void onFinish(){ 24 | 25 | } 26 | 27 | Type getType(){ 28 | Type type = ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]; 29 | if(type instanceof Class){ 30 | return type; 31 | }else{ 32 | return new TypeToken(){}.getType(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /okhttputilslib/src/main/java/git/dzc/okhttputilslib/UploadListener.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | import okhttp3.*; 4 | 5 | /** 6 | * Created by dzc on 15/12/13. 7 | */ 8 | public interface UploadListener extends okhttp3.Callback{ 9 | void onProgress(long totalBytes, long remainingBytes); 10 | } 11 | -------------------------------------------------------------------------------- /okhttputilslib/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | OKHttpUtilsLib 3 | 4 | -------------------------------------------------------------------------------- /okhttputilslib/src/test/java/git/dzc/okhttputilslib/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package git.dzc.okhttputilslib; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':okhttputilslib', ':okhttp' 2 | --------------------------------------------------------------------------------