Created
June 13, 2019 11:24
-
-
Save hfutxqd/7b786c64bb2f53aeca244d5f126acdff to your computer and use it in GitHub Desktop.
simple http injector sample for netbare
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.android.netbare | |
import android.text.TextUtils | |
import android.util.Log | |
import com.github.megatronking.netbare.http.HttpBody | |
import com.github.megatronking.netbare.http.HttpRequest | |
import com.github.megatronking.netbare.http.HttpResponse | |
import com.github.megatronking.netbare.injector.InjectorCallback | |
import com.github.megatronking.netbare.injector.SimpleHttpInjector | |
import java.io.ByteArrayInputStream | |
import java.io.ByteArrayOutputStream | |
import java.io.InputStream | |
import java.util.zip.GZIPInputStream | |
import java.util.zip.InflaterInputStream | |
class MyHttpInjector: SimpleHttpInjector() { | |
companion object { | |
const val TAG = "MyHttpInjector" | |
} | |
override fun sniffRequest(request: HttpRequest): Boolean { | |
var httpData = httpCache[request.id()] | |
if (httpData == null) { | |
httpData = HttpData(request.uid(), request.id()) | |
httpData.setRequest(request) | |
} | |
httpCache[request.id()] = httpData | |
return true | |
} | |
override fun sniffResponse(response: HttpResponse): Boolean { | |
var httpData = httpCache[response.id()] | |
if (httpData == null) { | |
httpData = HttpData(response.uid(), response.id()) | |
httpData.seResponse(response) | |
httpCache[response.id()] = httpData | |
} else { | |
httpData.seResponse(response) | |
} | |
return true | |
} | |
override fun onRequestInject(request: HttpRequest, body: HttpBody, callback: InjectorCallback) { | |
val httpData = httpCache[request.id()] | |
if (httpData != null) { | |
httpData.writeRequestBody(body.toBuffer().array()) | |
} | |
callback.onFinished(body) | |
} | |
override fun onResponseInject(response: HttpResponse, body: HttpBody, callback: InjectorCallback) { | |
val httpData = httpCache[response.id()] | |
if (httpData != null) { | |
httpData.writeResponseBody(body.toBuffer().array()) | |
} | |
callback.onFinished(body) | |
} | |
override fun onRequestFinished(request: HttpRequest) { | |
Log.i(MyHttpInjector.TAG, "onRequestFinished " + request.id()) | |
val uid = request.uid() | |
val pkg = App.getInstance().getUidMapping()[uid] | |
Log.i(MyHttpInjector.TAG + " " + request.id() + " >>", request.httpProtocol().name + " " + request.method().name + " " + request.url() + " pkg: " + pkg + " uid:" + uid) | |
Log.i(MyHttpInjector.TAG + " " + request.id() + " >>", request.requestHeaders().toString()) | |
val httpData = httpCache[request.id()] | |
if (httpData != null) { | |
val response = httpData.getResponse() | |
if (response != null) { | |
Log.i(MyHttpInjector.TAG + " " + response.id() + " <<", response.url() + " " + response.code() + " " + response.message()) | |
val headers = response.responseHeaders() | |
val contentEncoding = headers["Content-Encoding"]?.get(0) | |
val transferEncoding = headers["Transfer-Encoding"]?.get(0) | |
Log.i(MyHttpInjector.TAG + " " + response.id() + " <<", headers.toString()) | |
var bodyContent = httpData.getResponseBody() | |
if (TextUtils.equals(transferEncoding, "chunked")) { | |
bodyContent = getContentData(bodyContent) | |
} | |
val content = decompress(contentEncoding, bodyContent) | |
Log.i(MyHttpInjector.TAG + " " + response.id() + " <<", String(content)) | |
httpCache[response.id()]?.destroy() | |
httpCache.remove(response.id()) | |
} | |
} else { | |
Log.w(MyHttpInjector.TAG + " " + request.id() + " <<", "http id not found!") | |
} | |
} | |
override fun onResponseFinished(response: HttpResponse) { | |
Log.i(MyHttpInjector.TAG, "onResponseFinished " + response.id()) | |
} | |
class HttpData { | |
private var requestBody: ByteArrayOutputStream | |
private var responseBody: ByteArrayOutputStream | |
private lateinit var request: HttpRequest | |
private lateinit var response: HttpResponse | |
private var uid: Int | |
private var id: String | |
constructor(uid: Int, id: String) { | |
this.uid = uid | |
this.id = id | |
this.requestBody = ByteArrayOutputStream() | |
this.responseBody = ByteArrayOutputStream() | |
Log.i("HttpData", "new id:$id") | |
} | |
public fun setRequest(request: HttpRequest) { | |
this.request = request | |
} | |
public fun getRequest(): HttpRequest { | |
return request | |
} | |
public fun seResponse(response: HttpResponse) { | |
this.response = response | |
} | |
public fun getResponse(): HttpResponse? { | |
return response | |
} | |
public fun writeRequestBody(data: ByteArray) { | |
this.requestBody.write(data) | |
Log.i("HttpData", "writeRequestBody id:$id") | |
} | |
public fun getRequesBody(): ByteArray { | |
return this.requestBody.toByteArray() | |
} | |
public fun writeResponseBody(data: ByteArray) { | |
this.responseBody.write(data) | |
Log.i("HttpData", "writeResponseBody id:$id") | |
} | |
public fun getResponseBody(): ByteArray { | |
return this.responseBody.toByteArray() | |
} | |
public fun destroy() { | |
try { | |
Log.i("HttpData", "del id:$id") | |
this.requestBody.close() | |
this.responseBody.close() | |
} catch (t: Throwable) { | |
} | |
} | |
} | |
private var httpCache = HashMap<String, HttpData>() | |
private fun readData(inputStream: InputStream): ByteArray { | |
val buffer = ByteArray(4096) | |
val out = ByteArrayOutputStream() | |
var readLen = 0 | |
do { | |
readLen = inputStream.read(buffer) | |
if (readLen > 0) { | |
out.write(buffer, 0, readLen) | |
} | |
} while (readLen > 0) | |
return out.toByteArray() | |
} | |
private fun decompress(contentEncoding: String?, data: ByteArray): ByteArray { | |
if (TextUtils.equals(contentEncoding, "gzip")) { | |
Log.i("decompress", "gzip") | |
return readData(GZIPInputStream(ByteArrayInputStream(data))) | |
} else if (TextUtils.equals(contentEncoding, "deflate")) { | |
Log.i("decompress", "deflate") | |
return readData(InflaterInputStream(ByteArrayInputStream(data))) | |
} else if (TextUtils.equals(contentEncoding, "br")) { | |
Log.i("decompress", "br") | |
return data | |
} else { | |
Log.i("decompress", "identity") | |
return data | |
} | |
} | |
private fun getContentData(data: ByteArray): ByteArray { | |
var i = 0 | |
val out = ByteArrayOutputStream() | |
var partLen = StringBuilder() | |
while (i < data.size) { | |
partLen.append(data[i].toChar()) | |
if (partLen.endsWith("\r\n")) { | |
Log.i("Transfer-Encoding", "partLen=$partLen") | |
val len = Integer.parseInt(partLen.toString().trim(),16) | |
Log.i("Transfer-Encoding", "len=$len") | |
if (len > 0) { | |
out.write(data, i + 1, len) | |
} | |
partLen.clear() | |
i += len + 3 | |
} else { | |
i += 1 | |
} | |
if (partLen.length > 18) { | |
Log.e("Transfer-Encoding -> ", "partLen error") | |
return data | |
} | |
Log.i("Transfer-Encoding -> ", partLen.toString()) | |
} | |
return out.toByteArray() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment