mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-02-07 08:34:37 +01:00
[Gradle] Extract mhttp dependency.
This commit is contained in:
parent
15f9db5ca6
commit
0615593d94
@ -170,7 +170,7 @@ dependencies {
|
|||||||
implementation project(":agendacalendarview")
|
implementation project(":agendacalendarview")
|
||||||
implementation "eu.szkolny:cafebar:5bf0c618de"
|
implementation "eu.szkolny:cafebar:5bf0c618de"
|
||||||
implementation "eu.szkolny:material-about-library:0534abf316"
|
implementation "eu.szkolny:material-about-library:0534abf316"
|
||||||
implementation project(":mhttp")
|
implementation "eu.szkolny:mhttp:af4b62e6e9"
|
||||||
implementation "eu.szkolny:nachos:0e5dfcaceb"
|
implementation "eu.szkolny:nachos:0e5dfcaceb"
|
||||||
//implementation project(":Navigation")
|
//implementation project(":Navigation")
|
||||||
implementation project(":szkolny-font")
|
implementation project(":szkolny-font")
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
apply plugin: 'com.android.library'
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion setup.compileSdk
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion 9
|
|
||||||
targetSdkVersion setup.targetSdk
|
|
||||||
consumerProguardFiles 'proguard-rules.pro'
|
|
||||||
versionCode 1
|
|
||||||
versionName PROJ_VERSION
|
|
||||||
javaCompileOptions {
|
|
||||||
annotationProcessorOptions {
|
|
||||||
includeCompileClasspath = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
debugMinify {
|
|
||||||
debuggable = true
|
|
||||||
minifyEnabled = true
|
|
||||||
proguardFiles 'proguard-android.txt'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
packagingOptions {
|
|
||||||
exclude 'META-INF/services/javax.annotation.processing.Processor'
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
lintOptions {
|
|
||||||
textReport true
|
|
||||||
textOutput 'stdout'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compileOnly "androidx.appcompat:appcompat:${versions.appcompat}"
|
|
||||||
compileOnly 'io.reactivex.rxjava2:rxjava:2.1.3'
|
|
||||||
api 'com.squareup.okhttp3:okhttp:3.12.0'
|
|
||||||
api 'com.google.code.gson:gson:2.8.5'
|
|
||||||
//api deps.mhttpannotations
|
|
||||||
// implementation project(':mhttp-annotations')
|
|
||||||
}
|
|
||||||
|
|
||||||
//apply from: 'https://raw.githubusercontent.com/motcwang/Utils/master/bintray-publish/bintray.gradle'
|
|
@ -1,31 +0,0 @@
|
|||||||
# Project-wide Gradle settings.
|
|
||||||
|
|
||||||
# IDE (e.g. Android Studio) users:
|
|
||||||
# Gradle settings configured through the IDE *will override*
|
|
||||||
# any settings specified in this file.
|
|
||||||
|
|
||||||
# For more details on how to configure your build environment visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
|
||||||
|
|
||||||
# Specifies the JVM arguments used for the daemon process.
|
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
|
||||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
|
||||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
|
||||||
|
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
|
||||||
# This option should only be used with decoupled projects. More details, visit
|
|
||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
|
||||||
# org.gradle.parallel=true
|
|
||||||
PROJ_GROUP=im.wangchao
|
|
||||||
PROJ_VERSION=1.10.1
|
|
||||||
PROJ_NAME=mhttp
|
|
||||||
PROJ_WEBSITEURL=http://wangchao.im/2015/11/22/mhttpadapter-post.html
|
|
||||||
PROJ_ISSUETRACKERURL=https://github.com/motcwang/MHttp/issues
|
|
||||||
PROJ_VCSURL=git@github.com:motcwang/MHttp.git
|
|
||||||
PROJ_DESCRIPTION=
|
|
||||||
PROJ_ARTIFACTID=mhttp
|
|
||||||
PROJ_PACKAGING=aar
|
|
||||||
|
|
||||||
DEVELOPER_ID=mot
|
|
||||||
DEVELOPER_NAME=Wang Chao
|
|
||||||
DEVELOPER_EMAIL=magician.of.technique@aliyun.com
|
|
@ -1,4 +0,0 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="im.wangchao.mhttp">
|
|
||||||
|
|
||||||
</manifest>
|
|
@ -1,256 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.exception.ParserException;
|
|
||||||
import im.wangchao.mhttp.internal.exception.ResponseFailException;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.internal.Util;
|
|
||||||
|
|
||||||
import static im.wangchao.mhttp.Response.IO_EXCEPTION_CODE;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : AbsResponseHandler.
|
|
||||||
* Callback lifecycle as follow:
|
|
||||||
* onStart()
|
|
||||||
* -------------------------------------------------------
|
|
||||||
* |
|
|
||||||
* |
|
|
||||||
* is canceled --- Y --- onCancel()
|
|
||||||
* |
|
|
||||||
* N
|
|
||||||
* |
|
|
||||||
* onFinish()
|
|
||||||
* |
|
|
||||||
* |
|
|
||||||
* is successful --- N --- onFailure() ------------------
|
|
||||||
* | |
|
|
||||||
* Y |
|
|
||||||
* | |
|
|
||||||
* backgroundParser() --is download-- onProgress() |
|
|
||||||
* | | |
|
|
||||||
* | | |
|
|
||||||
* onSuccess() onSuccess() |
|
|
||||||
* | | |
|
|
||||||
* | | |
|
|
||||||
* ---------------------------------------------------------
|
|
||||||
* onFinally()
|
|
||||||
* </p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/8/17.</p>
|
|
||||||
* <p>Time : 下午5:56.</p>
|
|
||||||
*/
|
|
||||||
public abstract class AbsCallbackHandler<Parser_Type> implements Callback, Converter<Response, Parser_Type>{
|
|
||||||
private final static ExecutorService DEFAULT_EXECUTOR_SERVICE = Executors.newCachedThreadPool(Util.threadFactory("OkHttp", false));
|
|
||||||
|
|
||||||
public final static String DEFAULT_CHARSET = "UTF-8";
|
|
||||||
|
|
||||||
private Request request;
|
|
||||||
private String responseCharset = DEFAULT_CHARSET;
|
|
||||||
private boolean isFinished;
|
|
||||||
private boolean isCanceled;
|
|
||||||
|
|
||||||
private Executor mExecutor;
|
|
||||||
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public abstract void onSuccess(Parser_Type data, Response response);
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public abstract void onFailure(Response response, Throwable throwable);
|
|
||||||
/** Work on the request thread, that is okhttp thread. */
|
|
||||||
@Deprecated
|
|
||||||
public Parser_Type backgroundParser(Response response) throws Exception{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
/** Work on the request thread, that is okhttp thread. */
|
|
||||||
@Override public Parser_Type apply(Response response) throws Exception {
|
|
||||||
return backgroundParser(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onStart(){}
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onCancel(){}
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onProgress(long bytesWritten, long bytesTotal){}
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onUploadProgress(int bytesWritten, int bytesTotal){}
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onFinish(){}
|
|
||||||
/** Working thread depends on {@link #mExecutor}, default UI. */
|
|
||||||
public void onFinally(Response response){}
|
|
||||||
|
|
||||||
|
|
||||||
@Override final public void onFailure(@NonNull Call call, @NonNull IOException e) {
|
|
||||||
if (call.isCanceled()){
|
|
||||||
sendCancelEvent();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendFinishEvent();
|
|
||||||
|
|
||||||
final Request req = request;
|
|
||||||
Response response = Response.error(req,
|
|
||||||
IO_EXCEPTION_CODE,
|
|
||||||
e.getMessage());
|
|
||||||
|
|
||||||
sendFailureEvent(response, e);
|
|
||||||
sendFinallyEvent(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override final public void onResponse(@NonNull Call call, @NonNull okhttp3.Response response) throws IOException {
|
|
||||||
if (call.isCanceled()){
|
|
||||||
response.close();
|
|
||||||
sendCancelEvent();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sendFinishEvent();
|
|
||||||
|
|
||||||
final Request req = request;
|
|
||||||
Response okResponse;
|
|
||||||
if (response.isSuccessful() || response.isRedirect()
|
|
||||||
|| req.allowedErrorCodes().contains(response.code())) {
|
|
||||||
try {
|
|
||||||
okResponse = Response.newResponse(req, response);
|
|
||||||
Parser_Type data = apply(okResponse);
|
|
||||||
sendSuccessEvent(data, okResponse);
|
|
||||||
} catch (Exception e) {
|
|
||||||
sendFailureEvent(okResponse = Response.newResponse(req, response), e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sendFailureEvent(okResponse = Response.newResponse(req, response), new ResponseFailException());
|
|
||||||
}
|
|
||||||
// todo response.close()
|
|
||||||
sendFinallyEvent(okResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbsCallbackHandler(){}
|
|
||||||
|
|
||||||
@Override public void initialize(Request request){
|
|
||||||
isFinished = false;
|
|
||||||
isCanceled = false;
|
|
||||||
this.request = request;
|
|
||||||
this.mExecutor = request.callbackExecutor();
|
|
||||||
if (this.mExecutor == null){
|
|
||||||
this.mExecutor = request.callbackThreadMode().executor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isFinished(){
|
|
||||||
return isFinished;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the charset for the response string. If not set, the default is UTF-8.
|
|
||||||
*/
|
|
||||||
public final void setCharset(@NonNull final String charset) {
|
|
||||||
this.responseCharset = charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* subclass can override this method to change charset.
|
|
||||||
*/
|
|
||||||
public String charset() {
|
|
||||||
return TextUtils.isEmpty(responseCharset) ? DEFAULT_CHARSET : responseCharset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return request accept
|
|
||||||
*/
|
|
||||||
@Override public String accept(){
|
|
||||||
return Accept.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void print(String message){
|
|
||||||
Log.d(AbsCallbackHandler.class.getSimpleName(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable protected final String byteArrayToString(byte[] bytes){
|
|
||||||
try {
|
|
||||||
return bytes == null ? null : new String(bytes, charset());
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Request getRequest(){
|
|
||||||
return this.request;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void sendUploadProgressEvent(final int bytesWritten, final int bytesTotal) {
|
|
||||||
execute(()->{
|
|
||||||
try {
|
|
||||||
onUploadProgress(bytesWritten, bytesTotal);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
//Silent
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void sendProgressEvent(final long bytesWritten, final long bytesTotal) {
|
|
||||||
execute(()->{
|
|
||||||
try {
|
|
||||||
onProgress(bytesWritten, bytesTotal);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
//Silent
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final void sendSuccessEvent(final Parser_Type data, final Response response) {
|
|
||||||
execute(() -> onSuccess(data, response));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final void sendFailureEvent(final Response response, @Nullable final Throwable throwable) {
|
|
||||||
execute(() -> onFailure(response, throwable));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final void sendStartEvent() {
|
|
||||||
if (request.callbackThreadMode() == ThreadMode.BACKGROUND){
|
|
||||||
DEFAULT_EXECUTOR_SERVICE.execute(this::onStart);
|
|
||||||
} else {
|
|
||||||
execute(this::onStart);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final void sendFinishEvent() {
|
|
||||||
execute(() -> {
|
|
||||||
AbsCallbackHandler.this.isFinished = true;
|
|
||||||
onFinish();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final void sendFinallyEvent(final Response response) {
|
|
||||||
execute(() -> onFinally(response));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ final synchronized void sendCancelEvent() {
|
|
||||||
if (isCanceled){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
execute(() -> {
|
|
||||||
AbsCallbackHandler.this.isCanceled = true;
|
|
||||||
onCancel();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void execute(Runnable command){
|
|
||||||
if (mExecutor == null || threadInterrupted()){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mExecutor.execute(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean threadInterrupted(){
|
|
||||||
return Thread.currentThread().isInterrupted();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,33 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import androidx.annotation.StringDef;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Accept.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/4/25.</p>
|
|
||||||
* <p>Time : 上午11:06.</p>
|
|
||||||
*/
|
|
||||||
public interface Accept {
|
|
||||||
String EMPTY = "";
|
|
||||||
String ACCEPT_JSON = "application/json;charset=utf-8";
|
|
||||||
String ACCEPT_TEXT = "text/html;charset=utf-8";
|
|
||||||
String ACCEPT_DATA = "application/octet-stream";
|
|
||||||
String ACCEPT_IMAGE = "image/png,image/jpeg,image/*";
|
|
||||||
String ACCEPT_FILE = "application/octet-stream";
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@StringDef({
|
|
||||||
Accept.EMPTY,
|
|
||||||
Accept.ACCEPT_JSON,
|
|
||||||
Accept.ACCEPT_TEXT,
|
|
||||||
Accept.ACCEPT_DATA,
|
|
||||||
Accept.ACCEPT_IMAGE,
|
|
||||||
Accept.ACCEPT_FILE
|
|
||||||
})
|
|
||||||
public @interface $Accept {
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,149 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.net.Socket;
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.security.GeneralSecurityException;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.SSLSocket;
|
|
||||||
import javax.net.ssl.SSLSocketFactory;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Android5SSL.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/19.</p>
|
|
||||||
* <p>Time : 上午11:09.</p>
|
|
||||||
*/
|
|
||||||
/*package*/ class Android5SSL extends SSLSocketFactory {
|
|
||||||
private SSLSocketFactory defaultFactory;
|
|
||||||
// Android 5.0+ (API level21) provides reasonable default settings
|
|
||||||
// but it still allows SSLv3
|
|
||||||
// https://developer.android.com/about/versions/android-5.0-changes.html#ssl
|
|
||||||
static String protocols[] = null, cipherSuites[] = null;
|
|
||||||
|
|
||||||
static {
|
|
||||||
try {
|
|
||||||
SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket();
|
|
||||||
if (socket != null) {
|
|
||||||
/* set reasonable protocol versions */
|
|
||||||
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
|
|
||||||
// - remove all SSL versions (especially SSLv3) because they're insecure now
|
|
||||||
List<String> protocols = new LinkedList<>();
|
|
||||||
for (String protocol : socket.getSupportedProtocols())
|
|
||||||
if (!protocol.toUpperCase().contains("SSL"))
|
|
||||||
protocols.add(protocol);
|
|
||||||
Android5SSL.protocols = protocols.toArray(new String[protocols.size()]);
|
|
||||||
/* set up reasonable cipher suites */
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
|
||||||
// choose known secure cipher suites
|
|
||||||
List<String> allowedCiphers = Arrays.asList(
|
|
||||||
// TLS 1.2
|
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
|
||||||
"TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256",
|
|
||||||
// maximum interoperability
|
|
||||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
// additionally
|
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
|
|
||||||
List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
|
|
||||||
// take all allowed ciphers that are available and put them into preferredCiphers
|
|
||||||
HashSet<String> preferredCiphers = new HashSet<>(allowedCiphers);
|
|
||||||
preferredCiphers.retainAll(availableCiphers);
|
|
||||||
/* For maximum security, preferredCiphers should *replace* enabled ciphers (thus disabling
|
|
||||||
* ciphers which are enabled by default, but have become unsecure), but I guess for
|
|
||||||
* the security level of DAVdroid and maximum compatibility, disabling of insecure
|
|
||||||
* ciphers should be a server-side task */
|
|
||||||
// add preferred ciphers to enabled ciphers
|
|
||||||
HashSet<String> enabledCiphers = preferredCiphers;
|
|
||||||
enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites())));
|
|
||||||
Android5SSL.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Android5SSL(X509TrustManager tm) {
|
|
||||||
try {
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
sslContext.init(null, (tm != null) ? new X509TrustManager[]{tm} : null, null);
|
|
||||||
defaultFactory = sslContext.getSocketFactory();
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
throw new AssertionError(); // The system has no TLS. Just give up.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void upgradeTLS(SSLSocket ssl) {
|
|
||||||
// Android 5.0+ (API level21) provides reasonable default settings
|
|
||||||
// but it still allows SSLv3
|
|
||||||
// https://developer.android.com/about/versions/android-5.0-changes.html#ssl
|
|
||||||
if (protocols != null) {
|
|
||||||
ssl.setEnabledProtocols(protocols);
|
|
||||||
}
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && cipherSuites != null) {
|
|
||||||
ssl.setEnabledCipherSuites(cipherSuites);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String[] getDefaultCipherSuites() {
|
|
||||||
return cipherSuites;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String[] getSupportedCipherSuites() {
|
|
||||||
return cipherSuites;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
|
|
||||||
Socket ssl = defaultFactory.createSocket(s, host, port, autoClose);
|
|
||||||
if (ssl instanceof SSLSocket)
|
|
||||||
upgradeTLS((SSLSocket) ssl);
|
|
||||||
return ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
|
|
||||||
Socket ssl = defaultFactory.createSocket(host, port);
|
|
||||||
if (ssl instanceof SSLSocket)
|
|
||||||
upgradeTLS((SSLSocket) ssl);
|
|
||||||
return ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
|
|
||||||
Socket ssl = defaultFactory.createSocket(host, port, localHost, localPort);
|
|
||||||
if (ssl instanceof SSLSocket)
|
|
||||||
upgradeTLS((SSLSocket) ssl);
|
|
||||||
return ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Socket createSocket(InetAddress host, int port) throws IOException {
|
|
||||||
Socket ssl = defaultFactory.createSocket(host, port);
|
|
||||||
if (ssl instanceof SSLSocket)
|
|
||||||
upgradeTLS((SSLSocket) ssl);
|
|
||||||
return ssl;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
|
|
||||||
Socket ssl = defaultFactory.createSocket(address, port, localAddress, localPort);
|
|
||||||
if (ssl instanceof SSLSocket)
|
|
||||||
upgradeTLS((SSLSocket) ssl);
|
|
||||||
return ssl;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : BindApi.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/19.</p>
|
|
||||||
* <p>Time : 上午8:23.</p>
|
|
||||||
*/
|
|
||||||
final class BindApi {
|
|
||||||
/** HttpProcessor.SUFFIX */
|
|
||||||
private static final String SUFFIX = "_HttpBinder";
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked") public static <T> T bind(Class<T> type) {
|
|
||||||
String name = type.getName() + SUFFIX;
|
|
||||||
T obj = null;
|
|
||||||
try {
|
|
||||||
obj = (T)Class.forName(name).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(BindApi.class.getSimpleName(), e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : OkCallback.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/6/3.</p>
|
|
||||||
* <p>Time : 上午10:16.</p>
|
|
||||||
*/
|
|
||||||
public interface Callback extends okhttp3.Callback {
|
|
||||||
|
|
||||||
Callback EMPTY = new Callback() {
|
|
||||||
@Override public void initialize(Request request) {}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Call call, IOException e) {}
|
|
||||||
|
|
||||||
@Override public void onResponse(Call call, Response response) throws IOException {
|
|
||||||
response.close();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the callback.
|
|
||||||
*/
|
|
||||||
void initialize(Request request);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request accept.
|
|
||||||
*/
|
|
||||||
String accept();
|
|
||||||
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Converter.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/20.</p>
|
|
||||||
* <p>Time : 下午10:26.</p>
|
|
||||||
*/
|
|
||||||
public interface Converter<T, R> {
|
|
||||||
|
|
||||||
R apply(T t) throws Exception;
|
|
||||||
}
|
|
@ -1,179 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.cert.CertificateException;
|
|
||||||
import java.security.cert.CertificateFactory;
|
|
||||||
import java.security.cert.X509Certificate;
|
|
||||||
|
|
||||||
import javax.net.ssl.KeyManager;
|
|
||||||
import javax.net.ssl.KeyManagerFactory;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.TrustManager;
|
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.internal.Util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : HTTPS.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/9/2.</p>
|
|
||||||
* <p>Time : 下午3:58.</p>
|
|
||||||
*/
|
|
||||||
/*package*/ final class HTTPS {
|
|
||||||
|
|
||||||
// 信任所有证书的 TrustManager
|
|
||||||
private static X509TrustManager TrustAllCertificate = new X509TrustManager() {
|
|
||||||
@Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return new java.security.cert.X509Certificate[]{};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trust all certificate for debug
|
|
||||||
*/
|
|
||||||
/*package*/ static void trustAllCertificate(OkHttpClient.Builder builder) {
|
|
||||||
builder.sslSocketFactory(new Android5SSL(TrustAllCertificate), TrustAllCertificate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
|
|
||||||
InputStream... certificates) throws Exception {
|
|
||||||
setCertificates(builder, null, certificates, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
|
|
||||||
X509TrustManager trustManager,
|
|
||||||
InputStream bksFile,
|
|
||||||
String password) throws Exception {
|
|
||||||
setCertificates(builder, trustManager, null, bksFile, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
|
|
||||||
InputStream[] certificates,
|
|
||||||
InputStream bksFile,
|
|
||||||
String password) throws Exception {
|
|
||||||
setCertificates(builder, null, certificates, bksFile, password);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
/*package*/ static void setCertificates(OkHttpClient.Builder builder,
|
|
||||||
X509TrustManager trustManager,
|
|
||||||
InputStream[] certificates,
|
|
||||||
InputStream bksFile,
|
|
||||||
String password) throws Exception {
|
|
||||||
TrustManager[] trustManagers = prepareTrustManager(certificates);
|
|
||||||
KeyManager[] keyManagers = prepareKeyManager(bksFile, password);
|
|
||||||
|
|
||||||
X509TrustManager manager;
|
|
||||||
if (trustManager != null) {
|
|
||||||
manager = trustManager;
|
|
||||||
} else if (trustManagers != null) {
|
|
||||||
manager = chooseTrustManager(trustManagers);
|
|
||||||
} else {
|
|
||||||
manager = TrustAllCertificate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建TLS类型的SSLContext对象, that uses our finalTrustManager
|
|
||||||
SSLContext sslContext = SSLContext.getInstance("TLS");
|
|
||||||
// 用上面得到的trustManagers初始化SSLContext,这样sslContext就会信任keyStore中的证书
|
|
||||||
// 第一个参数是授权的密钥管理器,用来授权验证,比如授权自签名的证书验证。第二个是被授权的证书管理器,用来验证服务器端的证书
|
|
||||||
sslContext.init(keyManagers, new TrustManager[]{manager}, new SecureRandom());
|
|
||||||
builder.sslSocketFactory(sslContext.getSocketFactory(), manager);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ static TrustManager[] prepareTrustManager(InputStream... certificates) throws Exception {
|
|
||||||
if (certificates == null || certificates.length <= 0) return null;
|
|
||||||
|
|
||||||
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
|
|
||||||
// 创建一个默认类型的KeyStore,存储我们信任的证书
|
|
||||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
||||||
keyStore.load(null);
|
|
||||||
int index = 0;
|
|
||||||
for (InputStream certificate : certificates) {
|
|
||||||
String certificateAlias = Integer.toString(index++);
|
|
||||||
keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));
|
|
||||||
Util.closeQuietly(certificate);
|
|
||||||
}
|
|
||||||
|
|
||||||
TrustManagerFactory trustManagerFactory = TrustManagerFactory.
|
|
||||||
getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
//用我们之前的keyStore实例初始化TrustManagerFactory,使TrustManagerFactory信任keyStore中的证书
|
|
||||||
trustManagerFactory.init(keyStore);
|
|
||||||
return trustManagerFactory.getTrustManagers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ static KeyManager[] prepareKeyManager(InputStream bksFile, String password) throws Exception{
|
|
||||||
if (bksFile == null || password == null) return null;
|
|
||||||
|
|
||||||
KeyStore clientKeyStore = KeyStore.getInstance("BKS");
|
|
||||||
clientKeyStore.load(bksFile, password.toCharArray());
|
|
||||||
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
|
||||||
keyManagerFactory.init(clientKeyStore, password.toCharArray());
|
|
||||||
return keyManagerFactory.getKeyManagers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ static X509TrustManager chooseTrustManager(TrustManager[] trustManagers) {
|
|
||||||
for (TrustManager trustManager : trustManagers) {
|
|
||||||
if (trustManager instanceof X509TrustManager) {
|
|
||||||
return (X509TrustManager) trustManager;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* X509TrustManager */
|
|
||||||
/*package*/ static class MyTrustManager implements X509TrustManager {
|
|
||||||
private X509TrustManager defaultTrustManager;
|
|
||||||
private X509TrustManager localTrustManager;
|
|
||||||
|
|
||||||
/*package*/ MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException {
|
|
||||||
TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
|
||||||
var4.init((KeyStore) null);
|
|
||||||
defaultTrustManager = chooseTrustManager(var4.getTrustManagers());
|
|
||||||
this.localTrustManager = localTrustManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
// try {
|
|
||||||
// defaultTrustManager.checkClientTrusted(chain, authType);
|
|
||||||
// } catch (CertificateException e) {
|
|
||||||
// localTrustManager.checkClientTrusted(chain, authType);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
|
||||||
try {
|
|
||||||
defaultTrustManager.checkServerTrusted(chain, authType);
|
|
||||||
} catch (CertificateException e) {
|
|
||||||
localTrustManager.checkServerTrusted(chain, authType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override public X509Certificate[] getAcceptedIssuers() {
|
|
||||||
return new X509Certificate[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,252 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.StatFs;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor;
|
|
||||||
import im.wangchao.mhttp.internal.interceptor.MBridgeInterceptor;
|
|
||||||
import im.wangchao.mhttp.internal.log.LoggerImpl;
|
|
||||||
import okhttp3.Cache;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MHttp.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/6/2.</p>
|
|
||||||
* <p>Time : 上午8:40.</p>
|
|
||||||
*/
|
|
||||||
public final class MHttp {
|
|
||||||
private static volatile MHttp instance;
|
|
||||||
|
|
||||||
private OkHttpClient.Builder mOkBuilder;
|
|
||||||
private OkHttpClient mInnerClient;
|
|
||||||
private URLInterceptor mURLInterceptor;
|
|
||||||
private final HttpLoggingInterceptor mLoggingInterceptor = new HttpLoggingInterceptor(LoggerImpl.instance.get());
|
|
||||||
|
|
||||||
public static MHttp instance(){
|
|
||||||
if (instance == null) {
|
|
||||||
synchronized (MHttp.class){
|
|
||||||
instance = new MHttp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create annotation api
|
|
||||||
*/
|
|
||||||
public static <T> T create(Class<T> api){
|
|
||||||
return BindApi.bind(api);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* OkHttpClient
|
|
||||||
*/
|
|
||||||
public MHttp customOkHttpClient(@NonNull OkHttpClient client){
|
|
||||||
mOkBuilder = client.newBuilder()
|
|
||||||
.addInterceptor(MBridgeInterceptor.instance.get());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set logging level
|
|
||||||
*/
|
|
||||||
public MHttp loggingLevel(HttpLoggingInterceptor.Level level){
|
|
||||||
mLoggingInterceptor.setLevel(level);
|
|
||||||
LoggerImpl.instance.get().setLevel(level);
|
|
||||||
if (!mOkBuilder.interceptors().contains(mLoggingInterceptor)) {
|
|
||||||
mOkBuilder.addInterceptor(mLoggingInterceptor);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set cache Dir
|
|
||||||
*/
|
|
||||||
public MHttp cache(Context context, String dirName) {
|
|
||||||
File cache = new File(context.getApplicationContext().getCacheDir(), dirName);
|
|
||||||
if (!cache.exists()) {
|
|
||||||
//noinspection ResultOfMethodCallIgnored
|
|
||||||
cache.mkdirs();
|
|
||||||
}
|
|
||||||
long size = 5 * 1024 * 1024;
|
|
||||||
try {
|
|
||||||
StatFs statFs = new StatFs(cache.getAbsolutePath());
|
|
||||||
long count, blockSize;
|
|
||||||
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1){
|
|
||||||
count = statFs.getBlockCountLong();
|
|
||||||
blockSize = statFs.getBlockSizeLong();
|
|
||||||
} else {
|
|
||||||
count = statFs.getBlockCount();
|
|
||||||
blockSize = statFs.getBlockSize();
|
|
||||||
}
|
|
||||||
long available = count * blockSize;
|
|
||||||
// Target 2% of the total space.
|
|
||||||
size = available / 50;
|
|
||||||
} catch (IllegalArgumentException ignored) {
|
|
||||||
}
|
|
||||||
// Bound inside min/max size for disk cache.
|
|
||||||
size = Math.max(Math.min(size, size * 10), size);
|
|
||||||
|
|
||||||
mOkBuilder.cache(new Cache(cache, size));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set connect, read and write time with {@link TimeUnit#SECONDS}
|
|
||||||
*/
|
|
||||||
public MHttp timeout(int timeout){
|
|
||||||
timeout(timeout, TimeUnit.SECONDS);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp timeout(int timeout, TimeUnit unit){
|
|
||||||
connectTimeout(timeout, unit);
|
|
||||||
readTimeout(timeout, unit);
|
|
||||||
writeTimeout(timeout, unit);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp connectTimeout(long timeout, TimeUnit unit){
|
|
||||||
mOkBuilder.connectTimeout(timeout, unit);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp readTimeout(long timeout, TimeUnit unit){
|
|
||||||
mOkBuilder.readTimeout(timeout, unit);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp writeTimeout(long timeout, TimeUnit unit){
|
|
||||||
mOkBuilder.writeTimeout(timeout, unit);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp setURLInterceptor(URLInterceptor interceptor){
|
|
||||||
this.mURLInterceptor = interceptor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trust all certificate for debug
|
|
||||||
*/
|
|
||||||
public MHttp trustAllCertificate(){
|
|
||||||
HTTPS.trustAllCertificate(mOkBuilder);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
public MHttp setCertificates(InputStream... certificates){
|
|
||||||
return setCertificates(certificates, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
public MHttp setCertificates(X509TrustManager trustManager, InputStream bksFile, String password) {
|
|
||||||
try {
|
|
||||||
HTTPS.setCertificates(mOkBuilder, trustManager, null, bksFile, password);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set Certificate
|
|
||||||
*/
|
|
||||||
public MHttp setCertificates(InputStream[] certificates, InputStream bksFile, String password) {
|
|
||||||
try {
|
|
||||||
HTTPS.setCertificates(mOkBuilder, null, certificates, bksFile, password);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MHttp hostnameVerifier(HostnameVerifier hostnameVerifier){
|
|
||||||
mOkBuilder.hostnameVerifier(hostnameVerifier);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Current client.
|
|
||||||
*/
|
|
||||||
public OkHttpClient client(){
|
|
||||||
if (mOkBuilder == null){
|
|
||||||
throw new IllegalArgumentException("OkHttpClient cannot be null, please call the MHttp#client(OkHttpClient client) method first.");
|
|
||||||
}
|
|
||||||
if (mInnerClient == null){
|
|
||||||
mInnerClient = mOkBuilder.build();
|
|
||||||
}
|
|
||||||
return mInnerClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel all request.
|
|
||||||
*/
|
|
||||||
public MHttp cancelAll(){
|
|
||||||
client().dispatcher().cancelAll();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel request with {@code tag}
|
|
||||||
*/
|
|
||||||
public MHttp cancel(Object tag){
|
|
||||||
for (Call call : client().dispatcher().queuedCalls()) {
|
|
||||||
if (tag.equals(call.request().tag())) {
|
|
||||||
call.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Call call : client().dispatcher().runningCalls()) {
|
|
||||||
if (tag.equals(call.request().tag())) {
|
|
||||||
call.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ String proceedURL(String url){
|
|
||||||
if (mURLInterceptor != null){
|
|
||||||
return mURLInterceptor.interceptor(url);
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ HttpUrl proceedURL(HttpUrl url){
|
|
||||||
if (mURLInterceptor != null){
|
|
||||||
return mURLInterceptor.interceptor(url);
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*package*/ URL proceedURL(URL url){
|
|
||||||
if (mURLInterceptor != null){
|
|
||||||
return mURLInterceptor.interceptor(url);
|
|
||||||
}
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@private
|
|
||||||
private MHttp(){
|
|
||||||
//default instance
|
|
||||||
mOkBuilder = new OkHttpClient.Builder()
|
|
||||||
.addInterceptor(MBridgeInterceptor.instance.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import androidx.annotation.StringDef;
|
|
||||||
|
|
||||||
import java.lang.annotation.Retention;
|
|
||||||
import java.lang.annotation.RetentionPolicy;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Method.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/8.</p>
|
|
||||||
* <p>Time : 下午4:08.</p>
|
|
||||||
*/
|
|
||||||
public interface Method {
|
|
||||||
String POST = "POST";
|
|
||||||
String GET = "GET";
|
|
||||||
String HEAD = "HEAD";
|
|
||||||
String DELETE = "DELETE";
|
|
||||||
String PUT = "PUT";
|
|
||||||
String PATCH = "PATCH";
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.SOURCE)
|
|
||||||
@StringDef({Method.POST, Method.GET, Method.HEAD, Method.DELETE, Method.PUT, Method.PATCH})
|
|
||||||
@interface MethodType{}
|
|
||||||
}
|
|
@ -1,503 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.util.Pair;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.body.JSONBody;
|
|
||||||
import im.wangchao.mhttp.body.MediaTypeUtils;
|
|
||||||
import okhttp3.CacheControl;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okio.Buffer;
|
|
||||||
import okio.BufferedSink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MRequest.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/6/2.</p>
|
|
||||||
* <p>Time : 下午4:16.</p>
|
|
||||||
*/
|
|
||||||
public final class Request {
|
|
||||||
public static Builder builder(){
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private final okhttp3.Request mRawRequest;
|
|
||||||
private final RequestParams mRequestParams;
|
|
||||||
private final Callback mCallback;
|
|
||||||
private final MediaType mMediaType;
|
|
||||||
private final Executor mExecutor;
|
|
||||||
private final ThreadMode mThreadMode;
|
|
||||||
private final JsonObject mJsonBody;
|
|
||||||
private final okhttp3.OkHttpClient mOkHttpClient;
|
|
||||||
private final List<Integer> mAllowedErrorCodes;
|
|
||||||
private final String mTextBody;
|
|
||||||
|
|
||||||
private okhttp3.Call mRawCall;
|
|
||||||
|
|
||||||
private Request(Builder builder){
|
|
||||||
mRawRequest = builder.mRawRequest;
|
|
||||||
mRequestParams = builder.mRequestParams;
|
|
||||||
mCallback = builder.mCallback;
|
|
||||||
mMediaType = builder.mMediaType;
|
|
||||||
mExecutor = builder.mExecutor;
|
|
||||||
mThreadMode = builder.mThreadMode;
|
|
||||||
mJsonBody = builder.mJsonBody;
|
|
||||||
mOkHttpClient = builder.mOkHttpClient;
|
|
||||||
mAllowedErrorCodes = builder.mAllowedErrorCodes;
|
|
||||||
mTextBody = builder.mTextBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public okhttp3.Request raw() {
|
|
||||||
return mRawRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUrl url() {
|
|
||||||
return mRawRequest.url();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String method() {
|
|
||||||
return mRawRequest.method();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Headers headers() {
|
|
||||||
return mRawRequest.headers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String header(String name) {
|
|
||||||
return mRawRequest.header(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> headers(String name) {
|
|
||||||
return mRawRequest.headers(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestBody body() {
|
|
||||||
return mRawRequest.body();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String bodyToString(){
|
|
||||||
try {
|
|
||||||
final Buffer buffer = new Buffer();
|
|
||||||
body().writeTo(buffer);
|
|
||||||
return buffer.readUtf8();
|
|
||||||
} catch (final Exception e) {
|
|
||||||
return "did not work. "+e.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object tag() {
|
|
||||||
return mRawRequest.tag();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder newBuilder() {
|
|
||||||
return new Builder(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Callback callback() {
|
|
||||||
return mCallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JsonObject jsonBody() {
|
|
||||||
return mJsonBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String textBody() {
|
|
||||||
return mTextBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public OkHttpClient okHttpClient() {
|
|
||||||
return mOkHttpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Integer> allowedErrorCodes() {
|
|
||||||
return mAllowedErrorCodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the cache control directives for this response. This is never null, even if this
|
|
||||||
* response contains no {@code Cache-Control} header.
|
|
||||||
*/
|
|
||||||
public CacheControl cacheControl() {
|
|
||||||
return mRawRequest.cacheControl();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHttps() {
|
|
||||||
return mRawRequest.isHttps();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The executor used for {@link Callback} methods on which thread work.
|
|
||||||
*/
|
|
||||||
public Executor callbackExecutor() {
|
|
||||||
return mExecutor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link Callback} methods on which thread work.
|
|
||||||
*/
|
|
||||||
public ThreadMode callbackThreadMode() {
|
|
||||||
return mThreadMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestParams requestParams(){
|
|
||||||
return mRequestParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the async request.
|
|
||||||
*/
|
|
||||||
public Request enqueue(){
|
|
||||||
Callback callback = callback();
|
|
||||||
callback.initialize(this);
|
|
||||||
if (callback instanceof AbsCallbackHandler){
|
|
||||||
((AbsCallbackHandler) callback).sendStartEvent();
|
|
||||||
}
|
|
||||||
rawCall().enqueue(callback);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send the sync request.
|
|
||||||
*/
|
|
||||||
public Response execute() throws IOException {
|
|
||||||
return Response.newResponse(this, rawCall().execute());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel this request
|
|
||||||
*/
|
|
||||||
public Request cancel(){
|
|
||||||
if (rawCall().isCanceled()){
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
rawCall().cancel();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Call rawCall(){
|
|
||||||
if (mRawCall == null){
|
|
||||||
OkHttpClient client;
|
|
||||||
if (mOkHttpClient == null) {
|
|
||||||
client = MHttp.instance().client();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
client = mOkHttpClient;
|
|
||||||
}
|
|
||||||
mRawCall = client.newCall(raw());
|
|
||||||
}
|
|
||||||
return mRawCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String toString() {
|
|
||||||
return mRawRequest.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
|
||||||
private static final String TAG = Builder.class.getSimpleName();
|
|
||||||
|
|
||||||
okhttp3.Request mRawRequest;
|
|
||||||
okhttp3.Request.Builder mRawBuilder;
|
|
||||||
RequestParams mRequestParams;
|
|
||||||
Callback mCallback;
|
|
||||||
String mMethod;
|
|
||||||
MediaType mMediaType;
|
|
||||||
Executor mExecutor;
|
|
||||||
ThreadMode mThreadMode;
|
|
||||||
JsonObject mJsonBody;
|
|
||||||
OkHttpClient mOkHttpClient;
|
|
||||||
List<Integer> mAllowedErrorCodes;
|
|
||||||
String mTextBody;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
mCallback = Callback.EMPTY;
|
|
||||||
mMethod = Method.GET;
|
|
||||||
mRawBuilder = new okhttp3.Request.Builder();
|
|
||||||
mRequestParams = new RequestParams();
|
|
||||||
mThreadMode = ThreadMode.BACKGROUND;
|
|
||||||
mJsonBody = null;
|
|
||||||
mOkHttpClient = null;
|
|
||||||
mAllowedErrorCodes = new ArrayList<>();
|
|
||||||
mTextBody = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Builder(Request request) {
|
|
||||||
mCallback = request.mCallback;
|
|
||||||
mMethod = request.method();
|
|
||||||
mRequestParams = request.mRequestParams;
|
|
||||||
mRawBuilder = request.mRawRequest.newBuilder();
|
|
||||||
mExecutor = request.mExecutor;
|
|
||||||
mThreadMode = request.mThreadMode;
|
|
||||||
mMediaType = request.mMediaType;
|
|
||||||
mJsonBody = request.mJsonBody;
|
|
||||||
mOkHttpClient = request.mOkHttpClient;
|
|
||||||
mAllowedErrorCodes = request.mAllowedErrorCodes;
|
|
||||||
mTextBody = request.mTextBody;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder url(HttpUrl url) {
|
|
||||||
mRawBuilder.url(MHttp.instance().proceedURL(url));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder url(String url) {
|
|
||||||
mRawBuilder.url(MHttp.instance().proceedURL(url));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder url(URL url) {
|
|
||||||
mRawBuilder.url(MHttp.instance().proceedURL(url));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder header(String name, String value) {
|
|
||||||
mRawBuilder.header(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder addHeader(String name, String value) {
|
|
||||||
mRawBuilder.addHeader(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder removeHeader(String name) {
|
|
||||||
mRawBuilder.removeHeader(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder headers(Headers headers) {
|
|
||||||
mRawBuilder.headers(headers);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder cacheControl(CacheControl cacheControl) {
|
|
||||||
mRawBuilder.cacheControl(cacheControl);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder withClient(OkHttpClient okHttpClient) {
|
|
||||||
mOkHttpClient = okHttpClient;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder get() {
|
|
||||||
return method(Method.GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder head() {
|
|
||||||
return method(Method.HEAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder post() {
|
|
||||||
return method(Method.POST);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder postJson() {
|
|
||||||
return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder delete() {
|
|
||||||
return method(Method.DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder put() {
|
|
||||||
return method(Method.PUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder patch() {
|
|
||||||
return method(Method.PATCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setJsonBody(JsonObject jsonBody) {
|
|
||||||
mJsonBody = jsonBody;
|
|
||||||
return method(Method.POST).contentType(MediaTypeUtils.APPLICATION_JSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder setTextBody(String textBody, String mediaType) {
|
|
||||||
mTextBody = textBody;
|
|
||||||
return method(Method.POST).contentType(mediaType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder allowErrorCode(int code) {
|
|
||||||
mAllowedErrorCodes.add(code);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder addParameter(String key, Object value){
|
|
||||||
mRequestParams.put(key, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder addParameter(String key, InputStream stream, String name){
|
|
||||||
mRequestParams.put(key, stream, name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder addParameter(String key, InputStream stream, String name, String contentType){
|
|
||||||
mRequestParams.put(key, stream, name, contentType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder addParameter(String key, File file, String contentType){
|
|
||||||
try {
|
|
||||||
mRequestParams.put(key, file, contentType);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
Log.e(TAG, e.getMessage(), e);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder requestParams(RequestParams params) {
|
|
||||||
if (params != null){
|
|
||||||
mRequestParams = params;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder addParams(List<Pair<String, Object>> params) {
|
|
||||||
if (params != null){
|
|
||||||
mRequestParams.put(params);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder method(@NonNull String method) {
|
|
||||||
this.mMethod = method;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder tag(Object tag) {
|
|
||||||
mRawBuilder.tag(tag);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder callback(@NonNull Callback callback){
|
|
||||||
mCallback = callback;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder callbackExecutor(Executor executor){
|
|
||||||
mExecutor = executor;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder callbackThreadMode(ThreadMode threadMode){
|
|
||||||
mThreadMode = threadMode;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder userAgent(String ua){
|
|
||||||
header("User-Agent", ua);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder contentType(@NonNull String contentType){
|
|
||||||
this.mMediaType = MediaType.parse(contentType);
|
|
||||||
header("Content-Type", contentType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder contentType(@NonNull MediaType mediaType){
|
|
||||||
this.mMediaType = mediaType;
|
|
||||||
header("Content-Type", this.mMediaType.toString());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Request build() {
|
|
||||||
if (mMediaType == null){
|
|
||||||
// judgment request header
|
|
||||||
List<String> headers = mRawBuilder.build().headers("Content-Type");
|
|
||||||
final int len = headers.size();
|
|
||||||
if (len != 0){
|
|
||||||
StringBuilder mediaType = new StringBuilder();
|
|
||||||
for (int i = 0; i < len; i++){
|
|
||||||
mediaType.append(headers.get(i));
|
|
||||||
}
|
|
||||||
mMediaType = MediaType.parse(mediaType.toString());
|
|
||||||
if (mMediaType == null){
|
|
||||||
mMediaType = MediaTypeUtils.DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// default is application/x-www-form-urlencoded
|
|
||||||
else {
|
|
||||||
mMediaType = MediaTypeUtils.DEFAULT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Accept.EMPTY.equals(mCallback.accept())) {
|
|
||||||
addHeader("Accept", mCallback.accept());
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (mMethod) {
|
|
||||||
case Method.GET:
|
|
||||||
mRawBuilder.method(mMethod, null);
|
|
||||||
mRawRequest = mRawBuilder.build();
|
|
||||||
mRawRequest = mRawBuilder.url(mRequestParams.formatURLParams(mRawRequest.url())).build();
|
|
||||||
break;
|
|
||||||
case Method.HEAD:
|
|
||||||
mRawBuilder.method(mMethod, null);
|
|
||||||
mRawRequest = mRawBuilder.build();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (MediaTypeUtils.isJSON(mMediaType) && mJsonBody != null) {
|
|
||||||
mRawBuilder.method(mMethod, new JSONBody(mJsonBody.toString()));
|
|
||||||
}
|
|
||||||
else if (mTextBody != null) {
|
|
||||||
mRawBuilder.method(mMethod, new RequestBody() {
|
|
||||||
@Override
|
|
||||||
public MediaType contentType() {
|
|
||||||
return mMediaType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void writeTo(BufferedSink sink) throws IOException {
|
|
||||||
sink.write(mTextBody.getBytes(), 0, mTextBody.getBytes().length);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long contentLength() throws IOException {
|
|
||||||
return mTextBody.getBytes().length;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// inject callback if exist.
|
|
||||||
mRawBuilder.method(mMethod, mRequestParams.requestBody(mMediaType,
|
|
||||||
(mCallback instanceof AbsCallbackHandler ? (AbsCallbackHandler) mCallback : null)));
|
|
||||||
}
|
|
||||||
mRawRequest = mRawBuilder.build();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Request(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,378 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.body.FileBody;
|
|
||||||
import im.wangchao.mhttp.body.JSONBody;
|
|
||||||
import im.wangchao.mhttp.body.MediaTypeUtils;
|
|
||||||
import im.wangchao.mhttp.body.OctetStreamBody;
|
|
||||||
import im.wangchao.mhttp.body.ProgressRequestBody;
|
|
||||||
import okhttp3.FormBody;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.MultipartBody;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
|
|
||||||
import static im.wangchao.mhttp.body.MediaTypeUtils.APPLICATION_OCTET_STREAM;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : RequestParams.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/8/17.</p>
|
|
||||||
* <p>Time : 下午2:16.</p>
|
|
||||||
*/
|
|
||||||
public class RequestParams{
|
|
||||||
final private static String UTF_8_STR = "utf-8";
|
|
||||||
final private static Charset UTF_8 = Charset.forName(UTF_8_STR);
|
|
||||||
|
|
||||||
//params
|
|
||||||
final private List<Pair<String, Object>> urlParams = new ArrayList<>();
|
|
||||||
final private ConcurrentHashMap<String, StreamWrapper> streamParams = new ConcurrentHashMap<>();
|
|
||||||
final private ConcurrentHashMap<String, FileWrapper> fileParams = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
//default
|
|
||||||
private String contentEncoding = UTF_8_STR;
|
|
||||||
|
|
||||||
public RequestParams(){
|
|
||||||
this((Map<String, Object>)null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestParams(Map<String, Object> params){
|
|
||||||
if (params != null){
|
|
||||||
for(Map.Entry<String, Object> entry : params.entrySet()){
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestParams(Object...keysAndValues){
|
|
||||||
int len = keysAndValues.length;
|
|
||||||
if (len % 2 != 0){
|
|
||||||
throw new IllegalArgumentException("Supplied arguments must be even.");
|
|
||||||
}
|
|
||||||
for (int i = 0; i < len; i += 2){
|
|
||||||
String key = String.valueOf(keysAndValues[i]);
|
|
||||||
String val = String.valueOf(keysAndValues[i + 1]);
|
|
||||||
put(key, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public RequestParams(RequestParams params){
|
|
||||||
if (params == null){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.urlParams.addAll(params.getUrlParams());
|
|
||||||
this.streamParams.putAll(params.getStreamParams());
|
|
||||||
this.fileParams.putAll(params.getFileParams());
|
|
||||||
this.contentEncoding = params.contentEncoding();
|
|
||||||
}
|
|
||||||
|
|
||||||
RequestBody requestBody(MediaType mediaType, AbsCallbackHandler callback){
|
|
||||||
if (isJSON(mediaType)){
|
|
||||||
Charset charset = mediaType.charset();
|
|
||||||
if (charset == null){
|
|
||||||
charset = UTF_8;
|
|
||||||
}
|
|
||||||
return new JSONBody(parseJSON(), charset.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isForm(mediaType)){
|
|
||||||
return formBody();
|
|
||||||
}
|
|
||||||
|
|
||||||
MultipartBody.Builder builder = new MultipartBody.Builder();
|
|
||||||
builder.setType(MultipartBody.FORM);
|
|
||||||
//form
|
|
||||||
for (Pair<String, Object> entry: urlParams){
|
|
||||||
builder.addFormDataPart(entry.first, String.valueOf(entry.second));
|
|
||||||
}
|
|
||||||
//stream
|
|
||||||
for (Map.Entry<String, RequestParams.StreamWrapper> streamEntry: streamParams.entrySet()){
|
|
||||||
builder.addPart(
|
|
||||||
okhttp3.Headers.of("Content-Disposition",
|
|
||||||
String.format("form-data;name=\"%s\";filename=\"%s\"", streamEntry.getKey(), streamEntry.getValue().name),
|
|
||||||
"Content-Transfer-Encoding", "binary"),
|
|
||||||
uploadProgressRequestBody(
|
|
||||||
new OctetStreamBody(streamEntry.getValue().inputStream, streamEntry.getValue().contentType),
|
|
||||||
callback));
|
|
||||||
}
|
|
||||||
//file
|
|
||||||
for (Map.Entry<String, RequestParams.FileWrapper> file: fileParams.entrySet()){
|
|
||||||
builder.addPart(uploadProgressRequestBody(
|
|
||||||
new FileBody(file.getValue().file, file.getValue().contentType),
|
|
||||||
callback
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ProgressRequestBody uploadProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){
|
|
||||||
return new ProgressRequestBody(requestBody, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private FormBody formBody(){
|
|
||||||
FormBody.Builder builder = new FormBody.Builder();
|
|
||||||
for (Pair<String, Object> entry: urlParams){
|
|
||||||
builder.add(entry.first, String.valueOf(entry.second));
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Request body media type is JSON.
|
|
||||||
*/
|
|
||||||
private boolean isJSON(MediaType mediaType){
|
|
||||||
return MediaTypeUtils.isJSON(mediaType) && streamParams.size() == 0
|
|
||||||
&& fileParams.size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Request body media type is Form.
|
|
||||||
*/
|
|
||||||
private boolean isForm(MediaType mediaType){
|
|
||||||
return MediaTypeUtils.isFORM(mediaType) && streamParams.size() == 0
|
|
||||||
&& fileParams.size() == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request body encoding.
|
|
||||||
*/
|
|
||||||
public RequestParams contentEncoding(@NonNull String encoding) {
|
|
||||||
if (Charset.isSupported(encoding)){
|
|
||||||
this.contentEncoding = encoding;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String contentEncoding(){
|
|
||||||
return contentEncoding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(Map<String, String> params){
|
|
||||||
if (params != null){
|
|
||||||
for(Map.Entry<String, String> entry : params.entrySet()){
|
|
||||||
put(entry.getKey(), entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(List<Pair<String, Object>> params){
|
|
||||||
if (params != null){
|
|
||||||
urlParams.addAll(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, String value) {
|
|
||||||
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
|
|
||||||
urlParams.add(new Pair<>(key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, Object value) {
|
|
||||||
if (!TextUtils.isEmpty(key) && (value != null)) {
|
|
||||||
if (value instanceof File){
|
|
||||||
try {
|
|
||||||
put(key, (File)value);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
// Silent
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
urlParams.add(new Pair<>(key, value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void put(String key, InputStream stream){
|
|
||||||
put(key, stream, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, InputStream stream, String name){
|
|
||||||
put(key, stream, name, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, InputStream stream, String name, String contentType){
|
|
||||||
if (!TextUtils.isEmpty(key) && stream != null){
|
|
||||||
streamParams.put(key, StreamWrapper.newInstance(stream, name, contentType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(File file) throws FileNotFoundException {
|
|
||||||
put(file, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(File file, String contentType) throws FileNotFoundException {
|
|
||||||
put(RequestParams.class.getSimpleName(), file, contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, File file) throws FileNotFoundException {
|
|
||||||
put(key, file, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void put(String key, File file, String contentType) throws FileNotFoundException {
|
|
||||||
if (file == null || !file.exists()){
|
|
||||||
throw new FileNotFoundException();
|
|
||||||
}
|
|
||||||
if (!TextUtils.isEmpty(key)){
|
|
||||||
fileParams.put(key, new FileWrapper(file, contentType));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void remove(String key){
|
|
||||||
Pair<String, Object> removing = null;
|
|
||||||
for (Pair<String, Object> entry: urlParams) {
|
|
||||||
if (entry.first.equals(key)) {
|
|
||||||
removing = entry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
urlParams.remove(removing);
|
|
||||||
streamParams.remove(key);
|
|
||||||
fileParams.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean has(String key){
|
|
||||||
for (Pair<String, Object> entry: urlParams) {
|
|
||||||
if (entry.first.equals(key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return (streamParams.containsKey(key) || fileParams.containsKey(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty(){
|
|
||||||
return urlParams.isEmpty() && streamParams.isEmpty() && fileParams.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String parseJSON(){
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
|
|
||||||
String key;
|
|
||||||
Object value;
|
|
||||||
for (Pair<String, Object> entry: urlParams){
|
|
||||||
key = entry.first;
|
|
||||||
value = entry.second;
|
|
||||||
|
|
||||||
if (key.isEmpty() || value == null){
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
json.put(key, value);
|
|
||||||
} catch (JSONException e) {
|
|
||||||
// Silent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return json.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, StreamWrapper> getStreamParams() {
|
|
||||||
return streamParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, FileWrapper> getFileParams() {
|
|
||||||
return fileParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Pair<String, Object>> getUrlParams() {
|
|
||||||
return urlParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpUrl formatURLParams(HttpUrl url) {
|
|
||||||
HttpUrl.Builder builder = url.newBuilder();
|
|
||||||
if (urlParams.size() != 0) {
|
|
||||||
for (Pair<String, Object> entry : urlParams) {
|
|
||||||
try {
|
|
||||||
builder.addEncodedQueryParameter(URLEncoder.encode(entry.first, contentEncoding),
|
|
||||||
URLEncoder.encode(String.valueOf(entry.second), contentEncoding));
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
//Silent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Format get params.
|
|
||||||
*/
|
|
||||||
public String formatURLParams() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (urlParams.size() != 0) {
|
|
||||||
for (Pair<String, Object> entry : urlParams) {
|
|
||||||
String encode = "";
|
|
||||||
try {
|
|
||||||
encode = URLEncoder.encode(String.valueOf(entry.second), contentEncoding);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
//Silent
|
|
||||||
}
|
|
||||||
sb.append(entry.first).append("=").append(encode);
|
|
||||||
sb.append("&");
|
|
||||||
}
|
|
||||||
sb.deleteCharAt(sb.length() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString().replace(" ", "%20");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Url params convert to {@link List}.
|
|
||||||
*/
|
|
||||||
public List<Pair<String, Object>> getParamsList(){
|
|
||||||
List<Pair<String, Object>> params = new LinkedList<>();
|
|
||||||
|
|
||||||
for (Pair<String, Object> entry : urlParams) {
|
|
||||||
params.add(new Pair<>(entry.first, entry.second));
|
|
||||||
}
|
|
||||||
|
|
||||||
return params;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class FileWrapper {
|
|
||||||
public final File file;
|
|
||||||
public final String contentType;
|
|
||||||
|
|
||||||
public FileWrapper(File file, String contentType) {
|
|
||||||
this.file = file;
|
|
||||||
this.contentType = contentType;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StreamWrapper {
|
|
||||||
public final InputStream inputStream;
|
|
||||||
public final String name;
|
|
||||||
public final String contentType;
|
|
||||||
|
|
||||||
public StreamWrapper(InputStream inputStream, String name, String contentType) {
|
|
||||||
this.inputStream = inputStream;
|
|
||||||
this.name = name;
|
|
||||||
this.contentType = contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
static StreamWrapper newInstance(InputStream inputStream, String name, String contentType) {
|
|
||||||
return new StreamWrapper(
|
|
||||||
inputStream,
|
|
||||||
name,
|
|
||||||
TextUtils.isEmpty(contentType) ? APPLICATION_OCTET_STREAM : contentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.Protocol;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MResponse.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/6/3.</p>
|
|
||||||
* <p>Time : 下午3:03.</p>
|
|
||||||
*/
|
|
||||||
public final class Response {
|
|
||||||
public final static int IO_EXCEPTION_CODE = 1000;
|
|
||||||
|
|
||||||
public static Response error(Request request, int code, String message){
|
|
||||||
if (message == null){
|
|
||||||
message = "unknown exception.";
|
|
||||||
}
|
|
||||||
return new Response(request, new okhttp3.Response.Builder()
|
|
||||||
.request(request.raw())
|
|
||||||
.protocol(Protocol.HTTP_1_1)
|
|
||||||
.code(code)
|
|
||||||
.message(message)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Response newResponse(Request request, okhttp3.Response raw){
|
|
||||||
return new Response(request, raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Request request;
|
|
||||||
private final okhttp3.Response rawResponse;
|
|
||||||
public String parserErrorBody = null;
|
|
||||||
|
|
||||||
private Response(Request request, okhttp3.Response rawResponse){
|
|
||||||
this.request = request;
|
|
||||||
this.rawResponse = rawResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Request request() {
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
public okhttp3.Response raw() {
|
|
||||||
return rawResponse;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** HTTP status code. */
|
|
||||||
public int code() {
|
|
||||||
return rawResponse.code();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** HTTP status message or null if unknown. */
|
|
||||||
public String message() {
|
|
||||||
return rawResponse.message();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** HTTP headers. */
|
|
||||||
public Headers headers() {
|
|
||||||
return rawResponse.headers();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.executor.BACKGROUND;
|
|
||||||
import im.wangchao.mhttp.executor.MAIN;
|
|
||||||
import im.wangchao.mhttp.executor.SENDING;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ThreadMode.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/8/3.</p>
|
|
||||||
* <p>Time : 下午12:44.</p>
|
|
||||||
*/
|
|
||||||
public enum ThreadMode {
|
|
||||||
/**
|
|
||||||
* Callback will be called in the same thread, which is sending the request.
|
|
||||||
*/
|
|
||||||
SENDING{
|
|
||||||
@Override public Executor executor() {
|
|
||||||
return new SENDING();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Callback will be called in Android's main thread (UI thread).
|
|
||||||
*/
|
|
||||||
MAIN{
|
|
||||||
@Override public Executor executor() {
|
|
||||||
return new MAIN();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback will be called in a background thread. That is, work on the request thread(okhttp thread).
|
|
||||||
*/
|
|
||||||
BACKGROUND{
|
|
||||||
@Override public Executor executor() {
|
|
||||||
return new BACKGROUND();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public abstract Executor executor();
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
package im.wangchao.mhttp;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : URLInterceptor.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/1/15.</p>
|
|
||||||
* <p>Time : 上午11:01.</p>
|
|
||||||
*/
|
|
||||||
public interface URLInterceptor {
|
|
||||||
|
|
||||||
String interceptor(String origin);
|
|
||||||
|
|
||||||
HttpUrl interceptor(HttpUrl origin);
|
|
||||||
|
|
||||||
URL interceptor(URL origin);
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package im.wangchao.mhttp.body;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.internal.Util;
|
|
||||||
import okio.BufferedSink;
|
|
||||||
import okio.Okio;
|
|
||||||
import okio.Source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : FileBody.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/8.</p>
|
|
||||||
* <p>Time : 下午6:10.</p>
|
|
||||||
*/
|
|
||||||
public final class FileBody extends RequestBody{
|
|
||||||
private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET;
|
|
||||||
private final MediaType contentType;
|
|
||||||
private final File file;
|
|
||||||
|
|
||||||
public FileBody(File file){
|
|
||||||
this(file, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileBody(File file, String contentType){
|
|
||||||
this.file = file;
|
|
||||||
this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public MediaType contentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long contentLength() throws IOException {
|
|
||||||
return file.length();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
|
||||||
Source source = null;
|
|
||||||
try {
|
|
||||||
source = Okio.source(file);
|
|
||||||
sink.writeAll(source);
|
|
||||||
} finally {
|
|
||||||
Util.closeQuietly(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
package im.wangchao.mhttp.body;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okio.BufferedSink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : JSONBody.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/8.</p>
|
|
||||||
* <p>Time : 下午4:31.</p>
|
|
||||||
*/
|
|
||||||
public final class JSONBody extends RequestBody{
|
|
||||||
private final static MediaType CONTENT_TYPE = MediaTypeUtils.JSON;
|
|
||||||
private final MediaType contentType;
|
|
||||||
private final byte[] bytes;
|
|
||||||
|
|
||||||
public JSONBody(String content){
|
|
||||||
this(content, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JSONBody(String content, String charset){
|
|
||||||
if (TextUtils.isEmpty(content)){
|
|
||||||
throw new NullPointerException("content == null");
|
|
||||||
}
|
|
||||||
if (TextUtils.isEmpty(charset)){
|
|
||||||
charset = "utf-8";
|
|
||||||
}
|
|
||||||
this.contentType = TextUtils.isEmpty(charset) ? CONTENT_TYPE : MediaType.parse("application/json; charset=" + charset);
|
|
||||||
bytes = content.getBytes(contentType.charset());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public MediaType contentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long contentLength() throws IOException {
|
|
||||||
return bytes.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
|
||||||
sink.write(bytes, 0, bytes.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
package im.wangchao.mhttp.body;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MediaType.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2017/6/23.</p>
|
|
||||||
* <p>Time : 下午2:15.</p>
|
|
||||||
*/
|
|
||||||
public final class MediaTypeUtils {
|
|
||||||
/** MediaType String */
|
|
||||||
public static final String APPLICATION_OCTET_STREAM = "application/octet-stream";
|
|
||||||
public static final String APPLICATION_JSON = "application/json; charset=utf-8";
|
|
||||||
public static final String APPLICATION_FORM = "application/x-www-form-urlencoded";
|
|
||||||
public static final String APPLICATION_XML = "application/xml";
|
|
||||||
|
|
||||||
/** MediaType */
|
|
||||||
public static final MediaType JSON = MediaType.parse(APPLICATION_JSON);
|
|
||||||
public static final MediaType OCTET = MediaType.parse(APPLICATION_OCTET_STREAM);
|
|
||||||
public static final MediaType FORM = MediaType.parse(APPLICATION_FORM);
|
|
||||||
public static final MediaType XML = MediaType.parse(APPLICATION_XML);
|
|
||||||
public static final MediaType DEFAULT = FORM;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 判断两个 MediaType 是否相等,只判断 type 和 subType。
|
|
||||||
*/
|
|
||||||
public static boolean equals(@NonNull MediaType first, @NonNull MediaType second){
|
|
||||||
String first_type_subType = first.type().concat(first.subtype());
|
|
||||||
String second_type_subType = second.type().concat(second.subtype());
|
|
||||||
|
|
||||||
return TextUtils.equals(first_type_subType, second_type_subType);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isJSON(@NonNull MediaType mediaType){
|
|
||||||
return equals(mediaType, JSON);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isOCTET(@NonNull MediaType mediaType){
|
|
||||||
return equals(mediaType, OCTET);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isFORM(@NonNull MediaType mediaType){
|
|
||||||
return equals(mediaType, FORM);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isXML(@NonNull MediaType mediaType){
|
|
||||||
return equals(mediaType, XML);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
package im.wangchao.mhttp.body;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import android.text.TextUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.internal.Util;
|
|
||||||
import okio.Buffer;
|
|
||||||
import okio.BufferedSink;
|
|
||||||
import okio.Okio;
|
|
||||||
import okio.Source;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : OctetStreamBody.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/8.</p>
|
|
||||||
* <p>Time : 下午4:31.</p>
|
|
||||||
*/
|
|
||||||
public final class OctetStreamBody extends RequestBody{
|
|
||||||
private final static MediaType CONTENT_TYPE = MediaTypeUtils.OCTET;
|
|
||||||
private final MediaType contentType;
|
|
||||||
private final InputStream stream;
|
|
||||||
private long contentLength = -1L;
|
|
||||||
private Buffer buffer;
|
|
||||||
|
|
||||||
public OctetStreamBody(InputStream stream){
|
|
||||||
this(stream, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OctetStreamBody(InputStream stream, String contentType){
|
|
||||||
this.stream = stream;
|
|
||||||
this.contentType = TextUtils.isEmpty(contentType) ? CONTENT_TYPE : MediaType.parse(contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public MediaType contentType() {
|
|
||||||
return contentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long contentLength() throws IOException {
|
|
||||||
long result = contentLength;
|
|
||||||
if (result != -1L) return result;
|
|
||||||
return contentLength = writeOrCountBytes(null, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
|
||||||
contentLength = writeOrCountBytes(sink, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private long writeOrCountBytes(@Nullable BufferedSink sink, boolean countBytes) throws IOException{
|
|
||||||
long byteCount = 0L;
|
|
||||||
|
|
||||||
if (countBytes) {
|
|
||||||
buffer = new Buffer();
|
|
||||||
Source source = null;
|
|
||||||
try {
|
|
||||||
source = Okio.source(stream);
|
|
||||||
buffer.writeAll(source);
|
|
||||||
} finally {
|
|
||||||
Util.closeQuietly(source);
|
|
||||||
}
|
|
||||||
|
|
||||||
byteCount = buffer.size();
|
|
||||||
|
|
||||||
return byteCount;
|
|
||||||
} else {
|
|
||||||
if (sink == null){
|
|
||||||
return byteCount;
|
|
||||||
}
|
|
||||||
Source source = null;
|
|
||||||
try {
|
|
||||||
source = Okio.source(buffer == null ? stream : buffer.inputStream());
|
|
||||||
return sink.writeAll(source);
|
|
||||||
} finally {
|
|
||||||
if (buffer != null){
|
|
||||||
buffer.clear();
|
|
||||||
}
|
|
||||||
Util.closeQuietly(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
package im.wangchao.mhttp.body;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okio.Buffer;
|
|
||||||
import okio.BufferedSink;
|
|
||||||
import okio.ForwardingSink;
|
|
||||||
import okio.Okio;
|
|
||||||
import okio.Sink;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ProgressRequestBody.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/1/30.</p>
|
|
||||||
* <p>Time : 下午8:25.</p>
|
|
||||||
*/
|
|
||||||
public class ProgressRequestBody extends RequestBody {
|
|
||||||
|
|
||||||
private final RequestBody mRequestBody;
|
|
||||||
private final AbsCallbackHandler mCallback;
|
|
||||||
private BufferedSink mBufferedSink;
|
|
||||||
|
|
||||||
public ProgressRequestBody(RequestBody requestBody, AbsCallbackHandler callback){
|
|
||||||
this.mRequestBody = requestBody;
|
|
||||||
this.mCallback = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public MediaType contentType() {
|
|
||||||
return mRequestBody.contentType();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public long contentLength() throws IOException {
|
|
||||||
return mRequestBody.contentLength();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void writeTo(@NonNull BufferedSink sink) throws IOException {
|
|
||||||
if (mCallback == null){
|
|
||||||
mRequestBody.writeTo(sink);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (mBufferedSink == null){
|
|
||||||
mBufferedSink = Okio.buffer(forward(sink));
|
|
||||||
}
|
|
||||||
|
|
||||||
mRequestBody.writeTo(mBufferedSink);
|
|
||||||
mBufferedSink.flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Sink forward(Sink sink){
|
|
||||||
return new ForwardingSink(sink) {
|
|
||||||
private long bytesWritten = 0L;
|
|
||||||
private long contentLength = 0L;
|
|
||||||
|
|
||||||
@Override public void write(@NonNull Buffer source, long byteCount) throws IOException {
|
|
||||||
super.write(source, byteCount);
|
|
||||||
if (contentLength == 0) {
|
|
||||||
contentLength = contentLength();
|
|
||||||
}
|
|
||||||
bytesWritten += byteCount;
|
|
||||||
|
|
||||||
mCallback.sendUploadProgressEvent((int) bytesWritten, (int) contentLength);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : BinaryResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/18.</p>
|
|
||||||
* <p>Time : 下午2:49.</p>
|
|
||||||
*/
|
|
||||||
public class BinaryCallbackHandler extends AbsCallbackHandler<byte[]> {
|
|
||||||
|
|
||||||
@Override public void onSuccess(byte[] data, Response response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public byte[] backgroundParser(Response response) throws Exception {
|
|
||||||
return response.raw().body().bytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_DATA;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ImageResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/18.</p>
|
|
||||||
* <p>Time : 下午2:49.</p>
|
|
||||||
*/
|
|
||||||
public abstract class BitmapCallbackHandler extends AbsCallbackHandler<Bitmap> {
|
|
||||||
@Override public void onSuccess(Bitmap bitmap, Response response) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_IMAGE;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
import im.wangchao.mhttp.internal.exception.ParserException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : GSONResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/20.</p>
|
|
||||||
* <p>Time : 上午9:06.</p>
|
|
||||||
*/
|
|
||||||
public abstract class CustomCallbackHandler<T> extends TextCallbackHandler {
|
|
||||||
|
|
||||||
@Override final public void onSuccess(String data, Response response) {
|
|
||||||
if (data != null) {
|
|
||||||
onSuccess(parser(data));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
onFailure(response, new ParserException());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** parser Json to T */
|
|
||||||
protected abstract T parser(String data);
|
|
||||||
|
|
||||||
public void onSuccess(T t){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URLDecoder;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
import okhttp3.internal.Util;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : FileResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/18.</p>
|
|
||||||
* <p>Time : 下午2:39.</p>
|
|
||||||
*/
|
|
||||||
public class FileCallbackHandler extends AbsCallbackHandler<File> {
|
|
||||||
private File file;
|
|
||||||
final private static int BUFFER_SIZE = 4096;
|
|
||||||
|
|
||||||
public FileCallbackHandler(Context context){
|
|
||||||
this.file = getTempFile(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileCallbackHandler(File file){
|
|
||||||
this.file = file;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected File getFile(){
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onSuccess(File file, Response response){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public File backgroundParser(Response response) throws IOException{
|
|
||||||
writeFile(response.raw(), file);
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_FILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getTempFile(Context context){
|
|
||||||
try {
|
|
||||||
return File.createTempFile("temp", "_handled", context.getCacheDir());
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* write file , send progress message
|
|
||||||
*/
|
|
||||||
protected void writeFile(okhttp3.Response response, File file) throws IOException {
|
|
||||||
if (file == null){
|
|
||||||
throw new IllegalArgumentException("File == null");
|
|
||||||
}
|
|
||||||
if (this.file.isDirectory()) {
|
|
||||||
String contentDisposition = response.header("content-disposition");
|
|
||||||
if (contentDisposition != null) {
|
|
||||||
if (contentDisposition.contains("*=UTF-8")) {
|
|
||||||
contentDisposition = contentDisposition.replace("*=UTF-8''", "\"") + "\"";
|
|
||||||
contentDisposition = URLDecoder.decode(contentDisposition, "UTF-8");
|
|
||||||
}
|
|
||||||
String filename = contentDisposition.substring(contentDisposition.indexOf("\"") + 1, contentDisposition.lastIndexOf("\""));
|
|
||||||
this.file = new File(file, filename);
|
|
||||||
file = this.file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
InputStream instream = response.body().byteStream();
|
|
||||||
long contentLength = response.body().contentLength();
|
|
||||||
FileOutputStream buffer = new FileOutputStream(file);
|
|
||||||
if (instream != null) {
|
|
||||||
try {
|
|
||||||
byte[] tmp = new byte[BUFFER_SIZE];
|
|
||||||
int l;
|
|
||||||
long count = 0;
|
|
||||||
while ((l = instream.read(tmp)) != -1 && !Thread.currentThread().isInterrupted()) {
|
|
||||||
count += l;
|
|
||||||
buffer.write(tmp, 0, l);
|
|
||||||
|
|
||||||
sendProgressEvent(count, contentLength);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Util.closeQuietly(instream);
|
|
||||||
buffer.flush();
|
|
||||||
Util.closeQuietly(buffer);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
|
|
||||||
public class JsonArrayCallbackHandler extends AbsCallbackHandler<JsonArray> {
|
|
||||||
|
|
||||||
@Override public void onSuccess(JsonArray data, Response response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public JsonArray backgroundParser(Response response) throws Exception {
|
|
||||||
try {
|
|
||||||
byte[] body = response.raw().body().bytes();
|
|
||||||
String bodyString = byteArrayToString(body);
|
|
||||||
JsonArray object = new JsonParser().parse(bodyString).getAsJsonArray();
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_JSON;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.google.gson.JsonParser;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : JSONResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/18.</p>
|
|
||||||
* <p>Time : 下午2:25.</p>
|
|
||||||
*/
|
|
||||||
public class JsonCallbackHandler extends AbsCallbackHandler<JsonObject> {
|
|
||||||
|
|
||||||
@Override public void onSuccess(JsonObject data, Response response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public JsonObject backgroundParser(Response response) throws Exception {
|
|
||||||
try {
|
|
||||||
byte[] body = response.raw().body().bytes();
|
|
||||||
String bodyString = byteArrayToString(body);
|
|
||||||
try {
|
|
||||||
return new JsonParser().parse(bodyString).getAsJsonObject();
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
response.parserErrorBody = bodyString;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_JSON;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package im.wangchao.mhttp.callback;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Accept;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : TextResponseHandler.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 15/10/18.</p>
|
|
||||||
* <p>Time : 下午2:41.</p>
|
|
||||||
*/
|
|
||||||
public class TextCallbackHandler extends AbsCallbackHandler<String> {
|
|
||||||
@Override public void onSuccess(String data, Response response) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String backgroundParser(Response response) throws Exception {
|
|
||||||
return byteArrayToString(response.raw().body().bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return Accept.ACCEPT_TEXT;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package im.wangchao.mhttp.executor;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : BACKGROUND.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/9/2.</p>
|
|
||||||
* <p>Time : 下午4:50.</p>
|
|
||||||
*/
|
|
||||||
public final class BACKGROUND implements Executor {
|
|
||||||
@Override public void execute(@NonNull Runnable command) {
|
|
||||||
command.run();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package im.wangchao.mhttp.executor;
|
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MainThread.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/9/2.</p>
|
|
||||||
* <p>Time : 下午4:45.</p>
|
|
||||||
*/
|
|
||||||
public final class MAIN implements Executor{
|
|
||||||
private final Handler handler = new Handler(Looper.getMainLooper());
|
|
||||||
|
|
||||||
@Override public void execute(@NonNull Runnable command) {
|
|
||||||
handler.post(command);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package im.wangchao.mhttp.executor;
|
|
||||||
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.os.Looper;
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : SENDING.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/9/2.</p>
|
|
||||||
* <p>Time : 下午4:47.</p>
|
|
||||||
*/
|
|
||||||
public final class SENDING implements Executor {
|
|
||||||
private final Handler handler;
|
|
||||||
public SENDING(){
|
|
||||||
if (Looper.myLooper() == null){
|
|
||||||
throw new RuntimeException("The Looper of the current thread is null, please call Looper.prepare() on your thread.");
|
|
||||||
}
|
|
||||||
handler = new Handler(Looper.myLooper());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void execute(@NonNull Runnable command) {
|
|
||||||
handler.post(command);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Singleton.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/8/25.</p>
|
|
||||||
* <p>Time : 上午10:37.</p>
|
|
||||||
*/
|
|
||||||
public abstract class Singleton<T> {
|
|
||||||
private T instance;
|
|
||||||
|
|
||||||
protected abstract T create();
|
|
||||||
|
|
||||||
public T get(){
|
|
||||||
if (instance == null){
|
|
||||||
synchronized (this){
|
|
||||||
if (instance == null){
|
|
||||||
instance = create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Version.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/8/24.</p>
|
|
||||||
* <p>Time : 下午2:47.</p>
|
|
||||||
*/
|
|
||||||
public class Version {
|
|
||||||
private Version(){
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String userAgent() {
|
|
||||||
return moduleName().concat("1.10.1");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String moduleName() {
|
|
||||||
return "mhttp";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie;
|
|
||||||
|
|
||||||
import okhttp3.CookieJar;
|
|
||||||
|
|
||||||
public interface ClearableCookieJar extends CookieJar {
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
void clearForDomain(String domain);
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.cookie;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.cookie.cache.CookieCache;
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MemeryCookieJar.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/3/18.</p>
|
|
||||||
* <p>Time : 下午2:20.</p>
|
|
||||||
*/
|
|
||||||
public class MemoryCookieJar implements ClearableCookieJar {
|
|
||||||
|
|
||||||
private CookieCache cache;
|
|
||||||
|
|
||||||
public MemoryCookieJar(CookieCache cache) {
|
|
||||||
this.cache = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
synchronized public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
|
|
||||||
cache.addAll(cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
synchronized public List<Cookie> loadForRequest(HttpUrl url) {
|
|
||||||
List<Cookie> validCookies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
|
|
||||||
Cookie currentCookie = it.next();
|
|
||||||
|
|
||||||
if (isCookieExpired(currentCookie)) {
|
|
||||||
it.remove();
|
|
||||||
|
|
||||||
} else if (currentCookie.matches(url)) {
|
|
||||||
validCookies.add(currentCookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return validCookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isCookieExpired(Cookie cookie) {
|
|
||||||
return cookie.expiresAt() < System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized public void clear() {
|
|
||||||
cache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized public void clearForDomain(String domain) {
|
|
||||||
cache.clearForDomain(domain);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie;
|
|
||||||
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.cookie.cache.CookieCache;
|
|
||||||
import im.wangchao.mhttp.internal.cookie.persistence.CookiePersistor;
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
|
|
||||||
public class PersistentCookieJar implements ClearableCookieJar {
|
|
||||||
|
|
||||||
private CookieCache cache;
|
|
||||||
private CookiePersistor persistor;
|
|
||||||
|
|
||||||
public PersistentCookieJar(CookieCache cache, CookiePersistor persistor) {
|
|
||||||
this.cache = cache;
|
|
||||||
this.persistor = persistor;
|
|
||||||
|
|
||||||
this.cache.addAll(persistor.loadAll());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
synchronized public void saveFromResponse(@Nullable HttpUrl url, List<Cookie> cookies) {
|
|
||||||
// cookies need to be reversed, in order to replace old cookies with these coming later
|
|
||||||
// (if there are duplicate cookies in the same response)
|
|
||||||
List<Cookie> reverseCookies = new ArrayList<>(cookies);
|
|
||||||
Collections.reverse(reverseCookies);
|
|
||||||
cache.addAll(reverseCookies);
|
|
||||||
persistor.saveAll(reverseCookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@Override
|
|
||||||
synchronized public List<Cookie> loadForRequest(HttpUrl url) {
|
|
||||||
List<Cookie> removedCookies = new ArrayList<>();
|
|
||||||
List<Cookie> validCookies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
|
|
||||||
Cookie currentCookie = it.next();
|
|
||||||
if (isCookieExpired(currentCookie)) {
|
|
||||||
removedCookies.add(currentCookie);
|
|
||||||
it.remove();
|
|
||||||
|
|
||||||
} else if (currentCookie.matches(url)) {
|
|
||||||
validCookies.add(currentCookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
persistor.removeAll(removedCookies);
|
|
||||||
|
|
||||||
return validCookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
|
||||||
synchronized public List<Cookie> getForDomain(String domain) {
|
|
||||||
List<Cookie> removedCookies = new ArrayList<>();
|
|
||||||
List<Cookie> validCookies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
|
|
||||||
Cookie currentCookie = it.next();
|
|
||||||
if (isCookieExpired(currentCookie)) {
|
|
||||||
removedCookies.add(currentCookie);
|
|
||||||
it.remove();
|
|
||||||
|
|
||||||
} else if (domain.equals(currentCookie.domain())) {
|
|
||||||
validCookies.add(currentCookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
persistor.removeAll(removedCookies);
|
|
||||||
|
|
||||||
return validCookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
synchronized public String getCookie(String domain, String name) {
|
|
||||||
String cookieValue = null;
|
|
||||||
List<Cookie> removedCookies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Iterator<Cookie> it = cache.iterator(); it.hasNext(); ) {
|
|
||||||
Cookie currentCookie = it.next();
|
|
||||||
if (isCookieExpired(currentCookie)) {
|
|
||||||
removedCookies.add(currentCookie);
|
|
||||||
it.remove();
|
|
||||||
|
|
||||||
} else if (domain.equals(currentCookie.domain()) && name.equals(currentCookie.name())) {
|
|
||||||
cookieValue = currentCookie.value();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
persistor.removeAll(removedCookies);
|
|
||||||
|
|
||||||
return cookieValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isCookieExpired(Cookie cookie) {
|
|
||||||
return cookie.expiresAt() < System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized public void clear() {
|
|
||||||
cache.clear();
|
|
||||||
persistor.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized public void clearForDomain(String domain) {
|
|
||||||
cache.clearForDomain(domain);
|
|
||||||
persistor.clearForDomain(domain);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.cache;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
public interface CookieCache extends Iterable<Cookie> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all the new cookies to the session, existing cookies will be overwritten.
|
|
||||||
*
|
|
||||||
* @param cookies
|
|
||||||
*/
|
|
||||||
void addAll(Collection<Cookie> cookies);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all the cookies from the session.
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
void clearForDomain(String domain);
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.cache;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This class decorates a Cookie to re-implements equals() and hashcode() methods in order to identify
|
|
||||||
* the cookie by the following attributes: name, domain, path, secure & hostOnly.<p>
|
|
||||||
*
|
|
||||||
* This new behaviour will be useful in determining when an already existing cookie in session must be overwritten.
|
|
||||||
*/
|
|
||||||
class IdentifiableCookie {
|
|
||||||
|
|
||||||
private Cookie cookie;
|
|
||||||
|
|
||||||
static List<IdentifiableCookie> decorateAll(Collection<Cookie> cookies) {
|
|
||||||
List<IdentifiableCookie> identifiableCookies = new ArrayList<>(cookies.size());
|
|
||||||
for (Cookie cookie : cookies) {
|
|
||||||
identifiableCookies.add(new IdentifiableCookie(cookie));
|
|
||||||
}
|
|
||||||
return identifiableCookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
IdentifiableCookie(Cookie cookie) {
|
|
||||||
this.cookie = cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
Cookie getCookie() {
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object other) {
|
|
||||||
if (!(other instanceof IdentifiableCookie)) return false;
|
|
||||||
IdentifiableCookie that = (IdentifiableCookie) other;
|
|
||||||
return that.cookie.name().equals(this.cookie.name())
|
|
||||||
&& that.cookie.domain().equals(this.cookie.domain())
|
|
||||||
&& that.cookie.path().equals(this.cookie.path())
|
|
||||||
&& that.cookie.secure() == this.cookie.secure()
|
|
||||||
&& that.cookie.hostOnly() == this.cookie.hostOnly();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
int hash = 17;
|
|
||||||
if (cookie == null)
|
|
||||||
return hash;
|
|
||||||
hash = 31 * hash + cookie.name().hashCode();
|
|
||||||
hash = 31 * hash + cookie.domain().hashCode();
|
|
||||||
hash = 31 * hash + cookie.path().hashCode();
|
|
||||||
hash = 31 * hash + (cookie.secure() ? 0 : 1);
|
|
||||||
hash = 31 * hash + (cookie.hostOnly() ? 0 : 1);
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.cache;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
public class SetCookieCache implements CookieCache {
|
|
||||||
|
|
||||||
private Set<IdentifiableCookie> cookies;
|
|
||||||
|
|
||||||
public SetCookieCache() {
|
|
||||||
cookies = new HashSet<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addAll(Collection<Cookie> newCookies) {
|
|
||||||
updateCookies(IdentifiableCookie.decorateAll(newCookies));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All cookies will be added to the collection, already existing cookies will be overwritten by the new ones.
|
|
||||||
*
|
|
||||||
* @param cookies
|
|
||||||
*/
|
|
||||||
private void updateCookies(Collection<IdentifiableCookie> cookies) {
|
|
||||||
this.cookies.removeAll(cookies);
|
|
||||||
this.cookies.addAll(cookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
cookies.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearForDomain(String domain) {
|
|
||||||
Collection<IdentifiableCookie> removeCookies = new ArrayList<>();
|
|
||||||
for (IdentifiableCookie cookie: cookies) {
|
|
||||||
if (cookie.getCookie().domain().equals(domain)) {
|
|
||||||
removeCookies.add(cookie);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cookies.removeAll(removeCookies);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<Cookie> iterator() {
|
|
||||||
return new SetCookieCacheIterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SetCookieCacheIterator implements Iterator<Cookie> {
|
|
||||||
|
|
||||||
private Iterator<IdentifiableCookie> iterator;
|
|
||||||
|
|
||||||
public SetCookieCacheIterator() {
|
|
||||||
iterator = cookies.iterator();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return iterator.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Cookie next() {
|
|
||||||
return iterator.next().getCookie();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.persistence;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
public interface CookiePersistor {
|
|
||||||
|
|
||||||
List<Cookie> loadAll();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Persist all cookies, existing cookies will be overwritten.
|
|
||||||
*
|
|
||||||
* @param cookies cookies persist
|
|
||||||
*/
|
|
||||||
void saveAll(Collection<Cookie> cookies);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes indicated cookies from persistence.
|
|
||||||
*
|
|
||||||
* @param cookies cookies to remove from persistence
|
|
||||||
*/
|
|
||||||
void removeAll(Collection<Cookie> cookies);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all cookies from persistence.
|
|
||||||
*/
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all cookies from persistence for specified url.
|
|
||||||
*
|
|
||||||
* @param domain domain name
|
|
||||||
*/
|
|
||||||
void clearForDomain(String domain);
|
|
||||||
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.persistence;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.ObjectInputStream;
|
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
import java.io.Serializable;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
public class SerializableCookie implements Serializable {
|
|
||||||
private static final String TAG = SerializableCookie.class
|
|
||||||
.getSimpleName();
|
|
||||||
|
|
||||||
private transient Cookie cookie;
|
|
||||||
|
|
||||||
public String encode(Cookie cookie) {
|
|
||||||
this.cookie = cookie;
|
|
||||||
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
||||||
try {
|
|
||||||
ObjectOutputStream outputStream = new ObjectOutputStream(os);
|
|
||||||
outputStream.writeObject(this);
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "IOException in encodeCookie", e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return byteArrayToHexString(os.toByteArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Using some super basic byte array <-> hex conversions so we don't
|
|
||||||
* have to rely on any large Base64 libraries. Can be overridden if you
|
|
||||||
* like!
|
|
||||||
*
|
|
||||||
* @param bytes byte array to be converted
|
|
||||||
* @return string containing hex values
|
|
||||||
*/
|
|
||||||
private static String byteArrayToHexString(byte[] bytes) {
|
|
||||||
StringBuilder sb = new StringBuilder(bytes.length * 2);
|
|
||||||
for (byte element : bytes) {
|
|
||||||
int v = element & 0xff;
|
|
||||||
if (v < 16) {
|
|
||||||
sb.append('0');
|
|
||||||
}
|
|
||||||
sb.append(Integer.toHexString(v));
|
|
||||||
}
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Cookie decode(String encodedCookie) {
|
|
||||||
byte[] bytes = hexStringToByteArray(encodedCookie);
|
|
||||||
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(
|
|
||||||
bytes);
|
|
||||||
Cookie cookie = null;
|
|
||||||
try {
|
|
||||||
ObjectInputStream objectInputStream = new ObjectInputStream(
|
|
||||||
byteArrayInputStream);
|
|
||||||
cookie = ((SerializableCookie) objectInputStream.readObject()).cookie;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.d(TAG, "IOException in decodeCookie", e);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
Log.d(TAG, "ClassNotFoundException in decodeCookie", e);
|
|
||||||
}
|
|
||||||
return cookie;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts hex values from strings to byte array
|
|
||||||
*
|
|
||||||
* @param hexString string of hex-encoded values
|
|
||||||
* @return decoded byte array
|
|
||||||
*/
|
|
||||||
private static byte[] hexStringToByteArray(String hexString) {
|
|
||||||
int len = hexString.length();
|
|
||||||
byte[] data = new byte[len / 2];
|
|
||||||
for (int i = 0; i < len; i += 2) {
|
|
||||||
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
|
|
||||||
.digit(hexString.charAt(i + 1), 16));
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static long NON_VALID_EXPIRES_AT = -1l;
|
|
||||||
|
|
||||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
|
||||||
out.writeObject(cookie.name());
|
|
||||||
out.writeObject(cookie.value());
|
|
||||||
out.writeLong(cookie.persistent() ? cookie.expiresAt() : NON_VALID_EXPIRES_AT);
|
|
||||||
out.writeObject(cookie.domain());
|
|
||||||
out.writeObject(cookie.path());
|
|
||||||
out.writeBoolean(cookie.secure());
|
|
||||||
out.writeBoolean(cookie.httpOnly());
|
|
||||||
out.writeBoolean(cookie.hostOnly());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
|
|
||||||
Cookie.Builder builder = new Cookie.Builder();
|
|
||||||
|
|
||||||
builder.name((String) in.readObject());
|
|
||||||
|
|
||||||
builder.value((String) in.readObject());
|
|
||||||
|
|
||||||
long expiresAt = in.readLong();
|
|
||||||
if (expiresAt != NON_VALID_EXPIRES_AT) {
|
|
||||||
builder.expiresAt(expiresAt);
|
|
||||||
}
|
|
||||||
|
|
||||||
final String domain = (String) in.readObject();
|
|
||||||
builder.domain(domain);
|
|
||||||
|
|
||||||
builder.path((String) in.readObject());
|
|
||||||
|
|
||||||
if (in.readBoolean())
|
|
||||||
builder.secure();
|
|
||||||
|
|
||||||
if (in.readBoolean())
|
|
||||||
builder.httpOnly();
|
|
||||||
|
|
||||||
if (in.readBoolean())
|
|
||||||
builder.hostOnlyDomain(domain);
|
|
||||||
|
|
||||||
cookie = builder.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2016 Francisco José Montiel Navarro.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package im.wangchao.mhttp.internal.cookie.persistence;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import okhttp3.Cookie;
|
|
||||||
|
|
||||||
public class SharedPrefsCookiePersistor implements CookiePersistor {
|
|
||||||
|
|
||||||
private SharedPreferences sharedPreferences;
|
|
||||||
|
|
||||||
public SharedPrefsCookiePersistor(Context context) {
|
|
||||||
final String SHARED_PREFERENCES_NAME = "cookies";
|
|
||||||
|
|
||||||
sharedPreferences =
|
|
||||||
context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Cookie> loadAll() {
|
|
||||||
List<Cookie> cookies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Map.Entry<String, ?> entry : sharedPreferences.getAll().entrySet()) {
|
|
||||||
String serializedCookie = (String) entry.getValue();
|
|
||||||
Cookie cookie = new SerializableCookie().decode(serializedCookie);
|
|
||||||
cookies.add(cookie);
|
|
||||||
}
|
|
||||||
return cookies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void saveAll(Collection<Cookie> cookies) {
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
|
||||||
for (Cookie cookie : cookies) {
|
|
||||||
if (cookie.persistent()) {
|
|
||||||
editor.putString(createCookieKey(cookie), new SerializableCookie().encode(cookie));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void removeAll(Collection<Cookie> cookies) {
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
|
||||||
for (Cookie cookie : cookies) {
|
|
||||||
editor.remove(createCookieKey(cookie));
|
|
||||||
}
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static String createCookieKey(Cookie cookie) {
|
|
||||||
return (cookie.secure() ? "https" : "http") + "://" + cookie.domain() + cookie.path() + "|" + cookie.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
sharedPreferences.edit().clear().apply();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clearForDomain(String domain) {
|
|
||||||
List<Cookie> cookies = loadAll();
|
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
|
||||||
for (Cookie cookie : cookies) {
|
|
||||||
if (cookie.domain().equals(domain))
|
|
||||||
editor.remove(createCookieKey(cookie));
|
|
||||||
}
|
|
||||||
editor.apply();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ParserException.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/4/26.</p>
|
|
||||||
* <p>Time : 下午8:38.</p>
|
|
||||||
*/
|
|
||||||
public class ParserException extends Exception{
|
|
||||||
public ParserException(){
|
|
||||||
super("Response parse exception.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public ParserException(Throwable cause) {
|
|
||||||
super("Response parse exception.", cause);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ResponseFailException.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/4/25.</p>
|
|
||||||
* <p>Time : 下午4:06.</p>
|
|
||||||
*/
|
|
||||||
public class ResponseFailException extends Exception{
|
|
||||||
//Response Non Successful
|
|
||||||
public ResponseFailException(){
|
|
||||||
super("Response failure exception.");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,320 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.interceptor;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2015 Square, Inc.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import java.io.EOFException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import okhttp3.Connection;
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.Response;
|
|
||||||
import okhttp3.ResponseBody;
|
|
||||||
import okhttp3.internal.http.HttpHeaders;
|
|
||||||
import okhttp3.internal.platform.Platform;
|
|
||||||
import okio.Buffer;
|
|
||||||
import okio.BufferedSource;
|
|
||||||
import okio.GzipSource;
|
|
||||||
|
|
||||||
import static okhttp3.internal.platform.Platform.INFO;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An OkHttp interceptor which logs request and response information. Can be applied as an
|
|
||||||
* {@linkplain OkHttpClient#interceptors() application interceptor} or as a {@linkplain
|
|
||||||
* OkHttpClient#networkInterceptors() network interceptor}. <p> The format of the logs created by
|
|
||||||
* this class should not be considered stable and may change slightly between releases. If you need
|
|
||||||
* a stable logging format, use your own interceptor.
|
|
||||||
*/
|
|
||||||
public final class HttpLoggingInterceptor implements Interceptor {
|
|
||||||
private static final Charset UTF8 = Charset.forName("UTF-8");
|
|
||||||
|
|
||||||
public enum Level {
|
|
||||||
/** No logs. */
|
|
||||||
NONE,
|
|
||||||
/**
|
|
||||||
* Logs request and response lines.
|
|
||||||
*
|
|
||||||
* <p>Example:
|
|
||||||
* <pre>{@code
|
|
||||||
* --> POST /greeting http/1.1 (3-byte body)
|
|
||||||
*
|
|
||||||
* <-- 200 OK (22ms, 6-byte body)
|
|
||||||
* }</pre>
|
|
||||||
*/
|
|
||||||
BASIC,
|
|
||||||
/**
|
|
||||||
* Logs request and response lines and their respective headers.
|
|
||||||
*
|
|
||||||
* <p>Example:
|
|
||||||
* <pre>{@code
|
|
||||||
* --> POST /greeting http/1.1
|
|
||||||
* Host: example.com
|
|
||||||
* Content-Type: plain/text
|
|
||||||
* Content-Length: 3
|
|
||||||
* --> END POST
|
|
||||||
*
|
|
||||||
* <-- 200 OK (22ms)
|
|
||||||
* Content-Type: plain/text
|
|
||||||
* Content-Length: 6
|
|
||||||
* <-- END HTTP
|
|
||||||
* }</pre>
|
|
||||||
*/
|
|
||||||
HEADERS,
|
|
||||||
/**
|
|
||||||
* Logs request and response lines and their respective headers and bodies (if present).
|
|
||||||
*
|
|
||||||
* <p>Example:
|
|
||||||
* <pre>{@code
|
|
||||||
* --> POST /greeting http/1.1
|
|
||||||
* Host: example.com
|
|
||||||
* Content-Type: plain/text
|
|
||||||
* Content-Length: 3
|
|
||||||
*
|
|
||||||
* Hi?
|
|
||||||
* --> END POST
|
|
||||||
*
|
|
||||||
* <-- 200 OK (22ms)
|
|
||||||
* Content-Type: plain/text
|
|
||||||
* Content-Length: 6
|
|
||||||
*
|
|
||||||
* Hello!
|
|
||||||
* <-- END HTTP
|
|
||||||
* }</pre>
|
|
||||||
*/
|
|
||||||
BODY
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Logger {
|
|
||||||
void log(String message);
|
|
||||||
|
|
||||||
/** A {@link Logger} defaults output appropriate for the current platform. */
|
|
||||||
Logger DEFAULT = new Logger() {
|
|
||||||
@Override public void log(String message) {
|
|
||||||
Platform.get().log(INFO, message, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpLoggingInterceptor() {
|
|
||||||
this(Logger.DEFAULT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public HttpLoggingInterceptor(Logger logger) {
|
|
||||||
this.logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Logger logger;
|
|
||||||
|
|
||||||
private volatile Level level = Level.NONE;
|
|
||||||
|
|
||||||
/** Change the level at which this interceptor logs. */
|
|
||||||
public HttpLoggingInterceptor setLevel(Level level) {
|
|
||||||
if (level == null) throw new NullPointerException("level == null. Use Level.NONE instead.");
|
|
||||||
this.level = level;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Level getLevel() {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public Response intercept(Chain chain) throws IOException {
|
|
||||||
Level level = this.level;
|
|
||||||
|
|
||||||
Request request = chain.request();
|
|
||||||
if (level == Level.NONE) {
|
|
||||||
return chain.proceed(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean logBody = level == Level.BODY;
|
|
||||||
boolean logHeaders = logBody || level == Level.HEADERS;
|
|
||||||
|
|
||||||
RequestBody requestBody = request.body();
|
|
||||||
boolean hasRequestBody = requestBody != null;
|
|
||||||
|
|
||||||
Connection connection = chain.connection();
|
|
||||||
String requestStartMessage = "--> "
|
|
||||||
+ request.method()
|
|
||||||
+ ' ' + request.url()
|
|
||||||
+ (connection != null ? " " + connection.protocol() : "");
|
|
||||||
if (!logHeaders && hasRequestBody) {
|
|
||||||
requestStartMessage += " (" + requestBody.contentLength() + "-byte body)";
|
|
||||||
}
|
|
||||||
logger.log(requestStartMessage);
|
|
||||||
|
|
||||||
if (logHeaders) {
|
|
||||||
if (hasRequestBody) {
|
|
||||||
// Request body headers are only present when installed as a network interceptor. Force
|
|
||||||
// them to be included (when available) so there values are known.
|
|
||||||
if (requestBody.contentType() != null) {
|
|
||||||
logger.log("Content-Type: " + requestBody.contentType());
|
|
||||||
}
|
|
||||||
if (requestBody.contentLength() != -1) {
|
|
||||||
logger.log("Content-Length: " + requestBody.contentLength());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Headers headers = request.headers();
|
|
||||||
for (int i = 0, count = headers.size(); i < count; i++) {
|
|
||||||
String name = headers.name(i);
|
|
||||||
// Skip headers from the request body as they are explicitly logged above.
|
|
||||||
if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
|
|
||||||
logger.log(name + ": " + headers.value(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!logBody || !hasRequestBody) {
|
|
||||||
logger.log("--> END " + request.method());
|
|
||||||
} else if (bodyHasUnknownEncoding(request.headers())) {
|
|
||||||
logger.log("--> END " + request.method() + " (encoded body omitted)");
|
|
||||||
} else {
|
|
||||||
Buffer buffer = new Buffer();
|
|
||||||
requestBody.writeTo(buffer);
|
|
||||||
|
|
||||||
Charset charset = UTF8;
|
|
||||||
MediaType contentType = requestBody.contentType();
|
|
||||||
if (contentType != null) {
|
|
||||||
charset = contentType.charset(UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
logger.log("");
|
|
||||||
if (isPlaintext(buffer)) {
|
|
||||||
logger.log(buffer.readString(charset));
|
|
||||||
logger.log("--> END " + request.method()
|
|
||||||
+ " (" + requestBody.contentLength() + "-byte body)");
|
|
||||||
} else {
|
|
||||||
logger.log("--> END " + request.method() + " (binary "
|
|
||||||
+ requestBody.contentLength() + "-byte body omitted)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long startNs = System.nanoTime();
|
|
||||||
Response response;
|
|
||||||
try {
|
|
||||||
response = chain.proceed(request);
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.log("<-- HTTP FAILED: " + e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
|
|
||||||
|
|
||||||
ResponseBody responseBody = response.body();
|
|
||||||
long contentLength = responseBody.contentLength();
|
|
||||||
String bodySize = contentLength != -1 ? contentLength + "-byte" : "unknown-length";
|
|
||||||
logger.log("<-- "
|
|
||||||
+ response.code()
|
|
||||||
+ (response.message().isEmpty() ? "" : ' ' + response.message())
|
|
||||||
+ ' ' + response.request().url()
|
|
||||||
+ " (" + tookMs + "ms" + (!logHeaders ? ", " + bodySize + " body" : "") + ')');
|
|
||||||
|
|
||||||
if (logHeaders) {
|
|
||||||
Headers headers = response.headers();
|
|
||||||
for (int i = 0, count = headers.size(); i < count; i++) {
|
|
||||||
logger.log(headers.name(i) + ": " + headers.value(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!logBody || !HttpHeaders.hasBody(response)) {
|
|
||||||
logger.log("<-- END HTTP");
|
|
||||||
} else if (bodyHasUnknownEncoding(response.headers())) {
|
|
||||||
logger.log("<-- END HTTP (encoded body omitted)");
|
|
||||||
} else {
|
|
||||||
BufferedSource source = responseBody.source();
|
|
||||||
source.request(Long.MAX_VALUE); // Buffer the entire body.
|
|
||||||
Buffer buffer = source.buffer();
|
|
||||||
|
|
||||||
Long gzippedLength = null;
|
|
||||||
if ("gzip".equalsIgnoreCase(headers.get("Content-Encoding"))) {
|
|
||||||
gzippedLength = buffer.size();
|
|
||||||
GzipSource gzippedResponseBody = null;
|
|
||||||
try {
|
|
||||||
gzippedResponseBody = new GzipSource(buffer.clone());
|
|
||||||
buffer = new Buffer();
|
|
||||||
buffer.writeAll(gzippedResponseBody);
|
|
||||||
} finally {
|
|
||||||
if (gzippedResponseBody != null) {
|
|
||||||
gzippedResponseBody.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Charset charset = UTF8;
|
|
||||||
MediaType contentType = responseBody.contentType();
|
|
||||||
if (contentType != null) {
|
|
||||||
charset = contentType.charset(UTF8);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isPlaintext(buffer)) {
|
|
||||||
logger.log("");
|
|
||||||
logger.log("<-- END HTTP (binary " + buffer.size() + "-byte body omitted)");
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentLength != 0) {
|
|
||||||
logger.log("");
|
|
||||||
logger.log(buffer.clone().readString(charset));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gzippedLength != null) {
|
|
||||||
logger.log("<-- END HTTP (" + buffer.size() + "-byte, "
|
|
||||||
+ gzippedLength + "-gzipped-byte body)");
|
|
||||||
} else {
|
|
||||||
logger.log("<-- END HTTP (" + buffer.size() + "-byte body)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the body in question probably contains human readable text. Uses a small sample
|
|
||||||
* of code points to detect unicode control characters commonly used in binary file signatures.
|
|
||||||
*/
|
|
||||||
static boolean isPlaintext(Buffer buffer) {
|
|
||||||
try {
|
|
||||||
Buffer prefix = new Buffer();
|
|
||||||
long byteCount = buffer.size() < 64 ? buffer.size() : 64;
|
|
||||||
buffer.copyTo(prefix, 0, byteCount);
|
|
||||||
for (int i = 0; i < 16; i++) {
|
|
||||||
if (prefix.exhausted()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int codePoint = prefix.readUtf8CodePoint();
|
|
||||||
if (Character.isISOControl(codePoint) && !Character.isWhitespace(codePoint)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch (EOFException e) {
|
|
||||||
return false; // Truncated UTF-8 sequence.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean bodyHasUnknownEncoding(Headers headers) {
|
|
||||||
String contentEncoding = headers.get("Content-Encoding");
|
|
||||||
return contentEncoding != null
|
|
||||||
&& !contentEncoding.equalsIgnoreCase("identity")
|
|
||||||
&& !contentEncoding.equalsIgnoreCase("gzip");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,36 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.interceptor;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.Singleton;
|
|
||||||
import im.wangchao.mhttp.internal.Version;
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : MBridgeInterceptors.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 16/8/24.</p>
|
|
||||||
* <p>Time : 下午4:32.</p>
|
|
||||||
*/
|
|
||||||
public final class MBridgeInterceptor implements Interceptor {
|
|
||||||
private MBridgeInterceptor(){}
|
|
||||||
|
|
||||||
public static Singleton<MBridgeInterceptor> instance = new Singleton<MBridgeInterceptor>() {
|
|
||||||
@Override protected MBridgeInterceptor create() {
|
|
||||||
return new MBridgeInterceptor();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override public Response intercept(Chain chain) throws IOException {
|
|
||||||
Request request = chain.request();
|
|
||||||
Request.Builder builder = request.newBuilder();
|
|
||||||
|
|
||||||
if (request.header("User-Agent") == null) {
|
|
||||||
builder.header("User-Agent", Version.userAgent());
|
|
||||||
}
|
|
||||||
|
|
||||||
return chain.proceed(builder.build());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
package im.wangchao.mhttp.internal.log;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.internal.Singleton;
|
|
||||||
import im.wangchao.mhttp.internal.Version;
|
|
||||||
import im.wangchao.mhttp.internal.interceptor.HttpLoggingInterceptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : Logger.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/20.</p>
|
|
||||||
* <p>Time : 下午5:36.</p>
|
|
||||||
*/
|
|
||||||
public class LoggerImpl implements HttpLoggingInterceptor.Logger{
|
|
||||||
private static final String TAG = Version.moduleName();
|
|
||||||
private HttpLoggingInterceptor.Level mLevel;
|
|
||||||
|
|
||||||
public static Singleton<LoggerImpl> instance = new Singleton<LoggerImpl>() {
|
|
||||||
@Override protected LoggerImpl create() {
|
|
||||||
return new LoggerImpl();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public void setLevel(HttpLoggingInterceptor.Level level){
|
|
||||||
mLevel = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void log(String message) {
|
|
||||||
if (mLevel == HttpLoggingInterceptor.Level.NONE){
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Log.e(TAG, message);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,133 +0,0 @@
|
|||||||
package im.wangchao.mhttp.rxjava2;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Request;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.Observer;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.exceptions.CompositeException;
|
|
||||||
import io.reactivex.exceptions.Exceptions;
|
|
||||||
import io.reactivex.plugins.RxJavaPlugins;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ResponseEnqueueObservable.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/19.</p>
|
|
||||||
* <p>Time : 下午4:45.</p>
|
|
||||||
*/
|
|
||||||
public class ResponseEnqueueObservable<T> extends Observable<T> {
|
|
||||||
private final RxRequest<T> request;
|
|
||||||
|
|
||||||
public ResponseEnqueueObservable(RxRequest<T> request){
|
|
||||||
this.request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void subscribeActual(Observer<? super T> observer) {
|
|
||||||
|
|
||||||
AbsCallbackHandler<T> callback = request.callback();
|
|
||||||
EnqueueDisposable<T> disposable = new EnqueueDisposable<>(observer, callback);
|
|
||||||
|
|
||||||
observer.onSubscribe(disposable);
|
|
||||||
request.request().newBuilder().callback(disposable).build().enqueue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class EnqueueDisposable<T> extends AbsCallbackHandler<T> implements Disposable{
|
|
||||||
private final AbsCallbackHandler<T> originCallback;
|
|
||||||
private final Observer<? super T> observer;
|
|
||||||
private volatile boolean disposed;
|
|
||||||
boolean terminated = false;
|
|
||||||
|
|
||||||
EnqueueDisposable(Observer<? super T> observer, AbsCallbackHandler<T> callbackHandler){
|
|
||||||
this.observer = observer;
|
|
||||||
this.originCallback = callbackHandler;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void dispose() {
|
|
||||||
disposed = true;
|
|
||||||
Request request = getRequest();
|
|
||||||
request.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean isDisposed() {
|
|
||||||
return disposed;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override public String charset() {
|
|
||||||
return originCallback.charset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public String accept() {
|
|
||||||
return originCallback.accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onStart() {
|
|
||||||
originCallback.onStart();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onUploadProgress(int bytesWritten, int bytesTotal) {
|
|
||||||
originCallback.onUploadProgress(bytesWritten, bytesTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onProgress(long bytesWritten, long bytesTotal) {
|
|
||||||
originCallback.onProgress(bytesWritten, bytesTotal);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFinish() {
|
|
||||||
originCallback.onFinish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onCancel() {
|
|
||||||
originCallback.onCancel();
|
|
||||||
if (!disposed){
|
|
||||||
dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public T apply(Response response) throws Exception {
|
|
||||||
return originCallback.apply(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onSuccess(T data, Response response) {
|
|
||||||
if (disposed) return;
|
|
||||||
|
|
||||||
try {
|
|
||||||
originCallback.onSuccess(data, response);
|
|
||||||
|
|
||||||
observer.onNext(data);
|
|
||||||
|
|
||||||
if (!disposed) {
|
|
||||||
terminated = true;
|
|
||||||
observer.onComplete();
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
if (terminated) {
|
|
||||||
RxJavaPlugins.onError(t);
|
|
||||||
} else if (!disposed) {
|
|
||||||
try {
|
|
||||||
observer.onError(t);
|
|
||||||
} catch (Throwable inner) {
|
|
||||||
Exceptions.throwIfFatal(inner);
|
|
||||||
RxJavaPlugins.onError(new CompositeException(t, inner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
try {
|
|
||||||
originCallback.onFailure(response, throwable);
|
|
||||||
|
|
||||||
observer.onError(throwable);
|
|
||||||
} catch (Throwable inner) {
|
|
||||||
Exceptions.throwIfFatal(inner);
|
|
||||||
RxJavaPlugins.onError(new CompositeException(throwable, inner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFinally(Response response) {
|
|
||||||
originCallback.onFinally(response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
package im.wangchao.mhttp.rxjava2;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.Converter;
|
|
||||||
import im.wangchao.mhttp.Request;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.Observer;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.exceptions.CompositeException;
|
|
||||||
import io.reactivex.exceptions.Exceptions;
|
|
||||||
import io.reactivex.plugins.RxJavaPlugins;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : ResponseExecuteObservable.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/19.</p>
|
|
||||||
* <p>Time : 下午4:46.</p>
|
|
||||||
*/
|
|
||||||
public class ResponseExecuteObservable<T> extends Observable<T> {
|
|
||||||
private final RxRequest<T> request;
|
|
||||||
private final Converter<Response, T> converter;
|
|
||||||
|
|
||||||
public ResponseExecuteObservable(RxRequest<T> request, Converter<Response, T> converter){
|
|
||||||
this.request = request;
|
|
||||||
this.converter = converter;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected void subscribeActual(Observer<? super T> observer) {
|
|
||||||
|
|
||||||
ExecuteDisposable disposable = new ExecuteDisposable(request.request());
|
|
||||||
observer.onSubscribe(disposable);
|
|
||||||
|
|
||||||
boolean terminated = false;
|
|
||||||
try {
|
|
||||||
T response = converter.apply(request.request().execute());
|
|
||||||
if (!disposable.isDisposed()) {
|
|
||||||
observer.onNext(response);
|
|
||||||
}
|
|
||||||
if (!disposable.isDisposed()) {
|
|
||||||
terminated = true;
|
|
||||||
observer.onComplete();
|
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
Exceptions.throwIfFatal(t);
|
|
||||||
if (terminated) {
|
|
||||||
RxJavaPlugins.onError(t);
|
|
||||||
} else if (!disposable.isDisposed()) {
|
|
||||||
try {
|
|
||||||
observer.onError(t);
|
|
||||||
} catch (Throwable inner) {
|
|
||||||
Exceptions.throwIfFatal(inner);
|
|
||||||
RxJavaPlugins.onError(new CompositeException(t, inner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class ExecuteDisposable implements Disposable {
|
|
||||||
private final Request request;
|
|
||||||
private volatile boolean disposed;
|
|
||||||
|
|
||||||
ExecuteDisposable(Request request) {
|
|
||||||
this.request = request;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void dispose() {
|
|
||||||
disposed = true;
|
|
||||||
request.cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean isDisposed() {
|
|
||||||
return disposed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,233 +0,0 @@
|
|||||||
package im.wangchao.mhttp.rxjava2;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
import im.wangchao.mhttp.AbsCallbackHandler;
|
|
||||||
import im.wangchao.mhttp.Converter;
|
|
||||||
import im.wangchao.mhttp.Method;
|
|
||||||
import im.wangchao.mhttp.Request;
|
|
||||||
import im.wangchao.mhttp.RequestParams;
|
|
||||||
import im.wangchao.mhttp.Response;
|
|
||||||
import im.wangchao.mhttp.ThreadMode;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import okhttp3.CacheControl;
|
|
||||||
import okhttp3.Headers;
|
|
||||||
import okhttp3.HttpUrl;
|
|
||||||
import okhttp3.MediaType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Description : RxRequest.</p>
|
|
||||||
* <p>Author : wangchao.</p>
|
|
||||||
* <p>Date : 2018/3/26.</p>
|
|
||||||
* <p>Time : 下午5:40.</p>
|
|
||||||
*/
|
|
||||||
public class RxRequest<T> {
|
|
||||||
public static <T> RxRequest.Builder<T> builder(){
|
|
||||||
return new RxRequest.Builder<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Request request;
|
|
||||||
private AbsCallbackHandler<T> callback;
|
|
||||||
|
|
||||||
private RxRequest(Builder<T> builder){
|
|
||||||
request = builder.request;
|
|
||||||
callback = builder.callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Request request(){
|
|
||||||
return request;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbsCallbackHandler<T> callback(){
|
|
||||||
return callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RxRequest.Builder<T> newBuilder() {
|
|
||||||
return new Builder<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<T> execute(Converter<Response, T> converter){
|
|
||||||
return new ResponseExecuteObservable<>(this, converter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<T> enqueue(){
|
|
||||||
return new ResponseEnqueueObservable<>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class Builder<T> {
|
|
||||||
|
|
||||||
Request request;
|
|
||||||
Request.Builder requestBuilder;
|
|
||||||
AbsCallbackHandler<T> callback;
|
|
||||||
|
|
||||||
public Builder() {
|
|
||||||
requestBuilder = new Request.Builder();
|
|
||||||
callback = new AbsCallbackHandler<T>() {
|
|
||||||
@Override public void onSuccess(T data, Response response) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void onFailure(Response response, Throwable throwable) {
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private Builder(RxRequest<T> request) {
|
|
||||||
requestBuilder = request.request.newBuilder();
|
|
||||||
callback = request.callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> url(HttpUrl url) {
|
|
||||||
requestBuilder.url(url);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> url(String url) {
|
|
||||||
requestBuilder.url(url);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> url(URL url) {
|
|
||||||
requestBuilder.url(url);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> header(String name, String value) {
|
|
||||||
requestBuilder.header(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> addHeader(String name, String value) {
|
|
||||||
requestBuilder.header(name, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> removeHeader(String name) {
|
|
||||||
requestBuilder.removeHeader(name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> headers(Headers headers) {
|
|
||||||
requestBuilder.headers(headers);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> cacheControl(CacheControl cacheControl) {
|
|
||||||
requestBuilder.cacheControl(cacheControl);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> get() {
|
|
||||||
return method(Method.GET);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> head() {
|
|
||||||
return method(Method.HEAD);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> post() {
|
|
||||||
return method(Method.POST);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> delete() {
|
|
||||||
return method(Method.DELETE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> put() {
|
|
||||||
return method(Method.PUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> patch() {
|
|
||||||
return method(Method.PATCH);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder<T> addParameter(String key, Object value){
|
|
||||||
requestBuilder.addParameter(key, value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder<T> addParameter(String key, InputStream stream, String name){
|
|
||||||
requestBuilder.addParameter(key, stream, name);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder<T> addParameter(String key, InputStream stream, String name, String contentType){
|
|
||||||
requestBuilder.addParameter(key, stream, name, contentType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple to add request parameter
|
|
||||||
*/
|
|
||||||
public Builder<T> addParameter(String key, File file, String contentType) {
|
|
||||||
requestBuilder.addParameter(key, file, contentType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> requestParams(RequestParams params) {
|
|
||||||
requestBuilder.requestParams(params);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> method(@NonNull String method) {
|
|
||||||
requestBuilder.method(method);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> tag(Object tag) {
|
|
||||||
requestBuilder.tag(tag);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> callback(@NonNull AbsCallbackHandler<T> callback){
|
|
||||||
this.callback = callback;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> callbackExecutor(Executor executor){
|
|
||||||
requestBuilder.callbackExecutor(executor);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> callbackThreadMode(ThreadMode threadMode){
|
|
||||||
requestBuilder.callbackThreadMode(threadMode);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> userAgent(String ua){
|
|
||||||
requestBuilder.userAgent(ua);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> contentType(@NonNull String contentType){
|
|
||||||
requestBuilder.contentType(contentType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder<T> contentType(@NonNull MediaType mediaType){
|
|
||||||
requestBuilder.contentType(mediaType);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RxRequest<T> build() {
|
|
||||||
request = requestBuilder.build();
|
|
||||||
|
|
||||||
return new RxRequest<>(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ include ':wear'
|
|||||||
include ':codegen'
|
include ':codegen'
|
||||||
include ':annotation'
|
include ':annotation'
|
||||||
rootProject.name='Szkolny.eu'
|
rootProject.name='Szkolny.eu'
|
||||||
include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font'
|
include ':app', ':agendacalendarview', ':szkolny-font'
|
||||||
/*
|
/*
|
||||||
include ':Navigation'
|
include ':Navigation'
|
||||||
project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/
|
project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user