Skip to content

Commit

Permalink
fix(java): Properly encode nested parameters with file upload (#688)
Browse files Browse the repository at this point in the history
  • Loading branch information
jablan authored Sep 25, 2024
1 parent 7161c93 commit c32abb5
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* API tests for UploadsApi
Expand Down Expand Up @@ -104,18 +106,29 @@ public void uploadCreateTest() throws ApiException, IOException, InterruptedExce
Boolean skipUnverification = null;
String fileEncoding = null;
Object localeMapping = null;
Object formatOptions = null;
Boolean autotranslate = null;
Boolean markReviewed = null;
Boolean tagOnlyAffectedKeys = null;
Upload response = api.uploadCreate(projectId, file, fileFormat, localeId, xPhraseAppOTP, branch, tags, updateTranslations, updateTranslationKeys, updateTranslationsOnSourceMatch, updateDescriptions, convertEmoji, skipUploadTags, skipUnverification, fileEncoding, localeMapping, formatOptions, autotranslate, markReviewed, tagOnlyAffectedKeys);

Map<String, String> nestedFormatOptionsMap = new HashMap<>();
nestedFormatOptionsMap.put("nested_option", "sub_option");

Map<String, Object> formatOptionsMap = new HashMap<>();
formatOptionsMap.put("omit_separator_space", "true");
formatOptionsMap.put("fallback_language", "en");
formatOptionsMap.put("more_options", nestedFormatOptionsMap);

Upload response = api.uploadCreate(projectId, file, fileFormat, localeId, xPhraseAppOTP, branch, tags, updateTranslations, updateTranslationKeys, updateTranslationsOnSourceMatch, updateDescriptions, convertEmoji, skipUploadTags, skipUnverification, fileEncoding, localeMapping, formatOptionsMap, autotranslate, markReviewed, tagOnlyAffectedKeys);

Assert.assertEquals("valid id returned", "id_example", response.getId());
Assert.assertEquals("valid creation date returned", OffsetDateTime.parse("2015-01-28T09:52:53Z"), response.getCreatedAt());

RecordedRequest recordedRequest = mockBackend.takeRequest();
Assert.assertEquals("Request path", "//projects/projectId_example/uploads", recordedRequest.getPath());
Assert.assertTrue("Request payload", recordedRequest.getBody().readUtf8().contains("Content-Disposition: form-data; name=\"file\""));
String requestBody = recordedRequest.getBody().readUtf8();
Assert.assertTrue("payload contains filename", requestBody.contains("Content-Disposition: form-data; name=\"file\""));
Assert.assertTrue("payload contains fileFormat", Pattern.compile("Content-Disposition: form-data; name=\"file_format\"\\s+Content-Length: 11\\s+simple_json", Pattern.MULTILINE).matcher(requestBody).find());
Assert.assertTrue("payload contains nested format options", Pattern.compile("Content-Disposition: form-data; name=\"format_options\\[more_options\\]\\[nested_option\\]\"\\s+Content-Length: 10\\s+sub_option", Pattern.MULTILINE).matcher(requestBody).find());
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,14 +667,11 @@ public class ApiClient {
{{! TODO check why nested params ordering is different }}
params.addAll(parsedMappedParams(key, value, new ArrayList<Pair>()));
}
}
return params;
}
/**
* Formats the specified query parameter to a list containing a single {@code Pair} object.
*
Expand Down Expand Up @@ -1348,8 +1345,12 @@ public class ApiClient {
MediaType mediaType = MediaType.parse(guessContentTypeFromFile(file));
mpBuilder.addPart(partHeaders, RequestBody.create(mediaType, file));
} else {
Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + param.getKey() + "\"");
mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(param.getValue())));
// flatten the nested structures first
List<Pair> flatParams = parsedMappedParams(param.getKey(), param.getValue(), new ArrayList<Pair>());
for (Pair pair : flatParams) {
Headers partHeaders = Headers.of("Content-Disposition", "form-data; name=\"" + pair.getName() + "\"");
mpBuilder.addPart(partHeaders, RequestBody.create(null, parameterToString(pair.getValue())));
}
}
}
return mpBuilder.build();
Expand Down Expand Up @@ -1473,11 +1474,11 @@ public class ApiClient {
for(Map.Entry<String, Object> entry : mappedValue.entrySet()){
String nestedKey = key + "[" + entry.getKey() + "]";
parsedMappedParams(nestedKey, entry.getValue(), params);
parsedMappedParams(nestedKey, entry.getValue(), params);
}
}
else{
params.add(new Pair(key, parameterToString(value)));
params.add(new Pair(key, parameterToString(value)));
}

return params;
Expand Down

0 comments on commit c32abb5

Please sign in to comment.