WebSockets in kotlin - swift

I want to establish a connection with a server. For the connection is established I need to pass a url and in Header the accessToken (I can do this). If the connection is make with successful i need to pass another value (gameId). In swift the solution pass for this way:
(...)
self.manager = SocketManager(socketURL: URL(string: K.ProductionServer.baseURL)!,
config: [.log(true),
.compress,
.extraHeaders(["Authorization": "Bearer \(self.userSession.access_token)"]),
.connectParams(["game_id": self.gameId])])
(...)
Is there anything like this in kotlin? Until now, I maked the code below.
private fun instantiateWebSocket() {
val accessToken = "aaa"
val client : OkHttpClient = OkHttpClient()
val request : Request = Request.Builder()
.url("bbb")
.addHeader("Authorization", "Bearer $accessToken")
//.post("game_id", gameId)
.build()
val socketListener : SocketListener = SocketListener(this)
webSocket = client.newWebSocket(request, socketListener)
}

You can try to use Ktor HTTP client.

Related

Auth token handling for Gatling

Doing performance testing of API using Gatling.
Scenario:
Login (authToken will be generated in header)
For GET, POST, PUT request, need to pass that generated authToken in header
Here's my code snippet:
package apitest
import scala.concurrent.duration.*
import io.gatling.core.Predef.*
import io.gatling.http.Predef.*
import io.gatling.jdbc.Predef.*
import scala.language.postfixOps
class TestEnv4trial extends Simulation {
var e1: String = "https://testenv1-dev.net"
var e2: String = "https://testenv2-dev.net"
var BaseUrl: String = e1
var pwd: String = "pass123"
// Users
var admin: String = "admin123"
val httpProtocol = http
.baseUrl(BaseUrl)
.inferHtmlResources()
val login_headers = Map(
"Accept" -> """*/*""",
"Connection" -> "keep-alive",
"Content-Type" -> "application/x-www-form-urlencoded;charset=UTF-8"
)
val scn1 = scenario("Admin Login")
.exec(http("Login Admin")
.post({BaseUrl} + "/api/user/login")
.formParam("username", admin123)
.formParam("password", pass123)
.check(jsonPath("$.authToken").saveAs("tokenId")))
.exec { session => println(session("tokenId").as[String]); session } //authToken getting printed
val common_headers = Map(
"Accept" -> """*/*""",
"Accept-Encoding" -> "gzip, deflate, br",
"Accept-Language" -> "en-GB,en;q=0.9,en-US;q=0.8",
"Authorization" -> "Bearer " + $tokenId, //With hardcoded authToken works. Need to pass generated authToken in prev scenario here.
"Connection" -> "keep-alive",
)
val scn2 = scenario("All Employees")
.exec(http("All Employees")
.post("/api/employee/lists/")
.headers(common_headers)
.body(RawFileBody("test/TestEnv4trial/employees_request.json")).asJson)
setUp(
scn1.inject(atOnceUsers(1)).protocols(httpProtocol),
scn2.inject(atOnceUsers(1)).protocols(httpProtocol))
}
When I hardcode authToken generated in scn1 in common_headers, scn2 works.
But when I use tokenId, its not able to identify tokenId.
How do I pass saved key tokenId in common_headers?
Thanks.
"Authorization" -> "Bearer " + $tokenId
This doesn't compile.
Currently, you're using Session attributes, meaning tokenId is scoped for the single user executing scn1.
There's no way for a user executing scn2 to be able to reach it as is.

Gatling Error when running multiple users - 'httpRequest-2' failed to execute: No attribute named 'access_token' is defined

