I am using the Dirble Api and I am trying to test it to even get some results back but I think I might be doing it the wrong way. This is how I have been trying:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://api.dirble.com/v2/songs?token={MY_PROVIDED_ACCESS_TOKEN}")
.build();
try {
Response response = client.newCall(request).execute();
System.out.println("Test " + response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
But I keep getting the error:
{"error":"Unauthorized. Invalid or expired token."}
I assumed that this meant the tokens they provided me are just not functioning. So I generated a new one and same result.
This is there guidelines:
https://dirble.com/api-doc#introduction
I cant see anything I am doing wrong but since I am a novice in http requests, I would like to check there is nothing wrong with how I am doing it before I contact them to say the my access codes aren't working.
Related
In my app I make a simple get request via okhttp (this is simplified a bit, but you get the gist)
Request request = new Request.Builder()
.url(url)
.get()
.build();
try {
Response response = getOkHttpClient().newCall(request).execute();
if (response.isSuccessful()) {
return response.body().string();
} else {
return "";
}
}
catch (Exception e) {
Log.e(TAG, "Exception: ", e);
return "";
}
The url is a http url.
The api is my clients api and the call works fine outside their office network, unfortunately it does not work inside their office network.
Inside their network the response is 200 but there is no data attached to it (response.body().string() returns an empty string), however the request works just fine in the browser inside their network.
So what could the difference be between making the request inside their network from the app, versus inside their network in the browser? Could I spoof a browser user agent and that would fix it?
We do not know what was causing this, apparently their IT department made some sort of unrelated change to the network and now it works.
I am working on an Android app in which a log in post request is made to a webservice. The request returns a cookie which expires in 20 minutes.
Using okhttp3 and this PersistentCookieStore library, I got the cookie to be stored and subsequently added it as request header to access authentication-required get requests (e.g. personal information that are non-public).
The code goes this way,
CookieJar myCookieJar = new PersistentCookieJar(new SetCookieCache(),
new SharedPrefsCookiePersistor(this));
OkHttpClient client = new OkHttpClient.Builder().cookieJar(HttpRequests.cookieJar).build();
I then call a method like this inside an (after I have gone through another log in Async task to get the cookie) Async task to perform a get request that requires authentication,
public static String PostReq(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.addHeader("Cookie", "key=value")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
catch(Exception e){
}
}
The .addHeader("Cookie", "key=value") adds the cookie to the header to tell the webservice that I am authenticated.
Here comes my difficulty. Since the cookie expires after 20 minutes, I would like to be able to access the cookie itself to check for the expiration time and possibly redirect the user to the log in activity by calling the method,
myCookie.expiresAt()
and comparing it to
System.currentTimeMillis()
I tried to look at the PersistentCookieStore codes and found that it uses a SharedPreference with the key "CookiePersistence". I looked inside this file while my emulator was running the app and found it to be empty however.
How would I be able to access this cookie that I have obtained? Much thanks for any advice to be given.
OK, this is old, but I was facing the same problem, and here is how I fixed it.
Hold a reference to your SetCookieCache used to instantiate your CookieJar:
SetCookieCache cookieCache = new SetCookieCache();
CookieJar myCookieJar = new PersistentCookieJar(
cookieCache,
new SharedPrefsCookiePersistor(this)
);
Then use this to find your cookie and check it:
for (Cookie cookie : cookieCache) {
if (cookie.name().equals("cookie_name") && cookie.persistent()) {
//cookie is still good
break;
}
}
Or use cookie.expiresAt() to do your thing.
I want to change the read timeout on OkHttp client using retrofit for one api call. To be clear, I have one end point that can take very long, I need to increase it's timeout and only the timeout for that one api call. Is there a way I can do this through annotations? Is there a way I can do this without changing the timeouts for the rest of the app?
I'm facing a similar situation. I solve my problem providing two Api instances in my ApiModule, each one with your own OkHttpClient. Use #Named to identify each one.
I tried to avoid providing two instances only for a timeout configuration, seems a little strange for me, but since my API instance is a singleton (for performance), I could not see other solution.
You can actually do a per call configuration
Copy the default builder and make another client
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
Request request = new Request.Builder()
.url("http://blah_blah_api.com/") // This URL is served with a 1 second delay.
.build();
try {
// Copy to customize OkHttp for this request.
OkHttpClient copy = client.newBuilder()
.readTimeout(500, TimeUnit.MILLISECONDS)
.build();
Response response = copy.newCall(request).execute();
System.out.println("Response 1 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 1 failed: " + e);
}
try {
// Copy to customize OkHttp for this request.
OkHttpClient copy = client.newBuilder()
.readTimeout(3000, TimeUnit.MILLISECONDS)
.build();
Response response = copy.newCall(request).execute();
System.out.println("Response 2 succeeded: " + response);
} catch (IOException e) {
System.out.println("Response 2 failed: " + e);
}
}
I am attempting to call a put method on my server using OkHttp from an Android application.
This is the api method signature:
public void Put(int userId, string regId)
{
}
This is the Android code to call the above method:
private boolean SendGCMRegIdToServer(String registrationId, Integer userId) throws IOException {
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host(serverApiHost)
.addPathSegment("AppDashboard")
.addPathSegment("api")
.addPathSegment("GCM/")
.build();
MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String json = "{'userId':" + userId + ","
+ "'regId':'" + registrationId + "'"
+ "}";
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.put(requestBody)
.build();
//this should post the data to my server
Response response = client.newCall(request).execute();
if(response.code() == 400)
return false;
return true;
}
Now the problem is I am getting the error code 405 in the response saying Method not allowed, but I cannot see where the problem is because I can successfully call the method using Postman on the server itself as below:
http://localhost/AppDashboard/api/GCM?userId=5®Id=123
I'm thinking it may have something to do with an integer or string being passed incorrectly in the JSON string, but cannot see why this isn't working.
i had the same problem and server was returning 405 . after some search i realized that is a configuration problem on IIS that does not let put requests. so there is no problem in android code and you should config your server to let this kind of requests.
see this , this and this
Ok thanks for replies guys but seems I was getting a little confused between the two methods I was using to pass the params to my API.
Here's what I did:
changed the signature of the method to post with a param [FromBody] as a Model (only supports one paramater)...
public void Post([FromBody]UserGcmRegIdModel model)
{
}
I was then able to change my method call to the following using a nicer JSONBuilder and using .post in the request builder rather than .put
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("UserId", userId);
jsonObject.put("RegId", registrationId);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObject.toString();
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
I still don't know if there is a problem with put() methods on IIS but using a post in my case was absolutely fine so I'm going with that...
I see two different approaches in your REST api calls. In the one of OkHttp you send a PUT method with a JSON object serialized, and in POSTMAN you send a PUT (although I guess you do a GET) request with the parameters within the URL, I mean not in JSON body structure.
Anyway, HTTP 405 is telling you that your backend does not support the PUT method, and probably it's expecting a POST method with the "X-HTTP-Method-Override:PUT" HTTP header since POST is more standard method in REST than PUT.
What would I do is check your POSTMAN request carefully and adjust the one of Android to be the same method, parameters and headers, not more.
Answer Update (as question has been updated)
Of course there is a problem with that verb, as I said above IIS handles only the standard methods and PUT is not one of those. You have three choices:
Change your PUT to POST.
Use POST with X-HTTP-Method-Override to PUT. (reference)
Modify IIS config to support non standard REST methods. I
personally wouldn't suggest the 3rd one, since it's attached to the
backend config (e.g. imagine you change IIS to NancyFX).
I am trying to do a http post to my server to check if the login credentials are valid with help of this tutorial. I need to make a request to my server but i have to add Authorization, i get the string with the function getB64Auth from this answer. the function logs the right variable, (the same as i use with postman). But for some reason my program stops running if i run my code. I already tried adding the code from the comments but it didn't help.
What am i doing wrong?
private String getB64Auth (String login, String pass) {
String source=login+":"+pass;
String ret="Basic "+Base64.encodeToString(source.getBytes(),Base64.URL_SAFE| Base64.NO_WRAP);
Log.d("authy", ret);
return ret;
}
/** Called when the user clicks the Login button */
public void login(View view) {
// Getting username and password
EditText userText = (EditText) findViewById(R.id.inputLoginUsername);
EditText passText = (EditText) findViewById(R.id.inputLoginPassword);
String usernameInput = userText.getText().toString();
String passwordInput = passText.getText().toString();
String authorizationString = getB64Auth(usernameInput,passwordInput );
// Do something in response to button
// 1. Create an object of HttpClient
HttpClient httpClient = new DefaultHttpClient();
// 2. Create an object of HttpPost
// I have my real server name down here
HttpPost httpPost = new HttpPost("https://myservername.com/login");
// 3. Add POST parameters
httpPost.setHeader("Authorization", authorizationString);
// 5. Finally making an HTTP POST request
try {
HttpResponse response = httpClient.execute(httpPost);
Log.d("win", "win1");
// write response to log
Log.d("Http Post Response:", response.toString());
} catch (ClientProtocolException e) {
Log.d("fail", "Fail 3");
// Log exception
e.printStackTrace();
} catch (IOException e) {
Log.d("fail", "Fail 4");
// Log exception
e.printStackTrace();
}
}
When i run my code the app stops working, i can find the log authy but i cant find any fail succes logs.
The things i have changed in the example are step 3.
ive added my authorization there.
and removed step 4 cause i dont need it.
Working postman example, with the same request i want to make in android.
You can see I get a response, and only set Authorization on my request.
I cant find any decent post/authorization tutorials so i hope i'm looking at the right direction.
It's an android 4.* project
Just a few suggestions about such issues:
Check permissions (INTERNET is the one you would need)
Applications like Charles / Fiddler let you sniff the Http traffic from the device so you could investigate what is being sent
If the application is crashing - check the LogCat messages (for example it could contain a message explaining which permission is missing)
Regarding this message:
The application may be doing too much work on its main thread.
This usually means that you are doing some heavy operations in the main thread - for example parsing the Json from the Http response. Generally you'd like to do all these operations in a background thread and use the main one to update the UI only.