From 1b6d1456f37a7b56ebd9fae7f85caa86c797917f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 17 Apr 2023 08:35:58 +0300 Subject: [PATCH] Add support for POST with json body --- .../parsers/network/OkHttpWebClient.kt | 170 +++++++++--------- .../kotatsu/parsers/network/WebClient.kt | 114 ++++++------ 2 files changed, 150 insertions(+), 134 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/network/OkHttpWebClient.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/network/OkHttpWebClient.kt index 7d61ba1e7..0bfe7ef3a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/network/OkHttpWebClient.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/network/OkHttpWebClient.kt @@ -12,96 +12,98 @@ import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.parseJson class OkHttpWebClient( - private val httpClient: OkHttpClient, - private val mangaSource: MangaSource, + private val httpClient: OkHttpClient, + private val mangaSource: MangaSource, ) : WebClient { - override suspend fun httpGet(url: HttpUrl): Response { - val request = Request.Builder() - .get() - .url(url) - .addTags() - return httpClient.newCall(request.build()).await().ensureSuccess() - } + override suspend fun httpGet(url: HttpUrl): Response { + val request = Request.Builder() + .get() + .url(url) + .addTags() + return httpClient.newCall(request.build()).await().ensureSuccess() + } - override suspend fun httpHead(url: HttpUrl): Response { - val request = Request.Builder() - .head() - .url(url) - .addTags() - return httpClient.newCall(request.build()).await().ensureSuccess() - } + override suspend fun httpHead(url: HttpUrl): Response { + val request = Request.Builder() + .head() + .url(url) + .addTags() + return httpClient.newCall(request.build()).await().ensureSuccess() + } - override suspend fun httpPost(url: HttpUrl, form: Map): Response { - val body = FormBody.Builder() - form.forEach { (k, v) -> - body.addEncoded(k, v) - } - val request = Request.Builder() - .post(body.build()) - .url(url) - .addTags() - return httpClient.newCall(request.build()).await().ensureSuccess() - } + override suspend fun httpPost(url: HttpUrl, form: Map): Response { + val body = FormBody.Builder() + form.forEach { (k, v) -> + body.addEncoded(k, v) + } + val request = Request.Builder() + .post(body.build()) + .url(url) + .addTags() + return httpClient.newCall(request.build()).await().ensureSuccess() + } - override suspend fun httpPost(url: HttpUrl, payload: String): Response { - val body = FormBody.Builder() - payload.split('&').forEach { - val pos = it.indexOf('=') - if (pos != -1) { - val k = it.substring(0, pos) - val v = it.substring(pos + 1) - body.addEncoded(k, v) - } - } - val request = Request.Builder() - .post(body.build()) - .url(url) - .addTags() - return httpClient.newCall(request.build()).await().ensureSuccess() - } + override suspend fun httpPost(url: HttpUrl, payload: String): Response { + val body = FormBody.Builder() + payload.split('&').forEach { + val pos = it.indexOf('=') + if (pos != -1) { + val k = it.substring(0, pos) + val v = it.substring(pos + 1) + body.addEncoded(k, v) + } + } + val request = Request.Builder() + .post(body.build()) + .url(url) + .addTags() + return httpClient.newCall(request.build()).await().ensureSuccess() + } - override suspend fun graphQLQuery(endpoint: String, query: String): JSONObject { - val body = JSONObject() - body.put("operationName", null as Any?) - body.put("variables", JSONObject()) - body.put("query", "{$query}") - val mediaType = "application/json; charset=utf-8".toMediaType() - val requestBody = body.toString().toRequestBody(mediaType) - val request = Request.Builder() - .post(requestBody) - .url(endpoint) - .addTags() - val json = httpClient.newCall(request.build()).await().ensureSuccess().parseJson() - json.optJSONArray("errors")?.let { - if (it.length() != 0) { - throw GraphQLException(it) - } - } - return json - } + override suspend fun httpPost(url: HttpUrl, body: JSONObject): Response { + val mediaType = "application/json; charset=utf-8".toMediaType() + val requestBody = body.toString().toRequestBody(mediaType) + val request = Request.Builder() + .post(requestBody) + .url(url) + .addTags() + return httpClient.newCall(request.build()).await().ensureSuccess() + } - private fun Request.Builder.addTags(): Request.Builder { - if (mangaSource != null) { - tag(MangaSource::class.java, mangaSource) - } - return this - } + override suspend fun graphQLQuery(endpoint: String, query: String): JSONObject { + val body = JSONObject() + body.put("operationName", null as Any?) + body.put("variables", JSONObject()) + body.put("query", "{$query}") + val json = httpPost(endpoint, body).parseJson() + json.optJSONArray("errors")?.let { + if (it.length() != 0) { + throw GraphQLException(it) + } + } + return json + } - private fun Response.ensureSuccess(): Response { - val exception: Exception? = when (code) { // Catch some error codes, not all - 404 -> NotFoundException(message, request.url.toString()) - in 500..599 -> HttpStatusException(message, code, request.url.toString()) - else -> null - } - if (exception != null) { - runCatching { - close() - }.onFailure { - exception.addSuppressed(it) - } - throw exception - } - return this - } + private fun Request.Builder.addTags(): Request.Builder { + tag(MangaSource::class.java, mangaSource) + return this + } + + private fun Response.ensureSuccess(): Response { + val exception: Exception? = when (code) { // Catch some error codes, not all + 404 -> NotFoundException(message, request.url.toString()) + in 500..599 -> HttpStatusException(message, code, request.url.toString()) + else -> null + } + if (exception != null) { + runCatching { + close() + }.onFailure { + exception.addSuppressed(it) + } + throw exception + } + return this + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/network/WebClient.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/network/WebClient.kt index 93770c4ff..a304e0ab3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/network/WebClient.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/network/WebClient.kt @@ -7,62 +7,76 @@ import org.json.JSONObject interface WebClient { - /** - * Do a GET http request to specific url - * @param url - */ - suspend fun httpGet(url: String): Response = httpGet(url.toHttpUrl()) + /** + * Do a GET http request to specific url + * @param url + */ + suspend fun httpGet(url: String): Response = httpGet(url.toHttpUrl()) - /** - * Do a GET http request to specific url - * @param url - */ - suspend fun httpGet(url: HttpUrl): Response + /** + * Do a GET http request to specific url + * @param url + */ + suspend fun httpGet(url: HttpUrl): Response - /** - * Do a HEAD http request to specific url - * @param url - */ - suspend fun httpHead(url: String): Response = httpHead(url.toHttpUrl()) + /** + * Do a HEAD http request to specific url + * @param url + */ + suspend fun httpHead(url: String): Response = httpHead(url.toHttpUrl()) - /** - * Do a HEAD http request to specific url - * @param url - */ - suspend fun httpHead(url: HttpUrl): Response + /** + * Do a HEAD http request to specific url + * @param url + */ + suspend fun httpHead(url: HttpUrl): Response - /** - * Do a POST http request to specific url with `multipart/form-data` payload - * @param url - * @param form payload as key=>value map - */ - suspend fun httpPost(url: String, form: Map): Response = httpPost(url.toHttpUrl(), form) + /** + * Do a POST http request to specific url with `multipart/form-data` payload + * @param url + * @param form payload as key=>value map + */ + suspend fun httpPost(url: String, form: Map): Response = httpPost(url.toHttpUrl(), form) - /** - * Do a POST http request to specific url with `multipart/form-data` payload - * @param url - * @param form payload as key=>value map - */ - suspend fun httpPost(url: HttpUrl, form: Map): Response + /** + * Do a POST http request to specific url with `multipart/form-data` payload + * @param url + * @param form payload as key=>value map + */ + suspend fun httpPost(url: HttpUrl, form: Map): Response - /** - * Do a POST http request to specific url with `multipart/form-data` payload - * @param url - * @param payload payload as `key=value` string with `&` separator - */ - suspend fun httpPost(url: String, payload: String): Response = httpPost(url.toHttpUrl(), payload) + /** + * Do a POST http request to specific url with `multipart/form-data` payload + * @param url + * @param payload payload as `key=value` string with `&` separator + */ + suspend fun httpPost(url: String, payload: String): Response = httpPost(url.toHttpUrl(), payload) - /** - * Do a POST http request to specific url with `multipart/form-data` payload - * @param url - * @param payload payload as `key=value` string with `&` separator - */ - suspend fun httpPost(url: HttpUrl, payload: String): Response + /** + * Do a POST http request to specific url with `multipart/form-data` payload + * @param url + * @param payload payload as `key=value` string with `&` separator + */ + suspend fun httpPost(url: HttpUrl, payload: String): Response - /** - * Do a GraphQL request to specific url - * @param endpoint an url - * @param query GraphQL request payload - */ - suspend fun graphQLQuery(endpoint: String, query: String): JSONObject + /** + * Do a POST http request to specific url with json payload + * @param url + * @param body + */ + suspend fun httpPost(url: String, body: JSONObject): Response = httpPost(url.toHttpUrl(), body) + + /** + * Do a POST http request to specific url with json payload + * @param url + * @param body + */ + suspend fun httpPost(url: HttpUrl, body: JSONObject): Response + + /** + * Do a GraphQL request to specific url + * @param endpoint an url + * @param query GraphQL request payload + */ + suspend fun graphQLQuery(endpoint: String, query: String): JSONObject }