feat: add Fetcher seam with an identifying user agent

This commit is contained in:
marcos
2026-08-05 15:11:11 +00:00
parent 3d2150d2a6
commit 9ffcf816ea
2 changed files with 73 additions and 0 deletions
@@ -0,0 +1,14 @@
package dev.marcospaulo.canalhandia;
import java.io.IOException;
/** The one place the plugin talks to the network, so tests can replace it. */
interface Fetcher {
/** GET a URL, returning the body. */
String get(String url) throws IOException, InterruptedException;
/** POST JSON with a bearer token, returning the body. */
String postJson(String url, String json, String bearer)
throws IOException, InterruptedException;
}
@@ -0,0 +1,59 @@
package dev.marcospaulo.canalhandia;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
final class HttpFetcher implements Fetcher {
/**
* pt.minecraft.wiki answers 403 to a default user agent — MediaWiki policy
* requires callers to identify themselves.
*/
private static final String AGENT =
"Canalhandia-Minecraft-Bot/1.0 (https://marcospaulo.dev.br)";
private final HttpClient http = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
private final int timeoutSeconds;
HttpFetcher(int timeoutSeconds) {
this.timeoutSeconds = timeoutSeconds;
}
@Override
public String get(String url) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.timeout(Duration.ofSeconds(timeoutSeconds))
.header("User-Agent", AGENT)
.GET()
.build();
return body(http.send(request, HttpResponse.BodyHandlers.ofString()));
}
@Override
public String postJson(String url, String json, String bearer)
throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder(URI.create(url))
.timeout(Duration.ofSeconds(timeoutSeconds))
.header("Content-Type", "application/json")
.header("User-Agent", AGENT)
.header("Authorization", "Bearer " + bearer)
.POST(HttpRequest.BodyPublishers.ofString(json, StandardCharsets.UTF_8))
.build();
return body(http.send(request, HttpResponse.BodyHandlers.ofString()));
}
private String body(HttpResponse<String> response) throws IOException {
if (response.statusCode() / 100 != 2) {
throw new IOException("HTTP " + response.statusCode() + ": "
+ AiText.forLog(response.body()));
}
return response.body();
}
}