Problem with volley POST and response null from the server (Kotlin) - kotlin

I got a problem with my Volley POST in kotlin :
When I use this following code, my application go on "Response.Listener", but the array is null, so when I try to display the information I've just send, I can only get "null".
May you guys help me? :)
There is the kotlin code :
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener { response ->
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $response $jsonobj")
println("Yessai")
}, Response.ErrorListener{
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}
)
que.add(req)
}
Now, there is the PHP code :
<?php
$reponse = array("mail" => $_POST["mail"], "pwd" => $_POST["pwd"]);
echo json_encode($reponse);
?>
I tried to use a GET to recieve this data from a GET array, but the problem still being...
And when I go on my server's logs, I cans ee that I have a POST request from my application (even if I can't see what's in the request).
I use this code to do a Login task, but atm, I just want to send a post request from my application.
Please help :)

EDIT: Your PHP code is NOT fine.
To get JSON data you should not use $_POST (even if it was send with post). Use this instead:
<?php
$data = json_decode(file_get_contents('php://input'), true);
$reponse = array("mail" => $data["mail"], "pwd" => $data["pwd"]);
echo json_encode($reponse);
?>
Here is a code that work for volley (it's not too different than what you have :-) ):
val jsonObjectRequest: JsonObjectRequest = object : JsonObjectRequest(Method.POST, url, **jsonobj**, Response.Listener { response: JSONObject ->
try {
val email = response.getString("email")
val password = response.getString("password")
} catch (e: JSONException) {
// catch/handle JSON error
} catch (e: Exception) {
// catch/handle other error
}
}, Response.ErrorListener { error: VolleyError ->
//Error Listener code
}) {
override fun getBodyContentType(): String {
return "application/x-www-form-urlencoded"
}
// you can override more functions here if needed (getHeader, etc.)
}
queue.add(jsonObjectRequest)
For your case it would likely give:
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener { response: JSONObject ->
val mailBack = response.getString("mail")
val pwdBack = response.getString("pwd")
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $response $mailBack - $pwdBack")
println("Yessai")
}, Response.ErrorListener{
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}
)
que.add(req)
}

There is the code I have after you send me what code I have to put inside :
(Still returns null values)
private fun sendHtmlRequest(view: View){
val emailreq = view?.findViewById<EditText>(R.id.editText_email)
val pwdreq = view?.findViewById<EditText>(R.id.editText_password)
val email = emailreq.text.toString()
val pwd = pwdreq.text.toString()
val jsonobj = JSONObject()
var url = "https://www.dorian-roulet.com/testStage-master/mobileApp/testpostone.php"
jsonobj.put("mail", email)
jsonobj.put("pwd", pwd)
val que = Volley.newRequestQueue(context)
val jsonObjectRequest = JsonObjectRequest(
Request.Method.POST, url, jsonobj,
Response.Listener { response: JSONObject ->
val emails = response.getString("mail")
val passwords = response.getString("pwd")
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche $emails $passwords $response $jsonobj")
}, Response.ErrorListener {
view.findViewById<TextView>(R.id.error_login)?.text = ("Ca marche pas mec $jsonobj")
println("Erreur")
}) /*{
override fun getBodyContentType(): String {
return "application/x-www-form-urlencoded"
}
// you can override more functions here if needed (getHeader, etc.)
}*/
que.add(jsonObjectRequest)
}

Related

Get response from server in JWT