im new to Gatling and have been trying to setup a test where my users login, get an access token, then perform some simple get requests using that token. Having 1-2 users works fine, however once i start ramping up the users i start getting spammed with this error:
[ERROR] i.g.h.a.HttpRequestAction - 'httpRequest-2' failed to execute: No attribute named 'access_token' is defined
Im thinking it could have something to do with the way I am saving and using the access token ?
class GatlingTest extends Simulation {
val httpProtocol = http
.baseUrl("https://myurl.com/api/v1")
.inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.woff2""", """.*\.(t|o)tf""", """.*\.png""", """.*detectportal\.firefox\.com.*"""), WhiteList())
.acceptLanguageHeader("en-GB,en;q=0.5")
.upgradeInsecureRequestsHeader("1")
object GetUserData {
val userData = exec(http("Get_User_Data")
.get("/user")
.header("Authorization", "Bearer ${access_token}"))
.pause(1)
}
object GetUserInfo {
val userInfo = exec(http("Get_User_Info")
.get("/userInfo")
.header("Authorization", "Bearer ${access_token}")
.header("Accept", "application/json"))
.pause(1)
}
object Login {
val sentHeaders = Map("api_key" -> "nnxzv336wt2374h6zw5x24qd", "Content-Type" -> "application/x-www-form-urlencoded", "Accept" -> "application/json")
val login = exec(http("Login_User")
.post("/login")
.basicAuth("username", "password")
.headers(sentHeaders)
.body(StringBody("grant_type=password&username=username#username.local&password=12345"))
.check(jsonPath("$.access_token").saveAs("access_token"))
)
}
val user = scenario("User").exec(Login.login).exec(GetUserData.userData, GetUserInfo.userInfo)
setUp(
user.inject(
rampUsers(5).during(2.seconds),
).protocols(httpProtocol)
)
}
I have added Authorization Bearer to the get requests, like i mentioned it does work, but as soon as 3+ users are involved i get the error.
It means the login request failed and hence, the user wasn't able to capture the access_token there.

How do I upload an image to Parse Server using Kotlin/Jvm via Rest Service?

I'm creating a Kotlin/Jvm (without Android Sdk) application that interacts with a instance of a Parse Server (Back4App). Unfortunately, parse doesn't provide a Sdk implementation to use with Java/Kotlin without Android.
So I'm using the rest Api. Now I trying to upload a image from my disk into Back4App file server. In the doc there is snippet using curl. But I wasn't able to translate into a Retrofit service:
curl -X POST \
-H "X-Parse-Application-Id: 4MGgDJ0ZiQloXoSTE2I9VM6YUYIz8EwCKF4pK7zr" \
-H "X-Parse-REST-API-Key: ${REST_API_KEY}" \
-H "Content-Type: image/jpeg" \
--data-binary '#myPicture.jpg' \
https://YOUR.PARSE-SERVER.HERE/parse/files/pic.jpg
So I based my implementation in this article and other snippets from GitHub and created a retrofit service for it:
#Multipart
#POST("/parse/files")
fun upload(
#Part file: MultipartBody.Part
): Call<ResponseBody>
And call:
var file = File("assets/escudo.png")
var requestFile = RequestBody.create(MediaType.parse("**/image"), file)
var body = MultipartBody.Part.createFormData("picture", file.name, requestFile)
var r = getService().upload(body).execute()
I created the retrofit instance as below:
fun getService(): ParserService {
val retrofit = Retrofit
.Builder()
.baseUrl("https://parseapi.back4app.com")
.addConverterFactory(GsonConverterFactory.create())
.client(createClient()).build()
return retrofit.create(ParserService::class.java)
}
fun createClient(): OkHttpClient {
return OkHttpClient.Builder().addInterceptor(createHeadInterceptor()).build()
}
fun createHeadInterceptor(): Interceptor {
return HeaderInterceptor()
}
class HeaderInterceptor : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response =
chain.run {
val credentials = CredentialsUtils.readCredentials()
log.info { credentials }
proceed(
request().newBuilder()
// .addHeader("Content-Type", "application/json")
.addHeader("Content-Type", "image/png")
.addHeader("X-Parse-Application-Id", credentials.back4appAppId)
.addHeader("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
.build()
)
}
}
I was able to use it to posting Json data (by uncommenting the content/type header). But when I tried to upload an image I receive this response:
Response{protocol=h2, code=400, message=, url=https://parseapi.back4app.com/parse/files}
More info:
-- EDIT
I tried a different approuch without Retrofit, it gives a 201 response code and gives me an objectId, but it doesn't upload the file:
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val url = URL(serverUrl)
val conn = url.openConnection() as HttpURLConnection
conn.requestMethod = "POST"
conn.doOutput = true
val postData = file2.readBytes()
conn.addRequestProperty("Content-length", postData.size.toString())
conn.setRequestProperty("Content-Type", "image/*")
conn.setRequestProperty("X-Parse-Application-Id", credentials.back4appAppId)
conn.setRequestProperty("X-Parse-REST-API-Key", credentials.back4appRestApiKey)
val outputStream = DataOutputStream(conn.outputStream)
outputStream.write(postData)
outputStream.flush()
println(conn.responseCode)
-- EDIT
Trying now using Khttp:
val file = File("assets/foto.jpg")
val file2 = File("assets/escudo.png")
val serverUrl = "https://parseapi.back4app.com/classes/myfiles"
val files = listOf(FileLike("foto.jpg", file), FileLike("escudo.png", file2))
val response = post(serverUrl, headers = getHeaders(), files = files)
println(response)
println(response.text)
}
fun getHeaders(): Map<String, String> {
return mapOf(
"Content-Type" to "image/*",
"X-Parse-Application-Id" to credentials.back4appAppId,
"X-Parse-REST-API-Key" to credentials.back4appRestApiKey
)
}
Getting this error:
<Response [400]>
{"error":"Unexpected token - in JSON at position 0"}
If you're using Back4App, the correct Server URL is:
https://parseapi.back4app.com/files/pic.jpg

Scala HttpPost - How to pass authentication parameters

------Update
Was able to fix it by using the UsernamePasswordCredentials class
The code looks like below
val client = new DefaultHttpClient
client.getCredentialsProvider().setCredentials(AuthScope.ANY,new UsernamePasswordCredentials("user","password"));
i am trying to make a HttpPost call to a Restful API, its expecting a username/password, how to pass those parameters? I tried 2 ways
post.addHeader("Username","user")
post.addHeader("Password","clear pwd")
and
post.addHeader("Authorization","Basic base64encoded username:password")
nothing works, I get response text as
Response Text = HTTP/1.1 401 Unauthorized [WWW-Authenticate: Digest realm="API Realm", domain="/default-api", nonce="pOxqalJKm5L5QXiphgFNmrtaJsh+gU", algorithm=MD5, qop="auth", stale=true, Content-Type: text/html; charset=ISO-8859-1, Cache-Control: must-revalidate,no-cache,no-store, Content-Length: 311] org.apache.http.conn.BasicManagedEntity#5afa04c
Below is my code
val url = "http://restapi_url";
val post = new HttpPost(url)
//post.addHeader("Authorization","Basic QWBX3VzZXI6Q0NBQGRidHMxMjM=")
post.addHeader("Username","user_user")
post.addHeader("Password","clear pwd")
post.addHeader("APPLICATION_NAME","DO")
val fileContents = Source.fromFile("input.xml").getLines.mkString
post.setHeader("Content-type", "application/xml")
post.setEntity(new StringEntity(fileContents))
val response = (new DefaultHttpClient).execute(post)
println("Response Text = "+response.toString())
// print the response headers
println("--- HEADERS ---")
response.getAllHeaders.foreach(arg => println(arg))
Here the authorization header should be calculated like this:
httpPost.addHeader("Authorization", "Basic " + Base64.getEncoder.encodeToString("[your-username]:[your-password]".getBytes))
Instead of getUrlEncoder(), it should be getEncoder().
you can write like this, it works in my program
import java.util.Base64
httpPost.addHeader("Authorization", "Basic " + Base64.getUrlEncoder.encodeToString("[your-username]:[your-password]".getBytes))
DefaultHttpClient is deprecated. You should use BasicCredentialsProvider instead. Example code below:
val username = "your_username"
val password = "your_password"
val credentialsProvider = new BasicCredentialsProvider()
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(username, password)
)
val httpClient = HttpClientBuilder.create().setDefaultCredentialsProvider(credentialsProvider).build()

How to call CQ author URL from a standalone code

I am trying to hit URL in cq Author instance from my standalone code. The URL looks like — http://<somehost>:<someport>//libs/dam/gui/content/reports/export.json
Below is the code:
URL url = new URL(newPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setReadTimeout(15 * 10000);
connection.connect();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
But I got a 401 error, which is expected, as I'm not passing any authentication information — hence Sling says:
getAnonymousResolver: Anonymous access not allowed by configuration - requesting credentials.
How can I get resolve this?
You may use Basic HTTP authentication. Adding it to the HttpURLConnection is little awkward:
Authenticator.setDefault(new Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("admin", "admin".toCharArray());
}
});
Consider using Apache HttpClient:
UsernamePasswordCredentials creds = new UsernamePasswordCredentials("admin", "admin");
DefaultHttpClient authorizedClient = new DefaultHttpClient();
HttpUriRequest request = new HttpGet(url);
request.addHeader(new BasicScheme().authenticate(creds, request));
HttpResponse response = authorizedClient.execute(request);
InputStream stream = response.getEntity().getContent();