Wenn ich beim Erstellen einer Android-Anwendung eine API-Kommunikation durchführen wollte, musste ich diese aus irgendeinem Grund ohne Verwendung der OSS-Bibliothek implementieren.
Daher habe ich mit HttpURLConnection
meinen eigenen Kommunikationsteil erstellt.
Es tritt jedoch ein Fehler auf, wenn ich eine PATCH-Anfrage senden möchte.
Es scheint, dass HttpURLConnection
keine PATCH-Anfragen stellen kann.
Lüge ... richtig ...
Es gibt auch eine Möglichkeit, mit dem Header "X-HTTP-Method-Override" zu fälschen, dies scheint jedoch aufgrund serverseitiger Abhängigkeiten ungewiss zu sein. https://stackoverflow.com/questions/25163131/httpurlconnection-invalid-http-method-patch
Wie macht man die OSS-Bibliothek? Lesen Sie daher Öffentlicher Code der HTTP-Clientbibliothek mit dem Namen Jersey. Und implementiert. Es ist eine kleine alte Bibliothek, aber ich konnte ihren Betrieb bestätigen.
Implementieren Sie die Klasse "HttpClient" wie folgt. Dieses Mal wird die Inhaberauthentifizierung angenommen.
HttpClient.kt
internal class HttpClient {
companion object {
fun patch(url: String, accessToken: String? = null, body: String? = null): Pair<Int, String?> {
var responseJsonString: String? = null
val urlTmp = URL(url)
val con = urlTmp.openConnection() as HttpURLConnection
try {
setRequestMethodViaJreBugWorkaround( con, "PATCH")
con.instanceFollowRedirects = false
con.doOutput = true
con.connectTimeout = 60000
con.readTimeout = 60000
con.setRequestProperty("Content-Type", "application/json")
con.setRequestProperty("Accept", "application/json")
if(accessToken != null) con.setRequestProperty("Authorization", "Bearer $accessToken")
if(body != null) {
val os: OutputStream = con.outputStream
val ps = PrintStream(os)
ps.print(body)
ps.close()
}
val reader: BufferedReader
reader = if (con.responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader(InputStreamReader(con.inputStream, "UTF-8"))
} else {
BufferedReader(InputStreamReader(con.errorStream, "UTF-8"))
}
responseJsonString = reader.readLine()
con.disconnect()
} catch (e: Exception) {
e.printStackTrace()
Log.e("ApiClientException", e.toString())
}
return con.responseCode to responseJsonString
}
private fun setRequestMethodViaJreBugWorkaround(httpURLConnection: HttpURLConnection, method: String) {
try {
httpURLConnection.requestMethod = method // Check whether we are running on a buggy JRE
} catch (pe: ProtocolException) {
try {
AccessController.doPrivileged(PrivilegedExceptionAction<Any?> {
try {
httpURLConnection.requestMethod = method
// Check whether we are running on a buggy
// JRE
} catch (pe: ProtocolException) {
var connectionClass: Class<*>? = httpURLConnection.javaClass
val delegateField: Field?
try {
delegateField = connectionClass!!.getDeclaredField("delegate")
delegateField.isAccessible = true
val delegateConnection = delegateField[httpURLConnection] as HttpURLConnection
setRequestMethodViaJreBugWorkaround(delegateConnection, method)
} catch (e: NoSuchFieldException) {
// Ignore for now, keep going
} catch (e: IllegalArgumentException) {
throw RuntimeException(e)
} catch (e: IllegalAccessException) {
throw RuntimeException(e)
}
try {
var methodField: Field
while (connectionClass != null) {
try {
methodField = connectionClass.getDeclaredField("method")
} catch (e: NoSuchFieldException) {
connectionClass = connectionClass.superclass
continue
}
methodField.isAccessible = true
methodField[httpURLConnection] = method
break
}
} catch (e: java.lang.Exception) {
throw RuntimeException(e)
}
}
null
})
} catch (e: PrivilegedActionException) {
val cause: Throwable? = e.cause
if (cause is RuntimeException) {
throw cause
} else {
throw RuntimeException(cause)
}
}
}
}
}
}
Importieren Sie den obigen HttpClient
und verwenden Sie ihn wie folgt.
fun patchRequestSample() {
val (statusCode, responseJsonString) = HttpClient.patch("https://hoge/users/10", accessToken ="xxxx", body = sampleJson.toString())
}
Der Statuscode wird in "statusCode" und die Antwort in "responseJsonString" zurückgegeben.
Selbst wenn ich es nachgeschlagen habe, habe ich nur herausgefunden, wie ich den Header überschreiben kann, also werde ich es als Erinnerung belassen.
Recommended Posts