I am not able to log in into the app using Gatling - scala

I am new to Gatling facing some trouble while log in into the application.
There is an API which provides a random no and public key, I have to save these values so that I can parse them to next step.
Next step is a post request for entering User-id and password, password gets encrypted.
Also I have to save XSRF token from the cookie to maintain the session.
Then there is O.T.P authentication which I have to fetch from Rest API.
how do i need to perform all the above in sequence

object Actions {
def retrieveAuthData(session: Session, datakey: String): AuthData = {
// get response as a string
val t: String = session.get(datakey).as[String];
// retrieve parameters from json
val publicKey: String = a("PublicKey").asInstanceOf[String];
val random: String = a("Random").asInstanceOf[String];
val ds3: Boolean = a("DS3").asInstanceOf[Boolean];
val twoFA: Boolean = a("TwoFa").asInstanceOf[Boolean];
return new AuthData(publicKey, random, ds3, twoFA);
}
}

Related

Gatling session - get attribute as Long

I am a new in Scala and got some problems with casting from String to Long. I try to get Gatling session value as Long in request. Before in exec() part, I try to set the userId value
def setUserId(): ChainBuilder = {
exec(session => session
.set("userId", Random.nextLong())
)
}
Next, in request creator I want to use it like that because I need a new userId every call:
object UserRequestCreator {
def sampleUserRequest(currency: String): Request = {
Data data = new Data()
data.setUserId("${userId}".toLong)
data.setCurrency(currency)
}
}
Test scenario:
exec(setUserId())
.exec(http("postUser")
.post(endpointUser).asXml
.headers(headers)
.body(StringBody(toXmlString(sampleUserRequest("EUR"), classOf[Request])))
.check(status.is(200))
but receive error:
java.lang.NumberFormatException: For input string: "${userId}"
How to fix that in Scala?
I also try Long.valueOf, JLong.parseLong("${userId"}, 16), Try(BigDecimal(...)) and more but nothing can help. I think the problem is with $ symbol, but I don't see any different way to get this value from the session. Maybe it is possible to store Long in the Gating session?
From the documentation and based on your current code, one way to do it is like that:
// with a function payload
http("name").post("/")
.body(StringBody(session => s"""{ "foo": "${session("dynamicValueKey").as[String]}" }"""))
Thus, in your case:
StringBody(session => toXmlString(sampleUserRequest(session)("EUR"), classOf[Request])
def sampleUserRequest(session: Session)(currency: String): Request = {
//...
data.setUserId(session("userId").as[Long])
}

Retrofit2 post request is successful but I'm not able to retrieve token from response body

So I'm trying to making a login(post) request to an API (https://reqres.in/api/login) with retrofit 2. The connection was successful as the response code is 200, when I did the same on Postman I received a response which contains a token string which I want but in android studio when I log the response body it gives different output. I am new to kotlin so I think I must be doing something wrong while retrieving response.
Output I'm receiving:
Response{protocol=h2, code=200, message=, url=https://reqres.in/api/login}
Output I want (token field)
{
"token": "QpwL5tke4Pnpja7X4"
}
Retrofit Builder
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl(apiUrl)
.build()
val api : reqresAPI = retrofit.create(reqresAPI::class.java)
API Interface
interface reqresAPI {
// FOR REFERENCE
// https://reqres.in/api/login
// ANNOTATE WITH POST TO SEND DATA
#POST(value = "login")
fun sendData(
#Body user: User
): Call<ResponseModel> // CALL IS USED TO MAKE AN API CALL
}
Response Model
class ResponseModel{
val token : String = ""
get() = field
}
User model with 2 parameters email and password
class User (
val email :String,
val password :String
)
Calling API
val call = api.sendData(user)
call.enqueue(object : Callback<ResponseModel>{
override fun onResponse(call: Call<ResponseModel>, response: Response<ResponseModel>) {
Log.d("LOGGER", response.toString())
}
override fun onFailure(call: Call<ResponseModel>, t: Throwable) {
Log.d("LOGGER", "ERROR "+t.message.toString())
}
})
Please change this
class ResponseModel{
val token : String = ""
get() = field
}
to this
class ResponseModel{
#SerializedName("token")
val token : String
}

Build Jenkins pipeline using HttpRequest

I try to execute a jenkins pipeline from a Scala app, but the authentication is required. So, I think before this request, I need to call the auth endpoint and get a token, then assign it on the headers.
val userToken = "user_token_generated_in_jenkins"
val pipelineToken = "pipeline_token"
val pipelineName = "HttpRequestTest"
// test1
val baseUrl = s"http://jenkins_address/view/Development/job/$pipelineName/build?token=$pipelineToken"
val response = Http(baseUrl).headers("token" -> "tried_a_valid_token_auth").asString
// test2
val url = s"http://auto:$userToken#jenkins_address/job/$pipelineName/build?token=$pipelineToken"
val response2 = Http(url).asString
If I can be sure that first test is wrong, why for test2, where I use the user token (generated in Users manager), it asks me to use extra token (generated by authentication)? Is a double verification and useless in my opinion.
As an emergency solution, I can execute the pipeline with curl using sys.process. But I prefer to solve it using Http library because I want to use generated token and not a specific username in my project code.
// test3
import sys.process._
val data = List("curl", "-u", "username:password", baseUrl).!!
How can I execute an HttpRequest using Jenkins User Token?
Thanks
If your Http(..) is from Akk-HTTP, the solution could be derived from here:
val authorization = headers.Authorization(BasicHttpCredentials("username", "password"))
HttpRequest(
PUT,
uri = "/user",
entity = HttpEntity(`text/plain` withCharset `UTF-8`, userData),
headers = List(authorization),
protocol = `HTTP/1.0`)
In case of scalaj-http it could be derived from here
With applying to your existing code, it should be like this:
Http(baseUrl).auth("username", "password").asString
By the way
I want to use generated token and not a specific username in my
project code
It is not a problem. You can construct your process' auth string dynamically. You are able to get the credentials from somewhere in the "native" Http solution, right? So you can construct your sys.process with the same getted-from-somewhere credentials by concatinating strings or string interpolation:
// test3
import sys.process._
val (username, password) = gettingFromSomewhereCreadentials()
val data = List("curl", "-u", s"$username:$password", baseUrl).!!

Akka-http & scribe for linkedin API: set/get cookie without session (scala)

I am using akka-http for bulding a REST API. (I am new to build REST web services).
I don't know how I can get and set cookie without using a session. This cookie must contain encrypt token access. I don't use Play or spray.
My code for the moment is:
lazy val signin = path("signin") {
get {
/* create the OAuthService object with a callback URL*/
val service = buildService()
/* get the request token*/
val requestToken = service.getRequestToken
/* create the cookie */
val jwtCookieEncrypted = tokenUtil.createLinkedinTokenSecret(requestToken)
val cookie = HttpCookie("jwtTokenCookie", jwtCookieEncrypted)
/* making the user validate our requestToken by redirecting him to the following URL*/
val authURL = service.getAuthorizationUrl(requestToken)
redirect(authURL, StatusCodes.TemporaryRedirect)
}
}
lazy val callback = path("callback") {
// extract cookie with the jwtTokenCookie name
cookie("jwtTokenCookie") { cookiePair =>
complete(s"The logged in user is '${cookiePair.name}'")
}
get {
parameters('code, 'state) { (code, state) => // must come from cookie and not request parameters
/* create the OAuthService object with a callback URL*/
val service = buildService()
/* get the request token*/
val requestToken = new Token(code, state)
if(state == tokenUtil.decryptLinkedinToken(requestToken.getSecret).getOrElse("")) "continue" else "throw error"
val verifier = new Verifier(state)
/* get the access token
(need to exchange requestToken and verifier for an accessToken which is the one used to sign requests)*/
val accessToken = service.getAccessToken(requestToken, verifier)
logger.debug(accessToken.getRawResponse)
/* sign request*/
val ResourceUrl = Settings.LinkedIn.ResourceUrl
val request = new OAuthRequest(Verb.GET, ResourceUrl)
service.signRequest(accessToken, request)
val response = request.send
if (response.getCode == StatusCodes.OK.intValue) complete(response.getBody)
else complete(int2StatusCode(response.getCode))
}
}
}
signin ~ callback
Check the akka doc. In your response you can include the header. In your case, maybe with redirect it´s not so simple. But you could complete the signing request returning a 308 Http code with the Location Header pointing to your oauth2 Auth server.
Is it better ?
path("signin") {
get {
val service = buildService()
val requestToken = service.getRequestToken
val authURL = service.getAuthorizationUrl(requestToken)
val requestTokenCrypted = tokenUtil.createLinkedinToken(requestToken)
val cookie = HttpCookie("abcde", requestTokenCrypted.getSecret)
setCookie(cookie) {
complete(HttpResponse(
status = StatusCodes.TemporaryRedirect,
headers = List(Location(authURL))
))
}
}
}

Gatling2: Get response body as byte array

I want to send a request and will receive a byte[] body response. Based on this byte[] response I want to extract a value (using protobuf) and the reuse this value in another resquest.
After some hours search, I cannot find a possibility to extract the http response body as a byte array:
val httpConfig = http
.baseURL("http://www.whatever.com")
val request = exec(http("FirstRequest")
.post("/message")
.body(new ByteArrayBody((session: Session) => getFirstRequest(session)))
.check(status.is(200), ???getByteResponse???))
val response = exec(http("SecondRequest")
.post("/message")
.body(new ByteArrayBody((session: Session) => getSecondRequest(session)))
.check(status.is(200), ???getByteResponse???))
val scn = scenario("Request").exec(request,response)
setUp(scn.inject(atOnce(1 user)))
.protocols(httpConfig)
Alternatively it would also be fine if I could set a value in getFirstRequest, that I can reuse in getSecondRequest:
private def getFirstRequest(session: Session): Array[Byte] = {
... setting a session attribute ... (long)
... some protobuf stuff returning a byte array ...
}
private def getSecondRequest(session: Session): Array[Byte] = {
var value= session("value").as[Long]
... some protobuf stuff using value from session and then returning byte array...
}
I think you can try something like this :
.check(status.is(200), bodyBytes.saveAs("responseBody"))
This will save the body of the response in the virtual user's session.