Skip to content

Commit 207736e

Browse files
feat: Add support for sending JSON-encoded API requests
1 parent c937ef1 commit 207736e

4 files changed

Lines changed: 89 additions & 7 deletions

File tree

deepl-java/src/main/java/com/deepl/api/DeepLClient.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,15 @@ public MultilingualGlossaryInfo updateMultilingualGlossaryName(String glossaryId
577577
ArrayList<KeyValuePair<String, String>> bodyParams = new ArrayList<>();
578578
bodyParams.add(new KeyValuePair<>("name", name));
579579
String relativeUrl = String.format("/v3/glossaries/%s", glossaryId);
580-
HttpResponse response = httpClientWrapper.sendPatchRequestWithBackoff(relativeUrl, bodyParams);
581-
checkResponse(response, false, true);
582-
return jsonParser.parseMultilingualGlossaryInfo(response.getBody());
580+
try {
581+
HttpResponse response =
582+
httpClientWrapper.sendPatchRequestWithBackoff(relativeUrl, bodyParams);
583+
checkResponse(response, false, true);
584+
return jsonParser.parseMultilingualGlossaryInfo(response.getBody());
585+
} catch (InterruptedException e) {
586+
Thread.currentThread().interrupt();
587+
throw new DeepLException("Request was interrupted", e);
588+
}
583589
}
584590

585591
/**

deepl-java/src/main/java/com/deepl/api/HttpClientWrapper.java

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
import java.net.*;
1010
import java.time.*;
1111
import java.util.*;
12+
import org.apache.http.HttpHost;
1213
import org.apache.http.client.config.RequestConfig;
1314
import org.apache.http.client.methods.HttpPatch;
1415
import org.apache.http.entity.ByteArrayEntity;
1516
import org.apache.http.impl.client.CloseableHttpClient;
17+
import org.apache.http.impl.client.HttpClientBuilder;
1618
import org.apache.http.impl.client.HttpClients;
1719
import org.apache.http.util.EntityUtils;
1820
import org.jetbrains.annotations.*;
@@ -83,15 +85,61 @@ public HttpResponse sendPutRequestWithBackoff(
8385
return sendRequestWithBackoff(PUT, relativeUrl, content).toStringResponse();
8486
}
8587

88+
public HttpResponse sendJsonRequestWithBackoff(String relativeUrl, String jsonBody)
89+
throws InterruptedException, DeepLException {
90+
HttpContent content = HttpContent.buildJsonContent(jsonBody);
91+
return sendRequestWithBackoff(POST, relativeUrl, content).toStringResponse();
92+
}
93+
94+
public HttpResponse sendJsonRequestWithBackoff(String method, String relativeUrl, String jsonBody)
95+
throws InterruptedException, DeepLException {
96+
HttpContent content = HttpContent.buildJsonContent(jsonBody);
97+
return sendRequestWithBackoff(method, relativeUrl, content).toStringResponse();
98+
}
99+
100+
public HttpResponse sendJsonPatchRequestWithBackoff(String relativeUrl, String jsonBody)
101+
throws InterruptedException, DeepLException {
102+
return sendPatchRequestWithBackoff(relativeUrl, HttpContent.buildJsonContent(jsonBody));
103+
}
104+
86105
public HttpResponse sendPatchRequestWithBackoff(
87106
String relativeUrl, @Nullable Iterable<KeyValuePair<String, String>> params)
88-
throws DeepLException {
89-
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
90-
HttpContent content = HttpContent.buildFormURLEncodedContent(params);
107+
throws InterruptedException, DeepLException {
108+
HttpContent content = HttpContent.buildFormURLEncodedContent(params);
109+
return sendPatchRequestWithBackoff(relativeUrl, content);
110+
}
111+
112+
private HttpResponse sendPatchRequestWithBackoff(String relativeUrl, HttpContent content)
113+
throws InterruptedException, DeepLException {
114+
BackoffTimer backoffTimer = new BackoffTimer(this.minTimeout);
115+
while (true) {
116+
try {
117+
HttpResponse response = sendPatchRequest(relativeUrl, content, backoffTimer);
118+
if (backoffTimer.getNumRetries() >= this.maxRetries) {
119+
return response;
120+
} else if (response.getCode() != 429 && response.getCode() < 500) {
121+
return response;
122+
}
123+
} catch (ConnectionException exception) {
124+
if (!exception.getShouldRetry() || backoffTimer.getNumRetries() >= this.maxRetries) {
125+
throw exception;
126+
}
127+
}
128+
backoffTimer.sleepUntilRetry();
129+
}
130+
}
131+
132+
private HttpResponse sendPatchRequest(
133+
String relativeUrl, HttpContent content, BackoffTimer backoffTimer) throws DeepLException {
134+
HttpClientBuilder builder = HttpClients.custom();
135+
if (proxy != null) {
136+
InetSocketAddress addr = (InetSocketAddress) proxy.address();
137+
builder.setProxy(new HttpHost(addr.getHostName(), addr.getPort()));
138+
}
139+
try (CloseableHttpClient httpClient = builder.build()) {
91140
HttpPatch request = new HttpPatch(serverUrl + relativeUrl);
92141

93142
// Set timeouts
94-
BackoffTimer backoffTimer = new BackoffTimer(this.minTimeout);
95143
RequestConfig requestConfig =
96144
RequestConfig.custom()
97145
.setConnectTimeout((int) backoffTimer.getTimeoutMillis())

deepl-java/src/main/java/com/deepl/api/http/HttpContent.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ private static String urlEncode(String value) throws DeepLException {
5252
}
5353
}
5454

55+
public static HttpContent buildJsonContent(String jsonBody) {
56+
if (jsonBody == null) {
57+
throw new IllegalArgumentException("jsonBody must not be null");
58+
}
59+
return new HttpContent("application/json", jsonBody.getBytes(StandardCharsets.UTF_8));
60+
}
61+
5562
public static HttpContent buildMultipartFormDataContent(
5663
Iterable<KeyValuePair<String, Object>> params) throws Exception {
5764
String boundary = UUID.randomUUID().toString();

deepl-java/src/test/java/com/deepl/api/MultilingualGlossaryTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,27 @@ void testGlossaryUpdateName() throws Exception {
482482
}
483483
}
484484

485+
@Test
486+
void testGlossaryUpdateNameWithSpecialCharsIsProperlyEncoded() throws Exception {
487+
DeepLClient deepLClient = createDeepLClient();
488+
try (MultilingualGlossaryCleanupUtility cleanup =
489+
new MultilingualGlossaryCleanupUtility(deepLClient)) {
490+
GlossaryEntries entries = new GlossaryEntries();
491+
entries.put("key1", "value1");
492+
List<MultilingualGlossaryDictionaryEntries> glossaryDicts =
493+
Arrays.asList(new MultilingualGlossaryDictionaryEntries(sourceLang, targetLang, entries));
494+
MultilingualGlossaryInfo glossary =
495+
deepLClient.createMultilingualGlossary(cleanup.getGlossaryName(), glossaryDicts);
496+
497+
String nameWithSpecialChars = "Name with special chars: é &foo=bar \"quoted\"";
498+
MultilingualGlossaryInfo updatedGlossary =
499+
deepLClient.updateMultilingualGlossaryName(
500+
glossary.getGlossaryId(), nameWithSpecialChars);
501+
502+
Assertions.assertEquals(nameWithSpecialChars, updatedGlossary.getName());
503+
}
504+
}
505+
485506
@Test
486507
void testGlossaryTranslateTextSentence() throws Exception {
487508
DeepLClient deepLClient = createDeepLClient();

0 commit comments

Comments
 (0)