How to put json response in loop with condition? - scala

I have parsed json response and saved it using .findAll(). What I want to do is, ignore keyframeId if value is '-1' else put keyframeId in .get() request with loop. I did some code but the value doesnt set in get() request and gives 'KO'. Here it takes all the values in Vector and place all in single http call see error for details. Also I am not sure about the doIf condition. Can you please help? Thanks.
My Json response format is like this.
{
totalCount: 1134,
limit: 9,
offset: 0,
resources: [
{
title: "Test",
keyframeId: -1
}
{
title: "Test1",
keyframeId: 12345
}
{
title: "Test2",
keyframeId: 12341
}
{
title: "Test3",
keyframeId: -1
}
{
title: "Test4",
keyframeId: 135481
}
....
....
]}
Here is the gatling script,
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
class MamamSearch extends Simulation {
val testServerUrl = System.getProperty("testServerUrl", "https://someurl")
val username = System.getProperty("username", "ma")
val password = System.getProperty("password", "ma")
val userCount = Integer.getInteger("userCount", 1).toInt
val httpProtocol = http
.baseURL(testServerUrl)
.inferHtmlResources(BlackList(""".*\.js""", """.*\.css""", """.*\.gif""", """.*\.jpeg""", """.*\.jpg""", """.*\.ico""", """.*\.woff""", """.*\.(t|o)tf""", """.*\.png"""), WhiteList())
val headers_0 = Map(
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Cache-Control" -> "max-age=0",
"Upgrade-Insecure-Requests" -> "1")
val headers_2 = Map("Accept" -> "text/css,*/*;q=0.1")
val headers_6 = Map(
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding" -> "gzip, deflate, br",
"Cache-Control" -> "max-age=0",
"Origin" -> testServerUrl,
"Upgrade-Insecure-Requests" -> "1")
val headers_80 = Map(
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Upgrade-Insecure-Requests" -> "1")
val headers_7 = Map("Accept" -> "image/webp,image/*,*/*;q=0.8")
val headers_11 = Map("Origin" -> testServerUrl)
val headers_12 = Map(
"Cache-Control" -> "no-cache",
"If-Modified-Since" -> "Mon, 26 Jul 1997 05:00:00 GMT",
"Pragma" -> "no-cache",
"X-Requested-With" -> "XMLHttpRequest")
val headers_15 = Map(
"Accept" -> "application/json, text/plain, */*",
"Cache-Control" -> "no-cache",
"If-Modified-Since" -> "Mon, 26 Jul 1997 05:00:00 GMT",
"Pragma" -> "no-cache",
"X-Requested-With" -> "XMLHttpRequest")
val headers_16 = Map("Accept" -> "*/*")
val headers_18 = Map(
"Accept" -> "text/html",
"Cache-Control" -> "no-cache",
"If-Modified-Since" -> "Mon, 26 Jul 1997 05:00:00 GMT",
"Pragma" -> "no-cache",
"X-Requested-With" -> "XMLHttpRequest")
val headers_19 = Map(
"Accept" -> "*/*",
"Accept-Encoding" -> "gzip, deflate, br",
"Origin" -> testServerUrl)
val headers_27 = Map(
"Accept" -> "*/*",
"Accept-Encoding" -> "gzip, deflate, br",
"Content-type" -> "text/plain",
"Origin" -> testServerUrl)
val uri1 = testServerUrl + "/mamam"
val uri2 = "https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0"
// Login request
val scn = scenario("MamamSearch")
.exec(http("Login")
.post("/mamam/a/masteraccount/login")
.headers(headers_6)
.formParam("username", username)
.formParam("password", password))
// Fetch and save data
.exec(http("Keyframe_request")
.get(uri1 + "/awsset/browse%3Bresource_type=media%3Boffset=1%3Blimit=9")
.headers(headers_12)
.check(jsonPath("$.resources[*].keyframeId").findAll.saveAs("kList"))
)
// added loop and conditions
.doIf(session => session("Keyframe_request").validate[String].map(kList => !kList.contains("-1")))
{
foreach("${kList}", "keyId") {
exec(http("Set_Keyframes")
.get(uri1 + "/keyframes/${kList};width=185;height=103")
.headers(headers_7))
}
}
.exec(http("Logout")
.get("/mam/logout")
.headers(headers_80))
setUp(scn.inject(atOnceUsers(userCount))).protocols(httpProtocol)
}
Throws following Error:
21345 [GatlingSystem-akka.actor.default-dispatcher-13] WARN i.g.http.ahc.AsyncHandlerActor - Request 'Set_Keyframes' failed: status.find.in(200,304,201,202,203,204,205,206,207,208,209), but actually found 400
21346 [GatlingSystem-akka.actor.default-dispatcher-13] DEBUG i.g.http.ahc.AsyncHandlerActor -
>>>>>>>>>>>>>>>>>>>>>>>>>>
Request:
Set_Keyframes: KO status.find.in(200,304,201,202,203,204,205,206,207,208,209), but actually found 400
21390 [GatlingSystem-akka.actor.default-dispatcher-4] INFO io.gatling.http.ahc.HttpEngine - Sending request=Set_Keyframes uri=https://someurl/mamam/keyframes/Vector(167154,%20167035,%20167037,%20167040,%20167029,%20167024,%20167026,%20167022,%20167023);width=185;height=103:

If I have understood correctly you want to take a value from the response and then use it within the next request. Firstly you must save the correct keyframeId.
What was not clear was whether you wanted to select a random keyframeId from your list or multiple keyframes, I have opted to select a random one.
First is that we must apply some jsonPath to our JSON response. This code .check(jsonPath("$.resources[?(#.keyframeId > -1)].keyframeId") will return only a list of keyframeIds which are greater than -1.
Next we select a random one and save it to a variable.
// Fetch and save data
.exec(http("Keyframe_request")
.get(uri1 + "/awsset/browse%3Bresource_type=media%3Boffset=1%3Blimit=9")
.headers(headers_12)
.check(jsonPath("$.resources[?(#.keyframeId > -1)].keyframeId")
.ofType[String]
.findAll
.transform(s => util.Random.shuffle(s).apply(1))
.saveAs("keyframeId"))
Now you just need to check to see if the session variable keyframeId exists and use it to drive your response using ${keyframeId}

.foreach("${IdList}", "id") {
doIf(session => session("id").as[String] != "-1") {
exec(http("ID != -1").get(session => session("id").as[String])
.check(status.is(404)))}
}

Related

org.http4s.client Post with header and UriForm

With using org.http4s.client can't find how I can send headers and UriForm together with Post request.
import org.http4s.client.dsl.io._
import org.http4s.Method._
val lstHeader: List[Header] = List(
Header("Accept", "application/json")
, Header("Accept-Charset", "utf-8")
, Header("Accept-Encoding", "gzip")
)
val formData :UrlForm = UrlForm(
"username" -> "user",
"enc_password" -> "password",
"queryParams" -> "{}",
"optIntoOneTap" -> "false"
)
val req1 = POST(
formData,
uri"https://www.instagram.com/accounts/login/ajax/"
)
val req2: Request[IO] = Request[IO](
Method.POST,
uri"https://www.instagram.com/accounts/login/ajax/",
HttpVersion.`HTTP/2.0`,
Headers(lstHeader)
)
req1 without my headers
req2 without form data
Thanks
I found
val req2: Request[IO] = Request[IO](
Method.POST,
uri"https://www.instagram.com/accounts/login/ajax/",
HttpVersion.`HTTP/2.0`,
Headers(lstHeader)
).withEntity(formData)

Failed to build request: No attribute named 'token' is defined in Gatling script

I convert HAR file to Gatling simulations script, but I have problem with extracting token from request header. After conversion I have the following code:
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._
class LoginTest extends Simulation {
val httpProtocol = http
.baseUrl("https://webapi.mytestsite.com)
.inferHtmlResources()
.userAgentHeader("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36")
val headers_0 = Map(
"Accept" -> "application/json, text/plain, */*",
"Origin" -> "https://mytestsite.com",
"Sec-Fetch-Mode" -> "cors")
val headers_1 = Map(
"Access-Control-Request-Headers" -> "authorization",
"Access-Control-Request-Method" -> "GET",
"Origin" -> "https://mytestsite.com",
"Sec-Fetch-Mode" -> "cors")
val headers_2 = Map(
"Accept" -> "application/json, text/plain, */*",
"Origin" -> "https://mytestsite.com",
"Sec-Fetch-Mode" -> "cors",
"authorization" -> "Bearer ipV0mVqxcVO7xQUJ6lBPNxn77tWCivmO7Gohe47z7d7skAJV-mRCuVOwT1YmJVOvZ8N-T-ZFCgvT4nclOsfI303G7Y4EBIS9pFl4iU23C8l1k6Di387ZnAuDIkncHAne9HukSN9bBf1in9L8ath8fE57gx1CZw-kDXU4K67Q9F9brj413mMZiQrIp6VMJaFFPmMcEgq-h0uo9lP03qTdz6Aq_GdxZOV9iXls2nGG5j6nt_cFaxoTFICn0nwKRjR7eJloyUXmF3wfoqkvC_5t5gZ_YKDMf_mLxg4V2seBVyM1O11EwOpGpTOZG5FYDnJoarDybX6QkE-F4eb5aZM27NiPjstMwMn4zQ2EvhuinLNWHBzTtRN0MNW8TLT0X4f6hNS0F9lmjWBzl_OF-wCzoYQiFM7tQsU2UkHC1FHROJbPQDOH6oxDG06u8Nnco07cmLKn60zE4FYDa52DTt1lNGK7GIP97LgrGCHEdJByN4U")
val headers_3 = Map("Sec-Fetch-Mode" -> "no-cors")
val headers_6 = Map(
"Origin" -> "https://mytestsite.com",
"Sec-Fetch-Mode" -> "cors",
"content-type" -> "application/x-www-form-urlencoded; charset=UTF-8")
val uri1 = "https://api.wage.iteodev.com/signalr"
val uri2 = "https://mytestsite.com/static/media/download-app-headline.a2c2b312.svg"
val scn = scenario("LoginTest")
.exec(http("request_0")
.post("/api/oauth/token")
.headers(headers_0)
.formParam("username", "yelari#malboxe.com")
.formParam("password", "Zaq1#wsx")
.formParam("grant_type", "password")
.resources(http("request_1")
.options("/api/account")
.headers(headers_1),
http("request_2")
.get("/api/account")
.headers(headers_2),
http("request_3")
.get(uri2 + "")
.headers(headers_3),
http("request_4")
.options("/api/conversations/")
.headers(headers_1),
http("request_5")
.options("/api/notifications")
.headers(headers_1),
http("request_6")
.get(uri1 + "/negotiate?clientProtocol=1.5&Authorization=Bearer%20ipV0mVqxcVO7xQUJ6lBPNxn77tWCivmO7Gohe47z7d7skAJV-mRCuVOwT1YmJVOvZ8N-T-ZFCgvT4nclOsfI303G7Y4EBIS9pFl4iU23C8l1k6Di387ZnAuDIkncHAne9HukSN9bBf1in9L8ath8fE57gx1CZw-kDXU4K67Q9F9brj413mMZiQrIp6VMJaFFPmMcEgq-h0uo9lP03qTdz6Aq_GdxZOV9iXls2nGG5j6nt_cFaxoTFICn0nwKRjR7eJloyUXmF3wfoqkvC_5t5gZ_YKDMf_mLxg4V2seBVyM1O11EwOpGpTOZG5FYDnJoarDybX6QkE-F4eb5aZM27NiPjstMwMn4zQ2EvhuinLNWHBzTtRN0MNW8TLT0X4f6hNS0F9lmjWBzl_OF-wCzoYQiFM7tQsU2UkHC1FHROJbPQDOH6oxDG06u8Nnco07cmLKn60zE4FYDa52DTt1lNGK7GIP97LgrGCHEdJByN4U&connectionData=%5B%7B%22name%22%3A%22livechat%22%7D%5D")
.headers(headers_6),
http("request_7")
.get("/UploadedFiles/03765fee-ede8-4689-9a4c-13dd2ada18a4.png")
.headers(headers_3),
http("request_8")
.get("/api/notifications")
.headers(headers_2),
http("request_9")
.get("/api/conversations/")
.headers(headers_2),
http("request_10")
.get("/UploadedFiles/26ac4d69-8a63-4575-bec4-849d5a5e194a.png")
.headers(headers_3),
http("request_11")
.get(uri1 + "/start?transport=serverSentEvents&clientProtocol=1.5&Authorization=Bearer%20ipV0mVqxcVO7xQUJ6lBPNxn77tWCivmO7Gohe47z7d7skAJV-mRCuVOwT1YmJVOvZ8N-T-ZFCgvT4nclOsfI303G7Y4EBIS9pFl4iU23C8l1k6Di387ZnAuDIkncHAne9HukSN9bBf1in9L8ath8fE57gx1CZw-kDXU4K67Q9F9brj413mMZiQrIp6VMJaFFPmMcEgq-h0uo9lP03qTdz6Aq_GdxZOV9iXls2nGG5j6nt_cFaxoTFICn0nwKRjR7eJloyUXmF3wfoqkvC_5t5gZ_YKDMf_mLxg4V2seBVyM1O11EwOpGpTOZG5FYDnJoarDybX6QkE-F4eb5aZM27NiPjstMwMn4zQ2EvhuinLNWHBzTtRN0MNW8TLT0X4f6hNS0F9lmjWBzl_OF-wCzoYQiFM7tQsU2UkHC1FHROJbPQDOH6oxDG06u8Nnco07cmLKn60zE4FYDa52DTt1lNGK7GIP97LgrGCHEdJByN4U&connectionToken=P%2FGWEN0HNtZWUowxiulVcCbSNQGTg%2BtCrti09SWiZKkPiFyOPNuEW4HBfWX%2FTPbRLhbhW5sst3BwnE3ihcbCvNE9m42MoguFmLCUGUib12Xrqsb8mZ7LsjlhYh5ul07Q1ups4KfOqxgcT0bx%2F03o1A%3D%3D&connectionData=%5B%7B%22name%22%3A%22livechat%22%7D%5D")
.headers(headers_6)))
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}
But when I change
http("request_2")
.get("/api/account")
.headers(headers_2),
to
http("request_2")
.get("/api/account")
.headers(headers_2)
.check(header("Bearer").saveAs("token"))
and when I change
http("request_6")
.get(uri1 + "/negotiate?clientProtocol=1.5&Authorization=Bearer%20ipV0mVqxcVO7xQUJ6lBPNxn77tWCivmO7Gohe47z7d7skAJV-mRCuVOwT1YmJVOvZ8N-T-ZFCgvT4nclOsfI303G7Y4EBIS9pFl4iU23C8l1k6Di387ZnAuDIkncHAne9HukSN9bBf1in9L8ath8fE57gx1CZw-kDXU4K67Q9F9brj413mMZiQrIp6VMJaFFPmMcEgq-h0uo9lP03qTdz6Aq_GdxZOV9iXls2nGG5j6nt_cFaxoTFICn0nwKRjR7eJloyUXmF3wfoqkvC_5t5gZ_YKDMf_mLxg4V2seBVyM1O11EwOpGpTOZG5FYDnJoarDybX6QkE-F4eb5aZM27NiPjstMwMn4zQ2EvhuinLNWHBzTtRN0MNW8TLT0X4f6hNS0F9lmjWBzl_OF-wCzoYQiFM7tQsU2UkHC1FHROJbPQDOH6oxDG06u8Nnco07cmLKn60zE4FYDa52DTt1lNGK7GIP97LgrGCHEdJByN4U&connectionData=%5B%7B%22name%22%3A%22livechat%22%7D%5D")
to
http("request_6")
.get(uri1 + "/negotiate?clientProtocol=1.5&Authorization=Bearer%20${token}&connectionData=%5B%7B%22name%22%3A%22livechat%22%7D%5D")
I've got following error:
https://i.postimg.cc/0yTMKrvm/2019-10-12-23-46-37-C-WINDOWS-system32-cmd-exe.png
What am I doing wrong?
Looking at the screenshot, the error you are getting is: No attribute named 'token' is defined .
This suggests that you aren't saving the token from the header Bearer.
Look closely at the HTTP request when you call /api/account - especially the headers, and check that the header exists as you expect. You could use Chrome Dev Tools or any HTTP proxy for this.
You might want to debug your Script in Gatling as well, so that you can see all the variables you are capturing - see this post for some ideas on that - https://www.james-willett.com/debug-gatling/

Unable to print line or reach break point in Gatling 3.0 simulation

So I know we cannot perform DSL operations in before/after of a Gatling simulation, but in 3.0 it does not appear to work at all. If I run the simulation I don't see a print line and I do not reach a break point on the prints. I am using Intellij. I must be missing something obvious, any help would be appreciated
My Simulation:
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class Sample extends Simulation {
val httpProtocol = http
.baseUrl("https://www.google.com")
.inferHtmlResources()
val headers_0 = Map(
"accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding" -> "gzip, deflate, br",
"accept-language" -> "en-US,en;q=0.9",
"cache-control" -> "max-age=0",
"upgrade-insecure-requests" -> "1",
"user-agent" -> "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36")
def before = {
println("In the Before")
}
def after = {
println("All done!")
}
val scn = scenario("Sample")
.exec(http("request_0")
.get("/")
.headers(headers_0)
)
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}
I am using a object to run the simulation. Included below in case it's relevant:
import io.gatling.app.Gatling
import io.gatling.core.config.GatlingPropertiesBuilder
object temp {
def main(args: Array[String]): Unit = {
val simulation = classOf[Sample].getName
val runner = new GatlingPropertiesBuilder
runner.simulationClass(simulation)
Gatling.fromMap(runner.build)
}
}
Problem in chair, not in computer... solution below. Credit to Stéphane Landelle for solution.
import io.gatling.core.Predef._
import io.gatling.http.Predef._
class Sample extends Simulation {
val httpProtocol = http
.baseUrl("https://www.google.com")
.inferHtmlResources()
val headers_0 = Map(
"accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
"accept-encoding" -> "gzip, deflate, br",
"accept-language" -> "en-US,en;q=0.9",
"cache-control" -> "max-age=0",
"upgrade-insecure-requests" -> "1",
"user-agent" -> "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36")
before {
println("In the Before")
}
after {
println("All done!")
}
val scn = scenario("Sample")
.exec(http("request_0")
.get("/")
.headers(headers_0)
)
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
}

Sending multi part form data in post method in play/scala

How can I send multi part form data in post method in play scala
using : scalaVersion:2.11.7
playVersion-2.1.5
You need to do a little code, then you can use it like
val data = MultipartFormData(formFields, "asdasboundarystringas")
WS.url(myUrl).post(data.body)
The code of MultipartFormData you can find on the github: https://gist.github.com/EECOLOR/7649144
UPDATE
Another method, I have been try it with Play 2.4.3
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
class Application extends Controller {
def index = Action {
val url = "http://symlink.dk/code/php/submit/"
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost("http://symlink.dk/code/php/submit/")
val builder = postBuilder.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Symlink does not verify file part, so I am not sure about it, but fileds definitely was send
UPDATE
With Authentication and file verification
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Application extends Controller {
def index = Action {
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val encodedCredentials =
new String(encodeBase64("%s:%s".format(name, password).getBytes))
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Echo of posted data:
{
"args": {},
"data": "",
"files": {
"myFile": "package controllers\n\nimport play.api.Play.current\nimport play.api.libs.ws._\nimport play.api._\nimport play.api.mvc._\nimport com.ning.http.client.AsyncHttpClient\nimport com.ning.http.client.multipart.FilePart\nimport com.ning.http.client.multipart.StringPart\nimport java.io.File\nimport org.apache.commons.codec.binary.Base64.encodeBase64\n\nclass Application extends Controller {\n\n def index = Action {\n// val url = \"http://symlink.dk/code/php/submit/\"\n val url = \"http://httpbin.org/post\"\n\n val name = \"MyUserName\"\n val password = \"MyPassword\"\n\n val encodedCredentials =\n new String(encodeBase64(\"%s:%s\".format(name, password).getBytes))\n\n val asyncHttpClient:AsyncHttpClient = WS.client.underlying\n val postBuilder = asyncHttpClient.preparePost(url)\n val builder = postBuilder\n .addHeader(\"Authorization\", \"Basic \" + encodedCredentials)\n .addBodyPart(new StringPart(\"myField\", \"abc\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField1\", \"abc1\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField2\", \"abc2\", \"UTF-8\"))\n .addBodyPart(new FilePart(\"myFile\", new File(\"app/controllers/Application.scala\")))\n val response = asyncHttpClient.executeRequest(builder.build()).get();\n Ok(response.getResponseBody)\n }\n\n}\n"
},
"form": {
"myField": "abc",
"myField1": "abc1",
"myField2": "abc2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "1991",
"Content-Type": "multipart/form-data; boundary=ZUeOacX0k9AyI7O12kXDuV5gucDyh2IcA",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
UPDATE
just for clarification - if you do not need to send file as part of the form then you do not need to access underlying WSClient and can use trivial WS
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val result = WS.url(url)
.withAuth(name, password, WSAuthScheme.BASIC)
.post(
Map(
"myField" -> Seq("myValue"),
"myField1" -> Seq("myValue1"),
"myField2" -> Seq("myValue2")
)
)
val response = Await.result(result, 10 seconds)
Ok(response.body)
request that this code send:
{
"args": {},
"data": "",
"files": {},
"form": {
"myField": "myValue",
"myField1": "myValue1",
"myField2": "myValue2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "51",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
Thanks Andriy Kuba!
I've made some changes (WS.client.underlying didn't work for me)
I m running with play 2.4.
package utils
import com.ning.http.client.{AsyncHttpClient, ListenableFuture, Request, Response}
import com.ning.http.client.cookie.Cookie
import com.ning.http.client.multipart.{FilePart, StringPart}
/**
* Created by ozma on 27/05/16.
*/
object WsExtend {
def postFile(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): Response = {
postFileAsync(url, files, bodyParams, cookies, headers, encoding).get()
}
def postFileAsync(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): ListenableFuture[Response] = {
val asyncHttpClient:AsyncHttpClient = new AsyncHttpClient()
val postBuilder: AsyncHttpClient#BoundRequestBuilder = asyncHttpClient.preparePost(url)
files.foreach(e => postBuilder.addBodyPart(new FilePart(e._1, new java.io.File(e._2))))
bodyParams.foreach(e => postBuilder.addBodyPart(new StringPart(e._1, e._2, encoding)))
cookies.foreach(c => postBuilder.addCookie(c))
headers.foreach(h => postBuilder.addHeader(h._1, h._2))
val request: Request = postBuilder.build()
asyncHttpClient.executeRequest(request)
}
}
This is how I used it with Silhouette CookieAuthenticator
"cookie" is a header called "Set-Cookie" from login response.
WsExtend.postFile(
url=url,
files = List("fileparamname" -> filepath),
bodyParams = List("albumName" -> albumName),
headers = Map("Cookie" -> cookie)

How do I use Scala dispatch to get the URL returned in a 301 redirect?

I am using Scala dispatch HTTP library, version 0.10.1. I make a request to a URL that returns an HTTP 301, permanent redirect. For example, http://wikipedia.com returns a 301 that redirects to http://www.wikipedia.org/. How do I do I use dispatch to get the redirected URL?
Following the tutorial, here's what I've done.
import dispatch._, Defaults._
val svc = url("http://wikipedia.com")
val r = Http(svc OK as.String)
r()
This throws a "Unexpected response status: 301" exception. Presumably I need to either query the r value for the redirected URL, or maybe specify some argument other than OK in its definition, but I can't figure out what to do from the documentation.
Configure the underlying asyncClient to follow redirects:
val r = Http.configure(_ setFollowRedirects true)(svc OK as.String)
To get the redirected URL:
val svc = url("http://wikipedia.com/")
val r = Http(svc > (x => x))
val res = r()
println(res.getHeader("Location"))
dispatch / reboot v1.2.0:
val myRequest = url(theUrl)
def myGet = myRequest.GET
def myGetFollowRedi = myGet.setFollowRedirects(true)
def myRequestWithHeader = myGetFollowRedi <:< Map(
"User-Agent" -> "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.",
"Accept" -> "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.",
"Accept-Language" -> "de-DE,de;q=0.9,en-US;q=0.7,en;q=0.6,en-GB;q=0.4,nl-NL;q=0.3,nl;q=0.1",
"Accept-Encoding" -> "gzip, deflate, br",
"DNT" -> "1",
"Connection" -> "keep-alive",
"Upgrade-Insecure-Requests" -> "1",
"Sec-Fetch-Dest" -> "document",
"Sec-Fetch-Mode" -> "navigate",
"Sec-Fetch-Site" -> "none",
"Sec-Fetch-User" -> "?1"
)