How to customize whether a request follow the 302 by one okhttpclient - android

Currently, we only have one okhttpclient in our app, by some of our request need to intercept the original reponse and some want to follow the redirect.
we can identify the request whether it needs to redirect, but a okhttp client only has a global param to control this, how can we customize for each request?

You could use a network Interceptor to remove the server response’s Location header. If you need that data you can put it into another header like Rewritten-Location. Either way if the location header is absent the response will not be redirected.

Related

OkHttp POST request set withCredentials to True?

Can't get past Django Rest Framework Token Authorization because I can't set withCredentials=true using OkHttp RequestBuilder. (I'm referring to this https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials)
In javascript using axios.post this works fine. I'm having trouble converting this post request to android using OkHttp request builder.
Request builder only seems to give setter methods for Header and Body of post Request?
Tried reading through OkHttp documentation and I've also tried to send withCredentials=True as a header
Django Rest Framework backend not recognizing the token and not resolving the bearer token to a user.
If no class authenticates, request.user will be set to an instance > of django.contrib.auth.models.AnonymousUser, and request.auth > will be set to None.
I'm going to assume here that withCredentials is a query parameter.
Appending ?withCredentials=true. to the end of the URL will probably get things going for you.
An example in full might look like https://www.example.com?withCredentials=true.
With multiple parameters, it may look like https://www.example.com?withCredentials=true&otherParam=Stuff.

How to get a HEAD of a Retrofit call from an api endpoint that requires field in the request body?

I am trying to examine the headers of a response from an API call made via Retrofit 2.0.2 before actually downloading the content.
My API interface looks like the following:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#HEAD("profiles")
Call<Void> getProfileHeaders(#Field("puids") String puid);
Please note that the API call requires me to specify in the body a field called puids=%{UUID} list of UUIDs in order to return a response.
If I would like to download the data without examining the headers first, I would just call an interface like this:
#Headers({"Accept: application/json", "Origin: http://www.example.com"})
#FormUrlEncoded
#POST("profiles")
Call<String> getProfile(#Field("puids") String puid);
Now the issue is that when I try to use the getProfileHeader() endpoint, I get the following RuntimeException:
java.lang.IllegalArgumentException: #Field parameters can only be used with form encoding. (parameter #1)
In order to use the #Field parameters (as I suppose a POST method would normally would do if required), I would have to explicitly specify that I use #FormUrlEncoded, but I can't make a #HEAD call with that.
I am a bit puzzled how could I achieve what I want and what am I missing?
Basically I would like to know how can I examine a retrofit call's response headers before downloading the actual body, of an API endpoint that requires field parameters?
Cheers!
Ok, I just realized that my confusion originates from a couple of misunderstandings:
#HEAD is an HTTP method to usually verify the hyperlinks validity and the server's response to a GET call. It does not work with POST request and it is theoretically incorrect.
Taken from RFC2616 of the HTTP/1.1 definitions:
The HEAD method is identical to GET except that the server MUST NOT
return a message-body in the response. The metainformation contained
in the HTTP headers in response to a HEAD request SHOULD be identical
to the information sent in response to a GET request. This method can
be used for obtaining metainformation about the entity implied by the
request without transferring the entity-body itself. This method is
often used for testing hypertext links for validity, accessibility,
and recent modification.
The response to a HEAD request MAY be cacheable in the sense that the
information contained in the response MAY be used to update a
previously cached entity from that resource. If the new field values
indicate that the cached entity differs from the current entity (as
would be indicated by a change in Content-Length, Content-MD5, ETag or
Last-Modified), then the cache MUST treat the cache entry as stale.
When making a POST request by definition we already calculated the response server-side and taken the time to download the body in consideration.
One of the function's of the POST method, as defined in RFC2616 is:
Providing a block of data, such as the result of submitting a form, to a data-handling process;
Hence verifying the header in order not do download the body beats the purpose of this.
As mentioned by #Radek above, using interceptors on GET request to modify and/or examine requests on the fly would do the work, but at that point we could also initiate a HEAD method request.
The solution to this problem would be to better align to the standard definitions defined in RFC2616 by making changes on the server-side to instead of returning block of raw data as a POST response, make it to return a resource that would be than called in a GET/HEAD request then. All just refactor the service call to use GET instead of POST.
Okhttp which is used by retrofit has Interceptors which let you modify or examine requests on the fly. Check out the github documentation

Android LoginActivity using standard http request

I'm using LoginActivity template and I'm trying to login to a website with email and password using a standard http request. The site doesn't provide an API so I'm thinking of somehow mirroring the site login to fill the email and password boxes on the page then sending the login request.
Think of logging in to stackoverflow for example by taking the input of an email and password TextView (s) and sending a standard http request to the authentication server with those credentials exactly how it would happen in the browser (same requests and addresses).
I haven't done anything like this before and I have no idea if it's even possible so please forgive any ignorance on my part.
This is done in Android in a similar fashion as in the web browser. Namely, you will send a POST request with proper parameters, let's say a JSON Object for the sake of explaining which contains something like:
{
username: 'myUsername'
password: 'mypass'
}
This will get processed and if your credentials are correct, you will get a response which may contain a variety of data, among which the accessToken (it may be called a slight variation of this).
You are supposed to remember this access token and use it to fetch any other data from the site, because that token is used from there on to authenticate you. I have an API I personally made, and I send the accessToken as a parameter in every request for a resource that is unavailable to the unregistered user.
As for the technical side, I'm using a nifty library called OkHttp for sending the Http requests, and it's quite rewarding and easy to use. Here's a code snippet to see what I'm talking about:
//JSON is a media type for parsing json
//json is a json string containing payload e.g. username and pass like in the example
OkHttpClient httpClient = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = httpClient.newCall(request).execute();
The only thing left to to for you is to properly parse the response. You can find various solutions on this topic, but I personally use 2 approaches, BufferedReader for huge responses using response.body().byteStream(), and plain old String for not-so-large responses using response.body().string().
This is not a short, but very thorough explanation, so feel free to ask for clarification if you do not get some part.
Assuming that you need to log in to sites like StackOverflow from your app with standard http request. That is simply impossible. Because no organizations will allow third party sites/apps handling their users' credentials. If they intend to share their resource with third party most organizations follow this procedure:
First they provide api for you to use.
With that api only you can make users to login i.e you can't handle those credentials
Then they give a token to you corresponding to the user.
With that token you can perform subsequent requests.
If the organization doesn't provide api then they most probably are in situation of not allowing third party sites/apps to access their users' resource.

Android: HttpUrlConnection uses POST to send request bodys (instead of GET)

I'm developing an Android application which communicates with (our own) API. It was meant to use the API in manipulative requests with the request method POST and at not-manipulative requests GET (as it should be in RESTful applications).
To authenticate or add parameters to the request, the HTTP request body has been used (in both GET and POST requests). (YES, it is possible and allowed to add a request body to GET requests per HTTP definition (see e.g. this post)). The post generally says, that it is possible to add a request body, but the server may not use it during the request.
The problem is, that the request method is always set to POST, no mather if I set it to GET anywhere during the connection configuration, even if the getRequestMethod does return GET after setting it to GET via setRequestMethod("GET").
The android application uses the HttpsURLConnection (which is an extended class from HttpURLConnection, so it should behave similary).
By calling these methods, a request body will be attended:
https.setDoInput(true);
OutputStream os = https.getOutputStream();
os.write(outputInBytes);
os.close();
And by calling https.setRequestMethod("GET"), the request method should be set to GET.
After a little investigating, the line OutputStream os = https.getOutputStream(); sets the request method to POST, afterwards I set it to GET again and it remains GET till the end of the connection (as returned by https.getRequestMethod())
But in the end the server receives the request with the request method POST.
So my specific questions are:
Is there a possible workaround / solution for this problem?
Is it really that bad to add a request body to a GET request?
Currently I have just set all requests to POST, so there is no problem with it (and I wouldn't have a problem to leave it this way, but for several reasons I would like to know for sure that there is no other way to fix this problem)
Edit: The documentation of the getOutputStream() method says:
The default request method changes to "POST" when this method is called.
By default the HttpURLConnection is a GET Method (getDoInput() is true by default).
If you use setDoOutput(true) it will become a POST method.
If you need another method (PUT, DELETE, etc...) then you will use setRequestMethod(string).
And of course you have to select the method you want before the connect() method

How to get and make request with Cookies

I tried to make request using fetch API, but when I do console.log(response.headers.get("Set-Cookie")) I got undefined.
Is there any way to do requests with cookie persisting across requests?
Set-Cookie can't be read programmatically. Check this out => github/fetch#receiving-cookies
Like with XMLHttpRequest, the Set-Cookie response header returned from the server is a forbidden header name and therefore can't be programatically read with response.headers.get(). Instead, it's the browser's responsibility to handle new cookies being set (if applicable to the current URL). Unless they are HTTP-only, new cookies will be available through document.cookie.

Categories

Resources