I have the following code, where I validate the JWT token (with volley):
private fun validateToken(token: String) {
var queue = Volley.newRequestQueue(this)
val yourUrl = "https://mysite/wp-json/jwt-auth/v1/token/validate"
val parameters = JSONObject()
try {
parameters.put("username", "abc#test.com")
parameters.put("password", "12345678")
} catch (e: java.lang.Exception) {
}
val request: JsonObjectRequest =
object : JsonObjectRequest(
Method.POST, yourUrl, parameters,
Response.Listener { response -> Log.i("onResponse", response.toString()) },
Response.ErrorListener { error -> Log.e("onErrorResponse", error.toString()) }) {
#Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val headers: MutableMap<String, String> = HashMap()
// Basic Authentication
//String auth = "Basic " + Base64.encodeToString(CONSUMER_KEY_AND_SECRET.getBytes(), Base64.NO_WRAP);
headers["Authorization"] = "Bearer $token"
return headers
}
}
queue.add(request)
}
It works for me and I get the correct response from the server (in Log.i):
{"code":"jwt_auth_valid_token","data":{"status":200}}
My question is how in my code I do to be able to save the status: 200 in a variable so then it applies an ʻif status == 200` and if it is 200 then send it to another activity.
Add implementation 'com.google.code.gson:gson:2.8.6' to build.gradle(app)
Create Model.tk with:
data class dataServer (
#SerializedName("code") val code : String,
#SerializedName("data") val data : Data
)
data class Data (
#SerializedName("status") val status : Int
)
3. Update code:
private fun validateToken(token: String) {
var queue = Volley.newRequestQueue(this)
val yourUrl = "https://myweb/wp-json/jwt-auth/v1/token/validate"
val parameters = JSONObject()
try {
parameters.put("username", "abc#test.com")
parameters.put("password", "12345678")
} catch (e: java.lang.Exception) {
}
val request: JsonObjectRequest =
object : JsonObjectRequest(
Method.POST, yourUrl, parameters,
Response.Listener {
response ->
Log.i("onResponse", response.toString())
val gson = Gson()
val dataToken = gson.fromJson(response.toString(), dataServer::class.java)
val status = dataToken.data.status
println(status)
// use here if then
},
Response.ErrorListener { error -> Log.e("onErrorResponse", error.toString()) }) {
#Throws(AuthFailureError::class)
override fun getHeaders(): Map<String, String> {
val headers: MutableMap<String, String> = HashMap()
// Basic Authentication
//String auth = "Basic " + Base64.encodeToString(CONSUMER_KEY_AND_SECRET.getBytes(), Base64.NO_WRAP);
headers["Authorization"] = "Bearer $token"
return headers
}
}
queue.add(request)
}

Testing endpoint under auth with Ktor

I'm struggling to write tests for an endpoint that is under auth (token). In particular, when writing my test, I'm not able to chain the login request with my second request, despite providing the token received as part of the login request.
LoginEndpoint.kt
const val LOGIN_ENDPOINT = "$API_VERSION/login"
#Location(LOGIN_ENDPOINT)
class Login
fun Route.loginEndpoint(patientsRepository: Repository<Patient>, authProvider: AuthProvider) {
post<Login> {
val params = call.receive<Parameters>()
val userId = params["id"] ?: return#post call.respond(status = HttpStatusCode.BadRequest, message = "Missing user id")
val user = patientsRepository.get(userId)
if (user != null) {
val token = authProvider.generateToken(user.id!!)
call.respond(TextContent("{ \"token\": \"$token\" }", ContentType.Application.Json))
} else {
call.respond(status = HttpStatusCode.NotFound, message = "User with id $userId does not exist")
}
}
}
LoginEndpointTest.kt (passing, all good)
#Test
fun `given user exists then returns 200 and token`() {
val userId = "paco123"
val token = "magic_token_123"
withTestApplication({
givenTestModule()
}) {
every { authProvider.generateToken(userId) } answers { token }
givenPatientExists(userId)
with(handleRequest(HttpMethod.Post, "/$API_VERSION/login") {
addHeader("content-type", "application/x-www-form-urlencoded")
setBody("id=$userId")
}) {
assertEquals(HttpStatusCode.OK, response.status())
assertEquals("{ \"token\": \"magic_token_123\" }", response.content)
}
}
}
private fun Application.givenTestModule() {
module(
testing = true,
repositoryModule = TestingRepositoryModule,
authProvider = authProvider
)
}
Now, the problematic endpoint.
ProfileEndpoint.kt
const val PATIENTS_API_ENDPOINT = "$API_VERSION/profile"
#Location(PATIENTS_API_ENDPOINT)
class ProfileEndpoint
fun Route.profileEndpoint(patientsRepository: Repository<Patient>) {
authenticate("jwt") {
get<ProfileEndpoint> {
val apiUser: Patient = call.apiUser!!
val id = apiUser.id!!
val patient = patientsRepository.get(id)
when (patient != null) {
false -> call.respond(status = HttpStatusCode.NotFound, message = "Patient with id $id does not exist")
true -> call.respond(status = HttpStatusCode.OK, message = patient.map())
}
}
}
}
Finally, my failing test
ProfileEndpointTest.kt
#Test
fun `given user is logged in then returns 200 and profile`() {
val userId = "paco123"
val token = "magic_token_123"
withTestApplication({
givenTestModule()
}) {
every { authProvider.generateToken(userId) } answers { token }
givenPatientExists(userId)
handleRequest(HttpMethod.Post, "/$API_VERSION/login") {
addHeader("content-type", "application/x-www-form-urlencoded")
setBody("id=$userId")
}
handleRequest(HttpMethod.Get, "/$API_VERSION/profile") {
addHeader("Authorization", "Bearer $token")
}.apply {
assertEquals(HttpStatusCode.OK, response.status())
}
}
}
The error is:
expected:<200 OK> but was:<401 Unauthorized>
Expected :200 OK
Actual :401 Unauthorized
AuthProvider.kt
open class AuthProvider(secret: String = System.getenv(Environment.JWT_SECRET)) {
private val algorithm = Algorithm.HMAC512(secret)
fun getVerifier(): JWTVerifier = JWT
.require(algorithm)
.withIssuer(APP_NAME)
.build()
fun generateToken(userId: String): String = JWT.create()
.withSubject(SUBJECT)
.withIssuer(APP_NAME)
.withClaim(CLAIM, userId)
.withExpiresAt(expiresAt())
.sign(algorithm)
private fun expiresAt() = Date(System.currentTimeMillis() + MILLIES_PER_DAY * TOKEN_DAYS_LENGTH)
}
val ApplicationCall.apiUser get() = authentication.principal<Patient>()
I've tried using cookiesSession like in this documentation's example https://ktor.io/servers/testing.html#preserving-cookies but it didn't work. Any help would be much appreciated.

How to correctly do array request in volley

I'm trying to do get request and get array in json but i'm having error like this:
org.json.JSONException: Value [] of type org.json.JSONArray cannot be converted to JSONObject
here's my request code:
private fun getStudents(endLink: String) {
val request = JSONObject()
val studentLink = "https://192.168.1.1/getStudents.php?idEntity="
val linkFull = studentLink.plus(endLink)
val jsArrayRequest = JsonObjectRequest(Request.Method.GET, linkFull, request, Response.Listener<JSONObject> {
val builder = GsonBuilder()
val gson = builder.create()
val student =
gson.fromJson<Students>(it.toString(), students::class.java!!)
studentResponse = studentResponse
//updateInfo()
}, Response.ErrorListener {
Log.d("ERRORKA", it.message)
Toast.makeText(
this.context,
it.message, Toast.LENGTH_SHORT
).show()
})
MySingleTon.getInstance(this.context!!).addToRequestQue(jsArrayRequest)
}
also my data models:
class StudentResponse {
var groupNumber: String = ""
var students: List<Students>? = null
}
here's 2nd:
class Students {
val id: Int = 0
val firstName: String? = ""
val lastName: String? = ""
val middleName: String? = ""
val email: String? = ""
}
You are not doing jsonArrayRequest, you can see the object you are creating is of JsonObjectRequest. Do like below.
// Method: POST
val mDataArray = JSONArray(); // This should be JSONArray object
val mRequest = JsonArrayRequest(Request.Method.POST,"YOUR API URL", mDataArray,{
//Response listener
},{
//Error listener
})
// Method: GET
val mRequest = JsonArrayRequest(Request.Method.GET,"YOUR API URL", null,{
//Response listener
},{
//Error listener
})

Error with JSONObject() - Kotlin

I'm trying to do a login view with Volley Library.
It seems that "jsonobj" is always empty.
val jsonobj = JSONObject()
loginBtn.setOnClickListener {
jsonobj.put("mail", mailTxt.text)
jsonobj.put("pass", passTxt.text)
val que = Volley.newRequestQueue(this#MainActivity)
val req = JsonObjectRequest(Request.Method.POST, url, jsonobj,
Response.Listener{
response ->
toast(response["error"].toString())
}, Response.ErrorListener {
toast("Error")
})
que.add(req)
}
}
}

how to fetch information using volley library in kotlin

I've a php file on a server, and I have to fetch the information but i don't know how to pass a parameter to the query.
For example, if I have this query: SELECT * FROM accounttable WHERE idaccount = 1, i want to pass this 1 as a parameter, how can i do?
val stringRequest = StringRequest(Request.Method.POST, URL, Response.Listener<String>{ s ->
try {
val array = JSONArray(s)
for (i in 0..array.length() - 1) {
val objectAccount = array.getJSONObject(i)
val account = Account(
objectAccount.getString("accountplace"),
objectAccount.getString("useraccount"),
objectAccount.getString("accountpass"))
listAccounts.add(account)
}
}catch (e: JSONException){
e.printStackTrace()
}
}, Response.ErrorListener { error: VolleyError? -> Log.e("error", "error") })
val requesQueue = Volley.newRequestQueue(this)
requesQueue.add<String>(stringRequest)
You need to override the getParams() method on your Request. In order to do that you can either subclass StringRequest, or create an object expression (similar to an anonymous inner class from Java); as shown below.
val stringRequest = object : StringRequest(Request.Method.POST, URL, Response.Listener { s ->
// Your success code here
}, Response.ErrorListener { e ->
// Your error code here
}) {
override fun getParams(): Map<String, String> = mapOf("idaccount" to "1")
}