When I use cURL, after authorization, I receive Set-Cookie: JSESSIONID=xxx; Path=/; HttpOnly, but with Retrofit, despite authorization passes, I can't get this either in LogCat nor by response.getHeaders() in success callback method.
What am I doing wrong here?
cURL log
wojciechko#Ubuntu ~> curl --data "login=wkr&password=wkr" 192.168.1.2:8080/login -v
* Hostname was NOT found in DNS cache
* Trying 192.168.1.2...
* Connected to 192.168.1.2 (192.168.1.2) port 8080 (#0)
> POST /login HTTP/1.1
> User-Agent: curl/7.35.0
> Host: 192.168.1.2:8080
> Accept: */*
> Content-Length: 22
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 22 out of 22 bytes
< HTTP/1.1 302 Found
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Set-Cookie: JSESSIONID=C6F875A1176AB9D373FB9D5BC7A6E5DF; Path=/; HttpOnly
< Location: http://192.168.1.2:8080/
< Content-Length: 0
< Date: Mon, 01 Sep 2014 13:33:02 GMT
<
* Connection #0 to host 192.168.1.2 left intact
Retrofit log
myclient D/Retrofit﹕ ---> HTTP POST http://192.168.1.2:8080/login
myclient D/Retrofit﹕ Content-Type: application/x-www-form-urlencoded; charset=UTF-8
myclient D/Retrofit﹕ Content-Length: 22
myclient D/Retrofit﹕ login=wkr&password=wkr
myclient D/Retrofit﹕ ---> END HTTP (22-byte body)
myclient D/Retrofit﹕ <--- HTTP 200 http://192.168.1.2:8080/login (187ms)
myclient D/Retrofit﹕ : HTTP/1.1 200 OK
myclient D/Retrofit﹕ Cache-Control: no-cache, no-store, max-age=0, must-revalidate
myclient D/Retrofit﹕ Content-Language: en-US
myclient D/Retrofit﹕ Content-Length: 3066
myclient D/Retrofit﹕ Content-Type: text/html;charset=utf-8
myclient D/Retrofit﹕ Date: Mon, 01 Sep 2014 14:00:20 GMT
myclient D/Retrofit﹕ Expires: 0
myclient D/Retrofit﹕ Last-Modified: Mon, 16 Jun 2014 14:12:14 GMT
myclient D/Retrofit﹕ OkHttp-Received-Millis: 1409580018720
myclient D/Retrofit﹕ OkHttp-Response-Source: NETWORK 200
myclient D/Retrofit﹕ OkHttp-Selected-Protocol: http/1.1
myclient D/Retrofit﹕ OkHttp-Sent-Millis: 1409580018711
myclient D/Retrofit﹕ Pragma: no-cache
myclient D/Retrofit﹕ Server: Apache-Coyote/1.1
myclient D/Retrofit﹕ X-Content-Type-Options: nosniff
myclient D/Retrofit﹕ X-Frame-Options: DENY
myclient D/Retrofit﹕ X-XSS-Protection: 1; mode=block
Retrofit usage:
cookieManager = new CookieManager();
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieHandler.setDefault(cookieManager);
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(MyClient.API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setClient(new OkClient())
.build();
MyClient.MyApi api = restAdapter.create(MyClient.MyApi.class);
api.login(login, password, new Callback<Response>() {
#Override
public void success(Response loginResponse, Response response) {
Toast.makeText(getApplicationContext(), "SUCCESS!", Toast.LENGTH_SHORT).show();
}
#Override
public void failure(RetrofitError error) {
Toast.makeText(getApplicationContext(), "NOPE!", Toast.LENGTH_SHORT).show();
}
});
/******************/
public class MyClient {
public static final String API_URL = "http://192.168.1.2:8080";
interface MyApi {
#FormUrlEncoded
#POST("/login")
void login(#Field("login") String login, #Field("password") String password, Callback<Response> callback);
}
}
You need to set a logger to your rest adapter.
final RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(MyClient.API_URL)
.setLogLevel(RestAdapter.LogLevel.FULL)
.setLog(new RestAdapter.Log() {
#Override
public void log(String s) {
Log.d("RestAdapter", s);
}
})
.setClient(new OkClient())
.build();
Related
I was trying to add refresh token interceptor to http client
public class AuthInterceptor implements Interceptor {
private Disposable disposable;
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
// if (response.code() == HttpURLConnection.HTTP_UNAUTHORIZED) {
//
// synchronized (chain) {
//
//
// RefreshTokenApi refreshTokenApi = new RefreshTokenApi();
// disposable = refreshTokenApi.call().subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(
// (tokenResponse, throwable) -> {
//
// PreferencesWrapperImpl.SINGLETON.putStringForKey(tokenResponse.getResponse().header(Constants.AUTH_TOKEN), Constants.PreferenceKey.AUTH_TOKEN_KEY);
// Log.e("throwable", throwable.getMessage());
//
// });
//
//
// Request newRequest = request.newBuilder()
// .removeHeader(Constants.AUTH_TOKEN)
// .addHeader(Constants.AUTH_TOKEN, PreferencesWrapperImpl.SINGLETON.getStringForKey(Constants.PreferenceKey.AUTH_TOKEN_KEY, null))
// .build();
// response = chain.proceed(newRequest);
// }
// }
return response;
}
}
then i discovered that the request proceed many times so i thought that maybe my synchronized logic wrong and that is what caused request to occur multiple time so i commented the synchronized logic but actually the request still occur many times
and here is my logcat
D/OkHttp: --> POST http://134.209.26.2:88/api/common/version/check http/1.1
D/OkHttp:
--> POST http://134.209.26.2:88/api/common/version/check http/1.1
Content-Type: application/json; charset=utf-8
Content-Length: 35
D/OkHttp: Content-Type: application/json; charset=utf-8
Content-Length: 35
D/OkHttp: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMzQuMjA5LjI2LjI6ODhcL2FwaVwvc3BcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNTg3NjQxMjY5LCJleHAiOjE1ODc2NzcyNjksIm5iZiI6MTU4NzY0MTI2OSwianRpIjoiZThXQUpIenVSamdGOGpORyIsInN1YiI6MTMsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEiLCJwaWQiOjUsInR5cGUiOjF9.sA3-Ga9YI-4AyDZV_KIuOukONu3Abblq6ge8JbaMgp8
x-lang-code: en-us
D/OkHttp: Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC8xMzQuMjA5LjI2LjI6ODhcL2FwaVwvc3BcL2F1dGhcL2xvZ2luIiwiaWF0IjoxNTg3NjQxMjY5LCJleHAiOjE1ODc2NzcyNjksIm5iZiI6MTU4NzY0MTI2OSwianRpIjoiZThXQUpIenVSamdGOGpORyIsInN1YiI6MTMsInBydiI6Ijg3ZTBhZjFlZjlmZDE1ODEyZmRlYzk3MTUzYTE0ZTBiMDQ3NTQ2YWEiLCJwaWQiOjUsInR5cGUiOjF9.sA3-Ga9YI-4AyDZV_KIuOukONu3Abblq6ge8JbaMgp8
D/OkHttp: x-user-type: 1
D/OkHttp: x-lang-code: en-us
x-user-type: 1
D/OkHttp: {"user_platform":1,"version":"1.0"}
--> END POST (35-byte body)
D/OkHttp: {"user_platform":1,"version":"1.0"}
--> END POST (35-byte body)
D/OkHttp: <-- 200 OK http://134.209.26.2:88/api/common/version/check (446ms)
D/OkHttp: Date: Sat, 25 Apr 2020 22:01:29 GMT
Server: Apache/2.4.29 (Unix) OpenSSL/1.0.2n PHP/7.2.1 mod_perl/2.0.8-dev Perl/v5.16.3
D/OkHttp: <-- 200 OK http://134.209.26.2:88/api/common/version/check (447ms)
D/OkHttp: Vary: Authorization
D/OkHttp: Date: Sat, 25 Apr 2020 22:01:29 GMT
D/OkHttp: X-Powered-By: PHP/7.2.1
D/OkHttp: Server: Apache/2.4.29 (Unix) OpenSSL/1.0.2n PHP/7.2.1 mod_perl/2.0.8-dev Perl/v5.16.3
D/OkHttp: Cache-Control: no-cache, private
D/OkHttp: Vary: Authorization
D/OkHttp: Content-Length: 46
D/OkHttp: X-Powered-By: PHP/7.2.1
D/OkHttp: Keep-Alive: timeout=5, max=100
D/OkHttp: Cache-Control: no-cache, private
D/OkHttp: Connection: Keep-Alive
D/OkHttp: Content-Length: 46
D/OkHttp: Content-Type: application/json
D/OkHttp: Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json
{"data":{"status":1,"min":null,"latest":null}}
D/OkHttp: {"data":{"status":1,"min":null,"latest":null}}
<-- END HTTP (46-byte body)
D/OkHttp: <-- END HTTP (46-byte body)
E/APP_UPDATES: onSuccess
i use logging interceptor to so as you see the first request of app which is app updates post many times
I am creating new sample app with dagger, Rx, MVP and retrofit2. I am new in retrofit .For loginActivity i have send parameters as json string to web service.If the user exist and has permission, service return true in body and in header send Cookie:
D/Payesh: --> POST http://test.com/Authentication.svc/json/Login
D/Payesh: Content-Type: application/json; charset=utf-8
D/Payesh: Content-Length: 183
D/Payesh: {"username":"****","password":"***","customCredential":"****","isPersistent":false}
D/Payesh: --> END POST (183-byte body)
/data/data/com.groot.payesh/cache/okhttp_cache/journal.tmp
D/Payesh: <-- 200 OK http://test.com/Authentication.svc/json/Login (2111ms)
D/Payesh: Cache-Control: private
D/Payesh: Content-Type: application/json; charset=utf-8
D/Payesh: Server: Microsoft-IIS/8.5
D/Payesh: Set-Cookie: ASP.NET_SessionId=3pi1nyrozbjwagw543Wsck4; path=/
D/Payesh: Set-Cookie: .ASPXAUTH=EA9127C4A3002F1D5EA5AADC279....; expires=Tue, 27-Mar-2018 15:17:22 GMT; path=/
D/Payesh: X-Frame-Options: SAMEORIGION
D/Payesh: Access-Control-Allow-Origin: test.com
D/Payesh: Access-Control-Allow-Headers: Content-Type, Accept
D/Payesh: Access-Control-Allow-Methods: GET, POST
D/Payesh: Access-Control-Max-Age: 1728000
D/Payesh: Access-Control-Allow-Credentials: true
D/Payesh: Date: Mon, 26 Mar 2018 15:17:22 GMT
D/Payesh: Content-Length: 4
D/Payesh: true
D/Payesh: <-- END HTTP (4-byte body)
this is my ApiService:
#POST(UrlManager.AUTHENTICATION+"Login")
Observable<String> getAuthentication(#Body RequestBody params);
this method return a string and i received True when i run my app an get user and pass.
this is my observer method:
public DisposableObserver<String> observer() {
return new DisposableObserver<String>() {
#Override
public void onNext(String responseBody) {
Log.i("--->", "onNext: " + responseBody);
}...
I need this line in header:
Set-Cookie: .ASPXAUTH=EA9127C4A3002F1D5EA5AADC279....; expires=Tue, 27-Mar-2018 15:17:22 GMT; path=/
this is my Interceptor that initialized with dagger from My Application Class:
#AppScope
#Provides
public HttpLoggingInterceptor httpLoggingInterceptor() {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
#Override
public void log(String message) {
Timber.d(message);
}
});
return logging.setLevel(HttpLoggingInterceptor.Level.BODY);
}
How can i get Set-Cookie value?
I have a problem with retrofit 2. I'm sending some data to Microsoft EAS server but a response is received after 20 sec. Why I know that this is a retrofit problem? Because without retrofit it is working correctly.
my logs:
D/OkHttp: --> POST https://{my_host}/Microsoft-Server-ActiveSync?Cmd=Provision&User={myuser}&DeviceId=837bc6c5690b40b98ab55f7a2231e50c&DeviceType={mydevicetype} http/1.1
D/OkHttp: Content-Type: application/vnd.ms-sync.wbxml
D/OkHttp: Content-Length: 456
D/OkHttp: Authorization: Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
D/OkHttp: MS-ASProtocolVersion: 14.1
D/OkHttp: Connection: keep-alive
D/OkHttp: User-Agent: MyUserAgent
D/OkHttp: X-MS-PolicyKey: 0
D/OkHttp: [3,1,106,0,0,14,[...more here...],88,77,76,0,1,1,1,1] // <--- body
D/OkHttp: --> END POST (456-byte body)
after 20 sec (it seems like I receive response after 20 + normal receive time - in this case: 20596ms):
D/OkHttp: <-- 200 OK https://{my_host}/Microsoft-Server-ActiveSync?Cmd=Provision&User={myuser}&DeviceId=837bc6c5690b40b98ab55f7a2231e50c&DeviceType={mydevicetype} (20596ms)
D/OkHttp: Content-Type: application/vnd.ms-sync.wbxml
D/OkHttp: request-id: {request_id}
D/OkHttp: Set-Cookie: {cookie_data}
D/OkHttp: X-CalculatedBETarget: {target}.local
D/OkHttp: X-MS-BackOffDuration: L/-470
D/OkHttp: X-DiagInfo: EXCHANGEHA
D/OkHttp: X-BEServer: EXCHANGEHA
D/OkHttp: Set-Cookie: {cookie_data}
D/OkHttp: X-FEServer: EX01
D/OkHttp: Date: Fri, 07 Oct 2016 10:30:08 GMT
D/OkHttp: <-- END HTTP (binary 15-byte body omitted)
If I'm requesting it without retrofit, it sends me response immiedetaly.
My code:
Init:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(chain -> {
Request original = chain.request();
Request.Builder requestBuilder = original.newBuilder()
.addHeader("Authorization", getAuth(account))
.addHeader("MS-ASProtocolVersion", getProtocolVersion())
.addHeader("Connection", getConnectionType())
.addHeader("User-Agent", getUserAgent())
.addHeader("X-MS-PolicyKey", getPolicyKey());
Request request = requestBuilder.build();
return chain.proceed(request);
});
if (EasConfig.isDebug()) {
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logging);
}
httpClient.readTimeout(30, TimeUnit.SECONDS);
httpClient.writeTimeout(30, TimeUnit.SECONDS);
OkHttpClient client = httpClient.build();
retrofit = new Retrofit.Builder()
.baseUrl(getBaseUrl(account))
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
Call:
ActiveSyncService service = retrofit.create(ActiveSyncService.class);
service.getData(getContentType(), command, getUser(account), getDeviceId(), getUserAgent(), serializer.toByteArray());
Endpoint:
#POST("Microsoft-Server-ActiveSync")
Call<ResponseBody> getData(#Header("Content-Type") String contentType, // <--- it has to be here -- it's not woking if I set it in incerteptor (don't know why)
#Query("Cmd") String command,
#Query("User") String user,
#Query("DeviceId") String deviceId,
#Query("DeviceType") String deviceType,
#Body byte[] data);
I have a problem with retrofit in android when I try to get the access token it doesn't work at all and I get "unauthorized 401" but using DHC byRESTlet I can get the access token without any problem.
This is the interface I use :
public interface TokenService {
#Headers({
"Content-Type : application/x-www-form-urlencoded",
"Authorization : Basic dGVzdDo="
})
#FormUrlEncoded
#POST("/oauth/token")
Call<TokenEntity> getAccessToken(#Field("username") String username,
#Field("password") String password ,
#Field("grant_type") String grantType );
}
and this is log error :
D/OkHttp: --> POST http://192.168.1.5:8080/oauth/token http/1.1
D/OkHttp: Content-Type: application/x-www-form-urlencoded
D/OkHttp: Content-Length: 52
D/OkHttp: Content-Type : application/x-www-form-urlencoded
D/OkHttp: Authorization : Basic dGVzdDo=
D/OkHttp: username=abcd&password=aqwzsx123&grant_type=password
D/OkHttp: --> END POST (52-byte body)
D/OkHttp: <-- 401 Unauthorized http://192.168.1.5:8080/oauth/token (21ms)
D/OkHttp: Server: Apache-Coyote/1.1
D/OkHttp: X-Content-Type-Options: nosniff
D/OkHttp: X-XSS-Protection: 1; mode=block
D/OkHttp: Cache-Control: no-cache, no-store, max-age=0, must-revalidate
D/OkHttp: Pragma: no-cache
D/OkHttp: Expires: 0
D/OkHttp: X-Frame-Options: DENY
D/OkHttp: Cache-Control: no-store
D/OkHttp: Pragma: no-cache
D/OkHttp: WWW-Authenticate: Bearer realm="oauth", error="unauthorized", error_description="Full authentication is required to access this resource"
D/OkHttp: Content-Type: application/json;charset=UTF-8
D/OkHttp: Transfer-Encoding: chunked
D/OkHttp: Date: Fri, 06 May 2016 07:44:03 GMT
D/OkHttp: OkHttp-Sent-Millis: 1462520643079
D/OkHttp: OkHttp-Received-Millis: 1462520643087
D/OkHttp: {"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
<-- END HTTP (102-byte body)
ponse{protocol=http/1.1, code=401, message=Unauthorized, url=http://192.168.1.5:8080/oauth/token}
It does not seem like retrofit problem.
You may try using #Body instead of fields, try making class:
class Request {
String username;
...
}
and then
Call<TokenEntity> getAccessToken(#Body Request request);
What the title says. The problem only happens when using Retrofit. Uploads using Postman or Android's HTTPURLConnection+DataOutputStream work fine and return the json body from the REST api.
Here's a working request/response log from Postman:
Remote Address: xxx.xxx.xxx.xxx:80 Request URL: [ --- secret --- ]
Request Method:POST Status Code:200 OK Response Headers (8) Request
Headers view source Accept:*/* Accept-Encoding:gzip, deflate
Accept-Language:en-US,en;q=0.8,pt;q=0.6,gl;q=0.4
Cache-Control:no-cache Connection:keep-alive Content-Length:11519
Content-Type:multipart/form-data;
boundary=----WebKitFormBoundaryGlChAAe9WOKlPy2D
Cookie:laravel_session= [...] Host: [secret]
Request Payload
------WebKitFormBoundaryGlChAAe9WOKlPy2D Content-Disposition: form-data; name="upload[]"; filename="avatar.png" Content-Type:
image/png
------WebKitFormBoundaryGlChAAe9WOKlPy2D--
Here's the Retrofit version:
----> HTTP POST http://xxxxxxx
Accept: application/json
Content-Type: multipart/form-data
Content-Length: 9094
--1d87e0b7-bf5d-4034-b20b-48155a5dee2a
Content-Disposition: form-data; name="upload[]" filename="picSuggestion.jpg"
Content-Type: image/jpeg Content-Length: 8846
Content-Transfer-Encoding: binary
---> END HTTP (9094-byte body)
<--- HTTP 200 http://xxxxxxxx/api/uploads/?api=true&token=xxxx(1240ms)
: HTTP/1.1 200 OK
Cache-Control: no-cache
Connection: keep-alive
Content-Type: text/html; charset=UTF-8
Date: Fri, 28 Aug 2015 13:11:20 GMT
Server: nginx/1.4.6 (Ubuntu)
Set-Cookie: laravel_session=xxxxxxx; path=/; httponly
Transfer-Encoding: chunked
X-Android-Received-Millis: 1440767479264
X-Android-Response-Source: NETWORK 200
X-Android-Sent-Millis: 1440767478578
X-Powered-By: PHP/5.5.9-1ubuntu4.11
<--- END HTTP (0-byte body)
We tried a bunch of Retrofit service and interceptor configurations without success, but here's the latest one we tried
requestInterceptor2 = new RequestInterceptor() {
#Override
public void intercept(RequestInterceptor.RequestFacade request) {
request.addHeader("Content-Type", "multipart/form-data" );
request.addHeader("Accept", "application/json" );
request.addQueryParam("key", API_KEY);
}
};
#Multipart
#POST("/api/uploads/")
void uploadImage(#Part(value = "upload[]", encoding = "binary") TypedFile payload, #Query("api") boolean api, #Query("token") String token, Callback<uploadImagePoiResultVO> cb);