POST bodyPart type mismatch

Hey Stéphane,

Im trying to post a file over https. reading from Gatling 2 doc, this is the line i tried to use:

  • FileBodyPart(name, file, charset, contentType, transferEncoding, contentId)

I got this in my script:

.exec(
http(“PostMKV”)
.post("/xx")
.param(“metadata”, “”“someString”"")
.bodyPart(FileBodyPart(“10mbtest”, “dogkitten.mkv”, Some(“UTF-8”),“application”, “binary”, “contentId”)))

but i got compile error:

type mismatch;
found : String(“binary”)
required: Option[io.gatling.core.session.Session => io.gatling.core.validation.Validation[String]]
16:00:57.765 [ERROR] i.g.a.ZincCompiler$ - .bodyPart(FileBodyPart(“10mbtest”, “dogkitten.mkv”, Some(“UTF-8”),“application”, “binary”, “contentId”)))

anything i missed or did wrong?

Thanks

I advice you use the builder methods: https://github.com/excilys/gatling/blob/2.0.0-M3X/gatling-http/src/main/scala/io/gatling/http/request/BodyPart.scala#L101-L104

im using snapshot version so i guess it should be this one? https://github.com/excilys/gatling/blob/master/gatling-http/src/main/scala/io/gatling/http/request/BodyPart.scala#L68-L72

.exec(
http(“PostMKV”)
.post("/xx")
.param(“metadata”, “”“someString”"")
.bodyPart(FileBodyPart(“10mbtest”, “dogkitten.mkv”))
.charset(“Some"UTF-8"”)
.contentType(“application”)
.tranferEncoding(“binary”))

if i dont really need contentId

this is working well

.exec(
http(“PostMKV”)
.post("/xxx")
.param(“metadata”, “”“someString”"")
.bodyPart(FileBodyPart(“10mbtest”, “dogkitten.mkv”)
.charset(“UTF-8”)
.contentType(“application”)
.transferEncoding(“binary”)))

one more questions, i know for each session, gatling itself maintains a userId, which is a unique value. Do you know how i can refer it? i tried ${userId} as the session data listed but didnt work.

hmm, i got a 400. maybe i should not use rawFileBody for a video file?

exec(
http(“PostMKV”)
.post(“xxx”)
.header(“Content-Type”, “multipart/form-data”)
.param(“metadata”, “”“xxx”"")
.bodyPart(RawFileBodyPart(“10mbtest”, “blah.mkv”)
.contentType(“application”)
.fileName(“blah.mkv”)
.transferEncoding(“binary”)))

I noticed the request sent out was missing Content-Disposition: form-data; and filename=“dogkitten.mkv”

if i sent that in jmeter, it will look like this:

-----------------------------7d159c1302d0y0
Content-Disposition: form-data; name=“10mbtest”; filename=“dogkitten.mkv”
Content-Type: application
Content-Transfer-Encoding: binary

<actual file content, not shown here>
-----------------------------7d159c1302d0y0–

but in gatling, it looked like this:

maybe i should use the hack you provided in this post? https://groups.google.com/forum/#!topic/gatling/F4Wbi735oYg

tried .asMultipartForm, no luck. still 400, bad request.

in gatling, it looked like this:

Could you really compare the HTTP requests with Charles, please?

The only difference I see from my side is that AsyncHttpClient forces “; charset=utf-8” in the Content-Type. Could this be the problem?

I’ve fixed AsyncHttpClient and Gatling so that charset is not force for File parts.

Here’s what I get:

–Bh2ZFsRsLn1Zhm7iw9-fftHL6TMcHFb0riIo
Content-Disposition: form-data; name=“10mbtest”; filename=“blah.mkv”
Content-Type: application
Content-Transfer-Encoding: binary

<actual file content, not shown here>

–Bh2ZFsRsLn1Zhm7iw9-fftHL6TMcHFb0riIo–

Looks good to me.

i think i was doing something wrong and the 400 is actually complaining about duplicate file and id. so nothing to do with gatling. and i was using an old snapshot version so i dont think charset utf-8 was the problem. Sorry for bugging you so long for my fault. i got correct response after using a new user id. this is the code if it can benefit other ppl.

exec(
http(“PostMKV”)
.post("/xxx")
.header(“Content-Type”, “multipart/form-data”)
.param(“metadata”, “”“string”"")
.bodyPart(RawFileBodyPart(“10mbtest”, Properties.fileName)
.contentType(“application”)
.fileName(Properties.fileName)
.transferEncoding(“binary”))
.asMultipartForm)

One more question, how can i use the built-in session userId? i could not get it by just use ${userId}. since our system requires unique user id for each post, i guess use gatling session id is a good idea. use random ids will get overlap eventually if we run the test for a long time.

Hi Stéphane,

maybe it was very obvious for my last question, i just list it here. i want to have a unique id for every single loop across many gatling processes. So i was thinking using the built-in session ID. But i could not reference it, do you know to get that? i printed the session and saw userId as the attribute name, but simply ${userId} doesnt work.

Thanks,
Kan

The userId is not a Session attribute, stored in the Map. One of the reason is that we don’t want anyone to mess up with it and maybe remove it or whatever.
https://github.com/excilys/gatling/blob/master/gatling-core/src/main/scala/io/gatling/core/session/Session.scala#L65

If you want to access it, you have to write a function.

I see. i will write a function to read that. Just want to confirm, even for the same user but different loop, the userId will change, right? I noticed that with a single thread test.

?
No, the userId is supposed to be final for a given virtual user.

if not how can i implement a counter thats shared by all sessions?

a global AtomicInteger that you increment in exec function?

i will try that out. so gatling doesnt have something like counter in jmeter.

Nope.
Provide a use case that would justify that we implement something like this and we’ll consider it.

not necessarily, i think AtomicInteger or AtomicLong should be enough in most cases.