I am trying to send Mailgun POST /messages API request in Android using retrofit library.
Following is retrofit request:
HTTP POST https://api:key-xxx/v3/sandboxxxx/messages
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded
Content-Length: 148
from=Excited+User+%3Cmailgun%40sandboxxxxmailgun.org%3E&to=vir.jain%40gmail.com&subject=Hello&text=Testing+awesomeness
Response:
HTTP 401 https://api:key-xxx/v3/sandboxxxx.mailgun.org/messages (1966ms)
Server: nginx/1.7.9
Date: Mon, 15 Jun 2015 10:00:37 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9
Connection: keep-alive
WWW-Authenticate: Basic realm="MG API"
OkHttp-Selected-Protocol: http/1.1
OkHttp-Sent-Millis: 1434362440805
OkHttp-Received-Millis: 1434362441086
Forbidden
When I try this same request on Postman, it works perfectly & email is sent properly. But when sending using retrofit library from Android fails with Forbidden.
My Retrofit API:
#FormUrlEncoded
#POST("/messages")
public void sendEmail(#Field("from") String from, #Field("to") String to, #Field("subject") String subject, #Field("text") String text, RestCallback objectRestCallback);
Base URL is:
https://api:key-xxx/v3/sandboxxxsandboxxxx.mailgun.org
Everything is form URL encoded. But I'm really not sure what going wrong.
Can anyone please help me out whats wrong with above API?
Thank you,
Mahavir
I added following authorization header with Base64 encoded string of API key to the request, it started working.
request.addHeader("Authorization", "Basic "+getBase64String("api:key-xxxYOUR-API-KEY>"));
#Selvin: Thanks so much for sending wiki link :).
you need to specify your mailgun region: mg.SetAPIBase(mailgun.APIBaseEU)
// Create an instance of the Mailgun Client
mg := mailgun.NewMailgun(yourDomain, privateAPIKey)
mg.SetAPIBase(mailgun.APIBaseEU)
Related
Hello thank you very much for your time, I am having an unknown issue with retrofit, the only lead I have is a socket closed/timeout message, so I think I may help me to have more info on how the okhttp client and retrofit works, and since I understand sockets have to do more with HTTP clients I would like to know more on the inner workings behind an okhttp client as that may lead to a solution.
So this is my issue.
I am having an issue were by using retrofit to get some data via Post on an android application one of my CallBacks never comes back with a response body even though other calls in the same Web Service are stable and work fine. This error is rather random and it only happens while using retrofit on an android application, while using postman or using the API on a web browser works just fine.
The only way that I have been able to replicate the error consistently is by switching the Network type on the android emulator from Full to HSDPA or any other network type different from full or LTE.
<blockquote class="imgur-embed-pub" lang="en" data-id="a/8bgCxtr" data-context="false" ></blockquote><script async src="//s.imgur.com/min/embed.js" charset="utf-8"></script>
This is some responses I get by the Throwable on Failure Calls
java.net.SocketTimeoutException: timeout
detail message: timeout
I have tried increasing the Timeout on the OkHttp Client and instead of a timeout error, I get a Socket Closed.
java.net.SocketException: Socket closed
detail message: Socket closed
With no more information on the error than those simple lines, so I searched a way to get more information and I found that I could set a logg interceptor on the OkHttp client to get more info on the issue, but what I got was not enough for me to see a possible solution.
This is the logg I get when the call returns correctly :
D/OkHttp: --> POST http://192.168.1.68:83/api/Comercios/comercios
D/OkHttp: Content-Type: application/json; charset=UTF-8
D/OkHttp: Content-Length: 418
D/OkHttp: Authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfVXNlck5hbWUiOiJVU0VSX0JPTkFOWkExIiwiX0hhc2giOiI1U1FGQUEiLCJqdGkiOiIzNmNmYTZlOS01ODk3LTQ0NjYtYjA0Mi1kZGVkMDBiZGU5ZDAiLCJleHAiOjE1ODE0ODAxMjUsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODMiLCJhdWQiOiJNeVRlc3RBcGkifQ.9xAkkMxRpUEFMNdQaZvVTYQIEc-8w22fl_ubIAVaqi4
D/OkHttp:
{"anyObjects":{"idGrupo":"00d60025-6fb9-484f-97f0-08d79dfdbf92"},"cultura":"","hash":"5SQFAA","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfVXNlck5hbWUiOiJVU0VSX0JPTkFOWkExIiwiX0hhc2giOiI1U1FGQUEiLCJqdGkiOiIzNmNmYTZlOS01ODk3LTQ0NjYtYjA0Mi1kZGVkMDBiZGU5ZDAiLCJleHAiOjE1ODE0ODAxMjUsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODMiLCJhdWQiOiJNeVRlc3RBcGkifQ.9xAkkMxRpUEFMNdQaZvVTYQIEc-8w22fl_ubIAVaqi4","usuario":"USER_BONANZA1"}
D/OkHttp: --> END POST (418-byte body)
D/OkHttp: <-- 200 OK http://192.168.1.68:83/api/Comercios/comercios
(66ms)
D/OkHttp: Transfer-Encoding: chunked
D/OkHttp: Content-Type: application/json; charset=utf-8
D/OkHttp: Server: Kestrel
D/OkHttp: X-Powered-By: ASP.NET
D/OkHttp: Date: Wed, 12 Feb 2020 01:03:01 GMT
https://pastebin.com/wRwnMrsk 2020-02-11 19:02:59.515
D/OkHttp: <-- END HTTP (276837-byte body)
The response body is in a paste bin, too long to be on this post.
and this is when the call gets a time out or a socket closed
D/OkHttp: --> POST http://192.168.1.68:83/api/Comercios/comercios
D/OkHttp: Content-Type: application/json; charset=UTF-8 D/OkHttp:
Content-Length: 418 D/OkHttp: Authorization: Bearer
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfVXNlck5hbWUiOiJVU0VSX0JPTkFOWkExIiwiX0hhc2giOiJCRFo1R0EiLCJqdGkiOiI0NmI0MTA0NC03M2M2LTQ5MDEtOTcyMy0yZjE1NjE1ODgzZDgiLCJleHAiOjE1ODE0ODAzMjMsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODMiLCJhdWQiOiJNeVRlc3RBcGkifQ.EgVFlAzqOlV-RpjRRxXpQzp3q3kk1FqTcoaGDQBY0XA
D/OkHttp:
{"anyObjects":{"idGrupo":"00d60025-6fb9-484f-97f0-08d79dfdbf92"},"cultura":"","hash":"BDZ5GA","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJfVXNlck5hbWUiOiJVU0VSX0JPTkFOWkExIiwiX0hhc2giOiJCRFo1R0EiLCJqdGkiOiI0NmI0MTA0NC03M2M2LTQ5MDEtOTcyMy0yZjE1NjE1ODgzZDgiLCJleHAiOjE1ODE0ODAzMjMsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODMiLCJhdWQiOiJNeVRlc3RBcGkifQ.EgVFlAzqOlV-RpjRRxXpQzp3q3kk1FqTcoaGDQBY0XA","usuario":"USER_BONANZA1"}
D/OkHttp: --> END POST (418-byte body)
D/OkHttp: <-- 200 OK http://192.168.1.68:83/api/Comercios/comercios
(34ms)
D/OkHttp: Transfer-Encoding: chunked
D/OkHttp: Content-Type: application/json; charset=utf-8
D/OkHttp: Server: Kestrel
D/OkHttp: X-Powered-By: ASP.NET
D/OkHttp: Date: Wed, 12 Feb 2020 01:05:45 GMT
It simply returns an empty body with no other explanation on why.
When searching the socket closed error or the time out, it has been mostly dead ends, saying that it has to do with the server and not the application, I spoke with the person that manages the API and the server and time and time again I have been told that from their side there is nothing wrong, at least that they know, One thing that they mention is that maybe the byte size of the body is too big and that's why is not allowing is closing the socket randomly, but I do not know how to keep it open or if that is the issue in the first place.
So I would like to know if there is a way to see a more detailed log of what's going on with the Okhttp server so I can better search for a possible solution.
I am going to post my code here, the model I send to the Webservice is fine that's not the issue because if the structure is not as the servers expect it to be I receive an onSuccess Response with a detailed error of what I did wrong from the server, is just when everything is okay, that I receive a timeout or a socket closed plus, some times it works some times it doesn't ( Not a server issue according to postman and my peers) But it never works when I switch the network type on the android emulator and i have shown before in the post.
This are my Gradle implementations
implementation "com.squareup.retrofit2:retrofit:2.5.0"
implementation "com.squareup.retrofit2:converter-gson:2.3.0"
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
implementation 'com.squareup.okhttp3:logging-interceptor:3.12.0'
This is how I build my Client and retrofit
private fun buildRetrofit(): Retrofit {
val logger = HttpLoggingInterceptor()
logger.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient()
.newBuilder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(FN.returnWebAPI(this))
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
}
This is how I make the call, now is just receiving a response body to be sure it doesn't have to do with the parsing of the data.
val idGrupoComercios = hashMapOf("idGrupo" to id)
val hashComercio = HashComercio(hash, upperU.usuario.toUpperCase(Locale.getDefault()), "", jwt.toString(), idGrupoComercios
)
val callComercios: Call<ResponseBody> =
service.getComercios(tokenBearer, hashComercio)
callComercios.enqueue(object :
Callback<ResponseBody> {
override fun onFailure(
call: Call<ResponseBody>,
t: Throwable
) {
Crashlytics.logException(t)
}
override fun onResponse(
call: Call<ResponseBody>,
response: Response<ResponseBody>
) {
if (response.code() == 200) {
val data = response.body()!!
}
})
So any help or ideas on what I can do would be of great help, I am in a position where it seems i can do something from the app side of the project, so any help would be great.
We were able to find a sort of exit to the issue.
In the past, the highest time out I tried was for 5 minutes when building the client, but it seems like the socket it builds closes if you don't max it out so I changed the timeout to one day that way it maxed out the timeout it can take.
And the android system or the server is not really going to wait a day for a response, so, for the most part, it delivers a response if the server does not reset the connection.
java.net.SocketException: Connection reset
In those cases, you simply put true on the retryOnConnectionFailure, and even though it takes more time to return an answer it will deliver one.
I talked to the person that manages the servers and told me that the issue is that the HTTP client or retrofit fail to reconstruct the message in the first try, and subsequent tries are more likely to fail if the response body is too long using a 3g Connection, also if it contains images or hash values inside the json , as I was doing
putting a hash for a complete image on the json.
This is the code for the client
val client = OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.DAYS)
.readTimeout(1, TimeUnit.DAYS)
.writeTimeout(1, TimeUnit.DAYS)
.retryOnConnectionFailure(false)
.callTimeout(1, TimeUnit.DAYS)
.hostnameVerifier(HostnameVerifier { hostname, session -> true })
.build()
Also he told me that for best results json when using HSDPA should be smaller than 1024 bytes with header and all. up to 2024 bytes Response bodies.
I'm trying to get logged in soundcloud by using their API. I manage to got a code with a success response from /connect but when I try to get a token, I end up with a 401 error. Here is what I send :
POST /oauth2/token HTTP/1.1
Host: api.soundcloud.com
Content-Type: application/x-form-urlencoded
Cache-Control: no-cache
Postman-Token: 255c7769-0f65-5c40-27bc-9429ea8c38ea
client_id=<my client id>&
client_secret=<my secret id>&
redirect_uri=http%3A%2F%2Fmywebsite&
grant_type=authorization_code&
code=a99cfc85c0e46235d7fdb9ca74b7dddd%23
Does anyone knows what I miss here to get a working request ?
It turned out I was not calling /connect correctly, this is the correct way :
https://soundcloud.com/connect?
client_id=<my client id>
&redirect_uri=<my redirect url>
&response_type=token
&scope=non-expiring
&display=popup
With response_type=token, we directly receive an access token so we don't need to call /oauth2/token then.
I have a rails app that uses Authlogic (from gem Communityengine). Now I want users to be able to login on a mobile device (Android in that case)
If I understand correctly I can use Http Basic Authentication to authorize specified actions, but the first step (I think) is, when the user enters his username and password in his Android device, to check wether that user exists and if that passwort is correct.
How would I do this?
The password is encrypted in the database (with a pw salt) So as I understand I can not just check the database if the provided user and password is correct.
Here are some Http headers from my app as the result from different curl requests I did, I guess Http basic auth is working since I get a correct HTTP code when I provide user credentials:
martin#martin-desktop:~/Applications$ curl -I username:password#localhost:3000/users/username/posts/new
HTTP/1.1 200 OK
Date: Sun, 21 Apr 2013 12:17:29 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.19
X-UA-Compatible: IE=Edge,chrome=1
ETag: "b9aa82940f06722b7d8e35ce46e3166d"
Cache-Control: must-revalidate, private, max-age=0
X-Request-Id: 291ee45de8cb95e06ed4e8e6d3d9408c
X-Runtime: 0.335820
X-Rack-Cache: miss
Set-Cookie: _AppName_session=BAh7CkkiD3Nlc3Npb25faWQGOgZFRkkiJTA0ZDRhYmQwNDJjYmM1OGJmZTkyNzJjMTc5NThkODg0BjsAVEkiDnJldHVybl90bwY7AEZJIj1odHRwOi8vZ2l2LWR1ZXJlbi51bmktbXVlbnN0ZXIuZGUvdXNlcnMvbWFydGluL3Bvc3RzL25ldwY7AEZJIhV1c2VyX2NyZWRlbnRpYWxzBjsARkkiAYAzYWM2NTJlMjgyODA5MTY1ODg2ZTBjNTdhNGUzYjk5MzRkNWQ0YTE4MDdlN2M0MWI2OTQzYmQyNzZmOGFlMGI5NjliMjU3NzZhYTg4NjBkM2U0Y2Q5YTJjYzgwODVlNzY5NDgwMzE2MmQ3NTBjYzlhMmQ4ZTViYTJmNjJmYzVhZQY7AFRJIhh1c2VyX2NyZWRlbnRpYWxzX2lkBjsARmkGSSIQX2NzcmZfdG9rZW4GOwBGSSIxYzlIQitJNXNYZHNGa2NCb2hKcm5DY2tIcHNxdWJuWDEydVdZUU5WSlMvZz0GOwBG--2b5f5687425d7ec414e34b79eb89e0b6b465c86f; path=/; HttpOnly
Status: 200
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
martin#martin-desktop:~/Applications$ curl -I localhost:3000/users/username/posts/new
HTTP/1.1 302 Found
Date: Sun, 21 Apr 2013 12:17:40 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.19
X-UA-Compatible: IE=Edge,chrome=1
Cache-Control: no-cache
X-Request-Id: 9e4b9094f99f5877c8fb79647a1a22f1
X-Runtime: 0.004657
X-Rack-Cache: miss
Set-Cookie: _AppName_session=BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWJhZGVlNzBjNjA0YmQ1MTgyYmI5OWMxZjcxOGIzZmZkBjsAVEkiDnJldHVybl90bwY7AEZJIj1odHRwOi8vZ2l2LWR1ZXJlbi51bmktbXVlbnN0ZXIuZGUvdXNlcnMvbWFydGluL3Bvc3RzL25ldwY7AEY%3D--32120aefd22c0748c352b016582451ede84225ca; path=/; HttpOnly
Location: localhost:3000/login
Status: 302
Vary: Accept-Encoding
Content-Type: text/html; charset=utf-8
What I also found out so far is, that the Set-Cookie uses Base64 encoding (This is the encoding for the resulting string literal from http basic auth)
Any help is appreciated!
Nevermind I added this method, which checks for username and password validity and writes the result in the header:
def auth
authenticate_or_request_with_http_basic do |username, password|
if user = User.find_by_login(username)
response.headers['Auth'] = 'Password incorrect'
if user.valid_password?(password)
response.headers['Auth'] = 'Credentials correct'
end
else
response.headers['Auth'] = 'Username incorrect'
false
end
end
end
In my mobile application I just send a request to username:password#mysite.com and read the http header. Not sure if this is an elegant method or if it is inteded, but it works for now.
Im currently working on an app that will request GPS location updates. I have successfully implemented it as well as the latitude API and OAuth 2.0. It seems like the latitude API only reads the users last google latitude update. I dont know how to insert a new update into the latitude API.
An example would be https://play.google.com/store/apps/details?id=gaugler.backitude&hl=en
They are able to insert new gps updates directly to google latitude.
How can I achieve this?
This can be done with the current location insert() API call:
https://developers.google.com/latitude/v1/currentLocation/insert
used the oauth playground to Post the following to the api u ask about
IMO at {data, all u really need are latitude, longitude. You will have to check that.
POST /latitude/v1/location HTTP/1.1
Host: www.googleapis.com Content-length: 244 Content-type:
application/json Authorization: OAuth
ya29.AHES6ZTbG5HRDWduqeV60o_GWYagNg1BEk4c89V5ocSh0W2yc6FRYg
{"data":{"kind": "latitude#location", "timestampMs": "1355601946",
"latitude": "22", "longitude": "22", "accuracy": "40", "speed":
"10", "heading": "180", "altitude": "42", "altitudeAccuracy":
"50", "activityId": "xyzzzzzzz"}}
HTTP/1.1 200 OK Content-length:
158 Via: HTTP/1.1 GWA X-content-type-options: nosniff Etag:
"0UQtEv4nUExaO_EaPNLUB8rXY8M/mI3wNTFvwTjtI9TlZ9A9neseLn0"
X-google-cache-control: remote-fetch
-content-encoding: gzip Server: GSE Reason: OK X-xss-protection: 1; mode=block Pragma: no-cache Cache-control: no-cache, no-store,
max-age=0, must-revalidate Date: Sat, 15 Dec 2012 20:32:11 GMT
X-frame-options: SAMEORIGIN Content-type: application/json;
charset=UTF-8 Expires: Fri, 01 Jan 1990 00:00:00 GMT
{"data":{"kind":"latitude#location","timestampMs":"1355601946","latitude":22.0,"longitude":22.0,"accuracy":40,"speed":10,"altitude":42,"altitudeAccuracy":50}}
For dev against these api's you should consider 2 things:
debug on your stack will require that you inspect HTTP HEADERS, HTTP WIRE
so, look them up and figure out how to display
use the 'oauth playground' to simulate what your app will POST. Simply put, if it works in the playground combined with CURL client , you will know exactly what to do in your app.
I want to send the SOAP xml request to php server from android device, as shown below are required parameter for posting request. Currently i am not getting any method or sample to do achieve.Any suggest some samples.
POST /sample/server.php HTTP/1.0
Host: x.x.x.x
User-Agent: NuSOAP/0.7.3 (1.114)
Content-Type: text/xml; charset=ISO-8859-1
SOAPAction: ""
Content-Length: 551
Thanks