im calling a GET Api (API of ModernMTT) with OkHttp (Last version), my problem is that the reply from the server is not in UTF-8 but in Percent Encoding, and i dont understand why, i try to set MINE in UTF-8 without result.
From CURL and Postman the server reply good.
So the problem is on OkHttp.
My code
public static String translate(String string) throws IOException {
OkHttpClient client = new OkHttpClient().newBuilder().addInterceptor(new FixEncodingInterceptor()).build();
Request request = new Request.Builder()
.url("https://api.modernmt.eu/translate?source=" + sourceLanguage + "&target=" + targetLanguage + "&q=" + string)
.method("GET", null)
.addHeader("MMT-ApiKey", apiKey)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String stringTranslated= Objects.requireNonNull(response.body()).string();
ResponseMTT responseMTT = new Gson().fromJson(stringTranslated, ResponseMTT.class);
StandardCharsets.UTF_8));
return responseMTT.getData().getTranslation();
}
}
The response.body.string() return this format:
%22Sconto%20del%2020%:%20%3CPAColor0xFF66CC33%3EUtilities%20%E2%86%92%20Capacity%20of%20load%3CPAOldColor%3E.
Can you try to set "Accept-Charset" header to UTF-8 and test your code? I am assuming Postman is defaulting the accept charset header to utf-8.
Related
I can't figure out how to send a file via POST request to https://0x0.st in java
My code:
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addTextBody("key", key);
builder.addTextBody("client_id", client_id );
builder.addTextBody("direction_id", direction_id);
ContentType fileContentType = ContentType.create("image/jpeg");
String fileName = file.getName();
builder.addBinaryBody("client_files", file, fileContentType, fileName);
HttpEntity entity = builder.build();
Try this:
public static String uploadFile(String path, ContentType contentType) throws IOException {
File file = new File(path);
URI serverURL = URI.create("https://0x0.st/");
try(CloseableHttpClient client = HttpClientBuilder.create().build()) {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.addBinaryBody("file", file, contentType, file.getName());
HttpEntity requestEntity = builder.build();
HttpPost post = new HttpPost(serverURL);
post.setEntity(requestEntity);
try(CloseableHttpResponse response = client.execute(post)) {
HttpEntity responseEntity = response.getEntity();
int responseCode = response.getStatusLine().getStatusCode();
String responseString = EntityUtils.toString(responseEntity, "UTF-8");
if(responseCode == 200)
return responseString;
else throw new RuntimeException(responseCode + ": " + responseString);
}
}
}
The key for your upload must be file, url or shorten, otherwise you will get a 400 bad request response. If the request is successful, the provided code returns the URL for your uploaded file.
There are several Http clients available that you can try. The popular ones would be
Apache Http client
OK Http client.
I actually wrote my own Http client which is part of MgntUtils Open Source library written and maintained by me. The reason I wrote my own Http client is to provide a very simple option. It doesn't support all the features provided in other clients but is very simple in use, and it does support uploading and downloading binary information. Assuming from your code that key, client_id, and direction_id could be passed as request headers your code could be something like this
byte[] content = readFile() //Read file as bytes here
byte[] content = readFile() //Read file as bytes hereHttpClient client = new HttpClient();
client.setContentType("image/jpeg");
client.setRequestHeader("key", key);
client.setRequestHeader("client_id", client_id);
client.setRequestHeader("direction_id", direction_id);
String result = client.sendHttpRequest(" https://0x0.st", HttpMethod.POST, ByteBuffer.wrap(content));
System.out.println("Upload result: " + result); //If you expect any textual reply
System.out.println("Upload HTTP response" + client.getLastResponseCode() + " " + client.getLastResponseMessage());
Here is Javadoc for HttpClient class. The library could be obtained as Maven artifacts or from Github, including source code and Javadoc
I am trying to send request from Java to Twilio SMS API.
I am using java.net.http package:
var url = UriBuilder.fromUri(
"https://api.twilio.com/2010-04-01/Accounts/MyAccount/Messages.json").build();
var urlEncodedBody = URLEncoder.encode(String.format("To=%s&From=%s&Body=%s",
"+1123456789",
"+1223456789",
"Hello"),
StandardCharsets.UTF_8);
var request = HttpRequest.newBuilder(url)
.headers("Authorization", "Basic " + base64,
"Content-Type", "application/x-www-form-urlencoded")
.method("POST", HttpRequest.BodyPublishers.ofString(
urlEncodedBody))
.build();
HttpClient httpClient = HttpClient.newBuilder().build();
try {
var response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException |
InterruptedException e) {
throw new RuntimeException(e);
}
I keep getting the error response:
{"code": 21604, "message": "A 'To' phone number is required.", "more_info": "https://www.twilio.com/docs/errors/21604", "status": 400}
Any idea what I'm missing?
I think when you encode the body of the request you are also encoding the &s and =s so it just seems to be one string.
This answer on a different question suggests using a Map and encoding each value in turn. Using that as a basis, your could replace your string formatting with:
Map<String, String> parameters = new HashMap<>();
parameters.put("To", "+1123456789");
parameters.put("From", "+1223456789");
parameters.put("Body", "Hello");
String urlEncodedBody = parameters.entrySet()
.stream()
.map(e -> e.getKey() + "=" + URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
.collect(Collectors.joining("&"));
I'm trying to get some json data using OkHttp and can't figure out why when i try logging the response.body().toString() what i get is Results:﹕ com.squareup.okhttp.Call$RealResponseBody#41c16aa8
try {
URL url = new URL(BaseUrl);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.header(/****/)
.build();
Call call = client.newCall(request);
Response response = call.execute();
**//for some reason this successfully prints out the response**
System.out.println("YEAH: " + response.body().string());
if(!response.isSuccessful()) {
Log.i("Response code", " " + response.code());
}
Log.i("Response code", response.code() + " ");
String results = response.body().toString();
Log.i("OkHTTP Results: ", results);
I don't know what i'm doing wrong here. How do i get the response string?
You have use .string() function to print the response in System.out.println(). But at last in Log.i() you are using .toString().
So please use .string() on response body to print and get your request's response, like:
response.body().string();
NOTE:
.toString(): This returns your object in string format.
.string(): This returns your response.
I think this solve your problem... Right.
Just in case someone bumps into the same weird thing as I have. I run my code during development in Debug Mode and apparently since OKHttp 2.4
..the response body is a one-shot value that may be consumed only once
So when in debug there is a call "behind the scene" from the inspector and the body is always empty. See: https://square.github.io/okhttp/3.x/okhttp/okhttp3/ResponseBody.html
The response.body.string() can be consumed only once.
Please use as below:
String responseBodyString = response.body.string();
Use the responseBodyString as needed in your application.
Given that a response can potentially produce an OutOfMemoryError in cases of large files, you can instead "peek" the body with the number of bytes and call the string() method.
Note that this will consume the body.
response.peekBody(500).string());
Following is my modified CurlInterceptor. Check the end of the intercept function where I m recreating the Response object after consuming the old Response.
var responseBodyString = responseBody?.string()
response = response.newBuilder()
.body(
ResponseBody.create(
responseBody?.contentType(),
responseBodyString.toByteArray()
)
)
.build()
class CurlInterceptor: Interceptor
{
var gson = GsonBuilder().setPrettyPrinting().create()
override fun intercept(chain: Interceptor.Chain): Response {
Timber.d(" **** ->>Request to server -> ****")
val request = chain.request()
var response = chain.proceed(request)
var curl = "curl -v -X ${request.method()}"
val headers = request.headers()
for ( i in 0..(headers.size() -1) ){
curl = "${curl} -H \"${headers.name(i)}: ${headers.value(i)}\""
}
val requestBody = request.body()
if (requestBody != null) {
val buffer = Buffer()
requestBody.writeTo(buffer)
var charset: Charset =
Charset.forName("UTF-8")
curl = "${curl} --data '${buffer.readString(charset).replace("\n", "\\n")}'"
}
Timber.d("$curl ${request.url()}")
Timber.d("response status code ${response.code()} message: ${response.message()}")
dumbHeaders(response)
var responseBody = response?.body()
if(responseBody != null )
{
var responseBodyString = responseBody?.string()
response = response.newBuilder()
.body(
ResponseBody.create(
responseBody?.contentType(),
responseBodyString.toByteArray()
)
)
.build()
responseBodyString = gson.toJson(responseBodyString)
Timber.d("response json -> \n $responseBodyString")
}
Timber.d(" **** << Response from server ****")
return response
}
fun dumbHeaders(response: Response) {
try {
if (response.headers() != null) {
for (headerName in response.headers().names()) {
for (headerValue in response.headers(headerName)) {
Timber.d("Header $headerName : $headerValue")
}
}
}
}
catch (ex: Exception){}
}
}
Instead of using .toString() which returns an object
String results = response.body().toString();
you can use
String results = response.body().string();
Call call = client.newCall(request);
return call.execute().body().string();
we can get response as a return fromby these
try to change it like that for example:
protected String doInBackground(String... params) {
try {
JSONObject root = new JSONObject();
JSONObject data = new JSONObject();
data.put("type", type);
data.put("message", message);
data.put("title", title);
data.put("image_url", imageUrl);
data.put("uid",uid);
data.put("id", id);
data.put("message_id", messageId);
data.put("display_name", displayName);
root.put("data", data);
root.put("registration_ids", new JSONArray(receipts));
RequestBody body = RequestBody.create(JSON, root.toString());
Request request = new Request.Builder()
.url(URL)
.post(body)
.addHeader("Authorization", "key=" + serverKey)
.build();
Response response = mClient.newCall(request).execute();
String result = response.body().string();
Log.d(TAG, "Result: " + result);
return result;
} catch (Exception ex) {
Log.e(TAG,"Exception -> "+ex.getMessage());
}
return null;
}
Recreate the response object after consuming the string
val responseBodyString = response.body()!!.string()
response = response.newBuilder()
.body(ResponseBody.create(responseBody?.contentType(), responseBodyString.toByteArray()))
.build()
Kotlin Programmers I am here for you
response.body?.charStream()?.readText()?.let {
//Where it refers to Response string
callBack.onAPISuccess(it)
}
Here you can not use .toString() function and .string() function is not available in Kotlin than you can user charStream() and than convert that charStream into readText() but you have to unwrap the whole value before passing it.But it will never create problem.
I have not explored these charStream() and readText() functions in java but I think it should be there and you can use this in java if these functions are available because I just got to know that java has deprecated the .string() function.
I am struggling with creating a plain text file on a server via HTTP PUT. I am using apache commons httpClient. My credentials are working but there is no body content in my request. What must I do to create the file like this? It works as intended when I try via hurl.it (ie setting my credentials, and setting a body). What I would like is the string "hej" to show in the file body. After getting this to work I intend to use a JSONString. The following code generates an empty file on the server (204 response):
HttpClient httpClient = new DefaultHttpClient();
String encoding = http_username + ":" + http_password;
encoding = Base64.encodeBase64String(encoding.getBytes());
HttpPut httpput = new HttpPut(http_path);
HttpEntity content=null;
try{
content = new StringEntity("hej");
}
catch(UnsupportedEncodingException e){
logger.error("Failed to Encode result");
}
logger.info("executing request " + httpput.getRequestLine());
try {
httpput.setHeader("Authorization", "Basic " + encoding);
//httpput.setHeader("Content-Type", "application/json; charset=utf-8");
httpput.setEntity(content);
HttpResponse response = httpClient.execute(httpput);
Header[] allHeaders = response.getAllHeaders();
for (Header h : allHeaders) {
logger.info(h.getName() + ": " + h.getValue());
}
} catch (Exception e) {
logger.error(e.getMessage());
}
I have tried both setting a content type and not doing it, no difference. What basic thing am I doing wrong?
Turns out that Base64.encodeBase64String appends a newline character at the end of the string, which throws everything off!
String encoding = http_username + ":" + http_password;
encoding = Base64.encodeBase64String(encoding.getBytes());
encoding= encoding.replace("\r\n", ""); //This fixes everything
Wow, that just took me a couple of days to figure out!
I'm trying to use the API from Web Of Knowledge(WoK) to obtain some data. The documentation explain that you have to do POST Requests through HTTPS, sending a XML which contains the queries. But I only get the error 400 form server. (Bad Request)
Here is my code, I found it in Google and I make some fixes for my case.
public static void main(String[] args) throws Exception {
// Get target URL
String strURL = /*Here the Server URL*/;
// Get file to be posted
String strXMLFilename = "src/main/resources/xml/wosdata.xml";
File input = new File(strXMLFilename);
// Prepare HTTP post
PostMethod post = new PostMethod(strURL);
// Request content will be retrieved directly
// from the input stream
// Per default, the request content needs to be buffered
// in order to determine its length.
// Request body buffering can be avoided when
// content length is explicitly specified
post.setRequestEntity(new InputStreamRequestEntity(
new FileInputStream(input), input.length()));
// Specify content type and encoding
// If content encoding is not explicitly specified
// ISO-8859-1 is assumed
post.setRequestHeader(
"Content-type", "text/xml; charset=ISO-8859-1");
// Get HTTP client
HttpClient httpclient = new HttpClient();
// Execute request
try {
int result = httpclient.executeMethod(post);
// Display status code
System.out.println("Response status code: " + result);
// Display response
System.out.println("Response body: ");
System.out.println(post.getResponseBodyAsString());
}catch (Exception e) {
e.printStackTrace();
} finally {
// Release current connection to the connection pool
// once you are done
post.releaseConnection();
}
}
There is something wrong with the XML you are sending. You will have to look at server logs to find out exactly what, as 400 deliberately tells you as little as possible.
You should do it like this. First read the contents of the xml to String and do post using a StringRequestEntity.
// Get file to be posted
String strXMLFilename = "src/main/resources/xml/wosdata.xml";
StringBuilder contents = new StringBuilder();
try {
BufferedReader input = new BufferedReader(new FileReader(new File(strXMLFilename)));
try {
while (( line = input.readLine()) != null){
contents.append(line);
contents.append(System.getProperty("line.separator"));
}
}
finally {
input.close();
}
StringEntity requestEntity = new StringEntity(contents.toString());
post.setEntity(requestEntity);