I am working on custom gradle plugin which trigger API POST call. There is no many option for networking from gradle and UrlConnection looks as a best tool. I am able to trigger GET API call, but can not do it for POST.
Here is my client code from gradle plugin:
interface SwapTestPluginExtension {
val backEndEndpoint: Property<String>
}
class SwapTestPlugin: Plugin<Project> {
override fun apply(target: Project) {
val extension = target.extensions.create("swapTest", SwapTestPluginExtension::class.java)
target.task("prepareTestEnvironment") {
doLast {
try {
println("[start] ${SwapTestPlugin::class.simpleName}")
executePostApiCall(extension)
} catch (ex: Exception) {
println("Something whent wrong in ${SwapTestPlugin::class.simpleName} with exception ${ex}")
} finally {
println("[end] ${SwapTestPlugin::class.simpleName}")
}
}
}
}
private fun executePostApiCall(extension: SwapTestPluginExtension) {
val credentials = "{\"name\": \"\", \"pwd\" : \"\"}"
val req = URL("${extension.backEndEndpoint.get()}/test/environment").openConnection() as HttpURLConnection
req.setRequestMethod("POST")
req.setRequestProperty("Content-Type", "application/json; charset=UTF-8")
req.setRequestProperty("Accept", "*/*");
req.setDoOutput(true)
println("[swap-test-plugin] prepare to call API")
req.getOutputStream().write(JsonOutput.toJson(credentials).toByteArray(Charsets.UTF_8)/*.getBytes("UTF-8")*/)
req.outputStream.flush()
println("[swap-test-plugin] API has been called, going to read results")
val br = BufferedReader(InputStreamReader(req.inputStream, Charsets.UTF_8.name()))
val response = StringBuilder()
var responseLine: String? = null
while (br.readLine().also { responseLine = it } != null) {
response.append(responseLine!!.trim { it <= ' ' })
}
println("[swap-test-plugin] prepare to parse result")
val json = JsonSlurper().parseText(response.toString())
println("[json] ${json}")
}
}
Here is stubs for API methods on the backend:
controllers/test.js
const config = require('config');
const network = require('../utils/network')
const logger = require('../utils/logger')
exports.setEnvironment = async function(req, res) {
logger.log("[start] /test/environment call");
let result
if (config.isProduction) {
result = network.getErrorMsg(501, "This method is only supported for non-production mode for test purposes.")
} else {
// TODO clean up database if it is a debug mode
result = network.getMsg(200, JSON.stringify({"msg" : "just a stub"}));
}
logger.log(`[end] response ${JSON.stringify(result)}`)
network.send(req, res, result);
}
routes/index.js
...
router.post('/api/v1/test/environment', tests.setEnvironment);
...
Wireshark shows an POST request happens, but there is not activity on the server - it looks like it never reaches. The similar GET request works fine. Here is a source code of the backend in case you would like to copy-paste this block of code and reproduce.
1589 960.149964545 127.0.0.1 127.0.0.1 HTTP/JSON 100 POST /api/v1/test/environment HTTP/1.1 , JavaScript Object Notation (application/json)
1590 960.149967554 127.0.0.1 127.0.0.1 TCP 66 3100 → 50170 [ACK] Seq=1 Ack=262 Win=65280 Len=0 TSval=3277455079 TSecr=3277455079
Do you notice cause of this issue?