mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-31 05:48:19 +01:00
[Gradle] Extract mhttp dependency.
This commit is contained in:
parent
15f9db5ca6
commit
0615593d94
@ -170,7 +170,7 @@ dependencies {
|
||||
implementation project(":agendacalendarview")
|
||||
implementation "eu.szkolny:cafebar:5bf0c618de"
|
||||
implementation "eu.szkolny:material-about-library:0534abf316"
|
||||
implementation project(":mhttp")
|
||||
implementation "eu.szkolny:mhttp:af4b62e6e9"
|
||||
implementation "eu.szkolny:nachos:0e5dfcaceb"
|
||||
//implementation project(":Navigation")
|
||||
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 ':annotation'
|
||||
rootProject.name='Szkolny.eu'
|
||||
include ':app', ':agendacalendarview', ':mhttp', ':szkolny-font'
|
||||
include ':app', ':agendacalendarview', ':szkolny-font'
|
||||
/*
|
||||
include ':Navigation'
|
||||
project(':Navigation').projectDir = new File(settingsDir, '../Navigation/navlib')*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user