Skip to content

Instantly share code, notes, and snippets.

@hfutxqd
Created June 13, 2019 11:24
Show Gist options
  • Save hfutxqd/7b786c64bb2f53aeca244d5f126acdff to your computer and use it in GitHub Desktop.
Save hfutxqd/7b786c64bb2f53aeca244d5f126acdff to your computer and use it in GitHub Desktop.
simple http injector sample for netbare
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