#Cannot make POST requests with HttpClient -- handshake failed

1 messages · Page 1 of 1 (latest)

vivid solstice
#

Hey all! I have tried, tried, and tried again to get POST requests working in PowerNukkitX, but for some reason it just won't work.

Basically, every time a player joins I'm trying to send over a POST request to my server to store basic information about the player (statistical purposes and whatnot). The API works on its own (RestTestTest can go through it fine with no issue), and the event handler registers correctly, but the actual call to send a POST request always returns the same error:

00:25:58 [ForkJoinPool.commonPool-worker-1] [WARN] [CapeManager]: Failed to send HTTP request: (handshake_failure) Received fatal alert: handshake_failure

WHAT I HAVE TRIED DOING:

  1. Attempted multiple domains-- both my own and GitHub fail to handshake, meaning they don't even get something like a 404 error code and quit after failing to establish an HTTPS connection
  2. Altering all sorts of HttpClient settings, from the ciphers available to TLS version and everything inbetween
  3. Over an hour of troubleshooting with various A.I. agents (ChatGPT, Grok) none of which were any help
  4. Setting CORS and other networking options on my server to increasingly low levels of security (but cannot disable HTTPS)
  5. Bashing my head against a wall (still did nothing)

Project Java Version: 24

MY WORKING FUNCTION CODE:```java
@EventHandler
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
String capeId = player.getSkin().getCapeId();

    capeManager.getLogger().info("Player " + player.getLoginChainData().getXUID() + " joined with Cape ID " + capeId);

    String url = "https://website.lol/log-user";

    HttpClient client = HttpClient.newHttpClient();
    String body = "{\"xuid\": \"" + player.getLoginChainData().getXUID() + "\", \"username\": \"" + player.getName() + "\", \"capeId\": \"" + capeId + "\"}";

    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .header("Content-Type", "application/json")
            .header("Authorization", "mypasswordhere")
            .POST(HttpRequest.BodyPublishers.ofString(body))
            .build();

    CompletableFuture.runAsync(() -> {
        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            if (response.statusCode() == 200) {
                capeManager.getLogger().info("Request to " + url + " was successful!");
            } else {
                capeManager.getLogger().warning("Request to " + url + " failed with status code: " + response.statusCode());
            }
            System.out.println("Status Code: " + response.statusCode());
            System.out.println("Response Body: " + response.body());
        } catch (IOException | InterruptedException e) {
            capeManager.getLogger().warning("Failed to send HTTP request: " + e.getMessage());
        }
    });
}```

The requests work fine in a standalone Java project, for some reason this is exclusively limited to when it's run as a plugin within my test server. I have spent hours upon hours trying to fix this, and this server is truly my last hope. If anybody can help me fix this, please let me know!

Thank you!

vivid solstice
#

Slight update: I tried switching to OkHttp3 to see if a different library would help, but no. The SSL handshake still fails with the exact same error message.

glad sundial
#

Thats java.. We do not modify the java library.. If your code works in standalone, it should work in PNX too.. Could you check if you shade all the requires dependencies in your jar?

vivid solstice
#

It shouldn’t need any dependencies shaded since it’s just standard Java utilities and there’s no errors thrown for it otherwise

polar rain
vivid solstice
#

what libraries did you use? it seems like no matter what domain i use the handshake always fails (including trusted test routes), meaning its a plugin failure

vivid solstice
#

same here... clearly the networking gods hate me 😔

polar rain
vivid solstice
#

ty dude, that would be great

polar rain
#

Ur welcome

polar rain
#

it was with Lombok and Intellij but it should be still worth a try

#
package de.adrian.test.command;

import cn.nukkit.Player;
import cn.nukkit.command.CommandSender;
import cn.nukkit.command.PluginCommand;
import de.adrian.test.Main;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;

public class GetRequestCommand extends PluginCommand<Main> {
    public GetRequestCommand() {
        super("getrequest", Main.instance);
    }

    @Override
    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
        if (!sender.isPlayer()) {
            return false;
        }

        Player player = (Player) sender;

        OkHttpClient client = new OkHttpClient.Builder().build();

        Request request = new Request.Builder()
                .url("http://localhost:9999/test")
                .get()
                .build();

        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                try(ResponseBody body = response.body()) {
                    if (response.isSuccessful()) {
                        String bodyString = body.string();
                        player.sendMessage(bodyString);
                        player.sendMessage(String.valueOf(response.code()));
                    }
                }
            }

            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                System.out.println(e.getMessage());
            }
        });

        return true;
    }
}
#
package de.adrian.test.command;

import cn.nukkit.Player;
import cn.nukkit.command.CommandSender;
import cn.nukkit.command.PluginCommand;
import de.adrian.test.Main;
import okhttp3.*;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;

public class PostRequestCommand extends PluginCommand<Main> {


    public PostRequestCommand() {
        super("postrequest", Main.instance);
    }

    @Override
    public boolean execute(CommandSender sender, String commandLabel, String[] args) {
        if (!sender.isPlayer()) {
            return false;
        }

        Player player = (Player) sender;

        OkHttpClient client = new OkHttpClient.Builder().build();

        Request request = new Request.Builder()
                .url("http://localhost:9999/test")
                .post(RequestBody.create(MediaType.parse("text/plain"), args[0]))
                .build();

        client.newCall(request).enqueue(new Callback() {

            @Override
            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                    if (response.isSuccessful()) {
                        player.sendMessage(String.valueOf(response.code()));
                    }
                }

            @Override
            public void onFailure(@NotNull Call call, @NotNull IOException e) {
                System.out.println(e.getMessage());
            }
        });

        return true;
    }
}
#

for me everything works fine i can also test it when having the api on a different server but yeah

#

My project uses Javalin 6 for the API, OkHTTP 3 for the Post/Get Requests and is running on Java 22

#
package de.adrian.test;

import io.javalin.Javalin;

public class Main {
    public static void main(String[] args) {
        var app = Javalin.create();
        app.get("/test", ctx -> ctx.result("Hello World"));
        app.post("/test", context -> {
            if (!context.body().isEmpty()) {
                System.out.println("Got body: " + context.body());
                context.status(200);
            } else {
                System.out.println("Got empty body");
                context.status(400);
            }
        });
        app.start(9999);
    }
}
vivid solstice
#

i wish there was an easier way to host my node.js API on the server but i dont wanna ask for too much, thanks for the pointers!!!

polar rain
#

or use stuff like websockets or other caching / messaging methods to exchange informations constantly

#

when someone joins / an event gets fired