For Android Apps, is it possible to set different caching times for different urls using OkHttpClient?
for example, I have two urls:
http://www.example.com/getcountries.php
http://www.example.com/getnews.php
for the first url, i would like to set caching for 365 days:
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.maxStale(365, TimeUnit.DAYS)
.build())
.url("http://www.example.com/getcountries.php")
.build();
for the second url, i would like to set caching for 3 minutes:
Request request = new Request.Builder()
.cacheControl(new CacheControl.Builder()
.maxStale(3, TimeUnit.MINUTES)
.build())
.url("http://www.example.com/getnews.php")
.build();
will it work? (with caching in place, debugging is difficult).
Thanks for your support.
This will work but I think you want max-age and not max-stale. A cached response written at time a will be served until time b, a time that is derived from the response’s headers. The value you specify in max-stale is added to b to extend the lifetime of the cached response. The value you specify in max-age is added to a to constrain how long the cached response is valid.
https://square.github.io/okhttp/4.x/okhttp/okhttp3/-cache-control/-builder/
Related
I am trying to process Http GET request with parameters using Okhttp in Android Kotlin.
As there is no GET resource found on documentation and other internet resources didn't work, how can I set GET request in Okhttp with pre defined parameters.
Builder code with lack of GET method
val parameter = "{\"phone\": \"$phone\"}"
val request = Request.Builder().url(weburl)
.header("User-Agent", "OkHttp Headers.java")
.addHeader("Content-Type", "application/json")
.addHeader("Accept", "application/json")
//.method("GET",parameter.toRequestBody())
.build()
Output result
enter image description here
If you want to send the phone as a query parameter, you should add it to the request URL, not to the request body. You don't need to specify the method: GET is the default. By the way, you can get rid of the Content-type header (GET requests, usually, have no content):
val url = weburl.toHttpUrl().newBuilder()
.addQueryParameter("phone", phone)
.build()
val request = Request.Builder().url(url)
.header("User-Agent", "OkHttp Headers.java")
.header("Accept", "application/json")
.build()
If your requirement is to send a GET request with a request body, than you are out of luck I'm afraid: OkHttp does not support it. Anyways, most likely, it's not what you want (unless you are calling Elasticsearch API...)
I have a DJANGO REST server on my personal network that is set up to get and receive JSON strings to update "statuses" for a project I'm working on. I can GET the information down into my Android application just fine but when I try to PUT information up to the server, I get the error:
Bad Request: /api/users/1/
[28/Oct/2019 21:23:23] "PUT /api/users/1/ HTTP/1.1" 400 107
I think it's the app because I can successfully do a PUT request via Windows Powershell, but it doesn't work on the Android app. Here is the code using the OKHTTP class:
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
String content = String.format("{'status':%s}", selectedStatus);
RequestBody body = RequestBody.create(JSON, content);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(IPAddress + "api/users/" + currentUserID + "/")
.addHeader("Content-Type", "application/json")
.put(body) //PUT
.build();
client.newCall(request).execute();
I have tried using the standard HttpURLConnection class, which is what I did for the GET method, but I don't even get a response from the server when I do that. I've tried about a dozen ways to PUT something to the server, but nothing has worked. Any help achieving this goal would be appreciated. Thanks.
For anyone looking at this later, I found the issue. It turns out that in the Windows Powershell, you can use single quotes in the JSON string, but you NEED to use double quotes with the OKHTTP methods. Thus, I changed:
String content = String.format("{'status':%s}", selectedStatus);
to:
String content = String.format("{\"status\":%s}", selectedStatus);
and everything went through perfectly. Hope this helps someone.
I'm trying to send a json post request to some API which in response sends a binary file back.
I'm doing well in Postman:
Header:
Body and result:
And I get the following code from Code section in Postman for Java/OKHTTP
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\r\n \"Text\":\"Hello\",\r\n \"APIKey\":\"MY_API_KEY\",\r\n \"Speaker\":\"Female1\",\r\n \"Format\":\"mp3/32/m\",\r\n \"Quality\":\"quality/normal\"\r\n}");
Request request = new Request.Builder()
.url("http://url/CloudService/ReadText")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("cache-control", "no-cache")
.addHeader("postman-token", "0a1ce7c9-7a95-a2b9-7cde-8a7e6ce58386")
.build();
Response response = client.newCall(request).execute();
But when I use the above code in android it fails, I'm sure that I got Internet permission and the code is executed within an AsyncTask.
I'm not asking about the API or how to send json Post request to some API and get a binary file in response. I've used client.newCall(request).enqueue(new Callback(){//stuff here}); but none works. In response I got a 307 status code (instead of 200 in Postman) and no binary data at all. The API is very unclear and said nothing about the failure and I'm still working on that.
All I'm asking is that does Postman generates equivalent code for OkHttp correctly? and if not what is your suggestion for equivalent of this request in Java/OkHttp?
Just to provide another example, the following is also a working Python requests script to do the same job:
url = 'http://url/CloudService/ReadText'
api_key = 'MY_API_KEY'
body = {
'Text': 'Hello',
'Speaker': 'Female1',
'Format': 'mp3/32/m',
'Quality': 'quality/normal',
'APIKey': api_key
}
header = {
'Content-type': 'application/json'
}
r = requests.post(url, data=json.dumps(body), headers=header)
So after 3 days I found the problem, the server API did not mention that the URL endpoint must be ended with an / and even in their sample code they didn't use one.
It seems that both Postman and Python requests use an / at the end of URL in case of need, but Postman at least does not mention that in the generated equivalent code. Also OkHttp does not operate in the same manner.
However using a trailing / solved the problem.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am having an issue in my app, I need to be able to see or log the full network request so that I can see exactly what parameters are being posted to my server with what headers, currently it only shows me the URL, is there a way of doing this in android studio or is there some code I can write to display this data?
To further explain things seems the terms network request, parameters and headers are confusing people, I use the google volley library for all my htpp requests; GET, POST, PUT etc. Now when posting data to a URL or getting data via a specific URL i need to be able to confirm that the right parameters and headers are being sent to the server.
If you are talking about testing the parameters for your API, you probably looking for REST clients like:
Postman
Rest Client
to validate services. But before that, you should have proper documentation of all the web services.
Solution:
In Android Studio, to debug your code, simply place breakpoints on the code and press debug button to execute
You can place breakpoint by clicking on left of each line where breakpoint is shown.
Also check this tutorial:
Simple Debugging in Android Studio and follow further videos for proper debugging.
I would recommend you to use OkHttp for making all network calls. OkHttp provides Interceptors which will serve your exact purpose.
Defining an interceptor:
class LoggingInterceptor implements Interceptor {
#Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
long t1 = System.nanoTime();
logger.info(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
HttpUrl url = request.url(); // url of the request.
Headers reqHeaders = request.headers(); // Here you are able to access headers which are being sent with the request.
RequestBody body = request.body(); // provides body of request, which you can inspect to see what is being sent.
Response response = chain.proceed(request);
long t2 = System.nanoTime();
logger.info(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (t2 - t1) / 1e6d, response.headers()));
Headers resHeaders = response.headers(); // Headers received in the response.
return response;
}
}
Using it to make network calls:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();
Request request = new Request.Builder()
.url("http://www.publicobject.com/helloworld.txt")
.header("User-Agent", "OkHttp Example")
.build();
Response response = client.newCall(request).execute();
response.body().close();
Explore the Interceptors for more customization.
I am trying to use DELETE method of HttpMethod. The code that I am using for that is
response = restTemplate.exchange(url, HttpMethod.DELETE, requestEntity, Response.class);
I am also using JacksonJson for mapping json. The delete functionality returns the json which should be mapped to Response class. But calling the above line doesn't works and gives internal server error with 500 as response code. But, the same API does work with RESTClient in the browser so I guess there is something that I am not doing correctly.
After doing some more research it seems that DELETE method doesn't supports request body. As we had the control over REST API we have changed the request body to be added as parameters. After doing this change the request is working properly.
Hope it helps someone.
A little late to the party I'd like to chime in here as well (document my solution for posterity)
I'm too using spring's rest template, also trying to perform a delete request with a payload AND i'd also like to be able to get the response code from the server side
Disclaimer: I'm on Java 7
My solution is also based on a post here on SO, basically you initially declare a POST request and add a http header to override the request method:
RestTemplate tpl = new RestTemplate();
/*
* http://bugs.java.com/view_bug.do?bug_id=7157360
* As long as we are using java 7 we cannot expect output for delete
* */
HttpHeaders headers = new HttpHeaders();
headers.add("X-HTTP-Method-Override", "DELETE");
HttpEntity<Collection<String>> request = new HttpEntity<Collection<String>>(payload, headers);
ResponseEntity<String> exchange = tpl.exchange(uri, HttpMethod.POST, request, String.class);