How to send a multipart request with only one json field? - karate

I'm trying to send a multipart request with one field but I cannot find it in the logs. My code is
Feature: test
Scenario: test send
Given url 'https://apitester.com/api/send'
And multipart field myJson = {test:'send'}
When method post
Then status 200
but in the logs I find only
1 > POST https://apitester.com/api/send
1 > Accept-Encoding: gzip,deflate
1 > Connection: Keep-Alive
1 > Content-Length: 226
1 > Content-Type: multipart/mixed; boundary=57Gy9v3RTbI82kmdNf-nsWld3wK1rz6W99F
1 > Host: apitester.com
1 > User-Agent: Apache-HttpClient/4.5.12 (Java/14.0.1)
In Postman I get something like this and it's working fine:
POST /api/send HTTP/1.1
Host: apitester.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
----WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="myJson"
{"test":"send"}
----WebKitFormBoundary7MA4YWxkTrZu0gW
If I add And header Content-Type = 'application/json' it gets somehow similar but it's not working either:
1 > POST https://apitester.com/api/send
1 > Accept-Encoding: gzip,deflate
1 > Connection: Keep-Alive
1 > Content-Length: 218
1 > Content-Type: application/json; boundary=bzLjH96ptD4G7HSRWI65XMnIhllxtiO
1 > Host: apitester.com
1 > User-Agent: Apache-HttpClient/4.5.12 (Java/14.0.1)
--bzLjH96ptD4G7HSRWI65XMnIhllxtiO
Content-Disposition: form-data; name="myJson"
Content-Type: application/json; charset=UTF-8
Content-Transfer-Encoding: 8bit
{"test":"send"}
--bzLjH96ptD4G7HSRWI65XMnIhllxtiO--
How can I troubleshoot this?

Yes, if the Content-Type is not "printable" (e.g. binary) Karate doesn't log it.
On troubleshooting, this can be difficult, but if you work with your server-side folks you should be able to figure it out sooner. If you post a cURL command that works, the community here can help you.
We'll improve the logging in future versions.

Related

Having trouble getting content-encoding to show up in response header for get request

I was trying to write a karate test that validated that a particular response header contained the Content-Encoding header field with a value of gzip. I tried on my api where both times the content-encoding field was missing from karate's response. Both of these endpoints returned the content-encoding field on postman and curl commands.
I then tried to hit the postman-echo service to see if it was my api endpoint that karate was having issues with and it seems that it is not only my api. Could someone take a look at my code and see if I am doing something incorrectly to get the header field to show up in the response?
Feature: test getting Content-Encoding
Background:
* url 'https://postman-echo.com/gzip'
Scenario:
Given header Accept-Encoding = 'gzip'
When method get
Then status 200
And match responseHeaders contains {'Content-Encoding':'#present'}
This is what karate request looks like
1 > GET https://postman-echo.com/gzip
1 > Accept-Encoding: gzip
1 > Connection: Keep-Alive
1 > Host: postman-echo.com
1 > User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_252)
and the response looks like
1 < 200
1 < Connection: keep-alive
1 < Content-Type: application/json; charset=utf-8
1 < Date: Fri, 08 May 2020 16:18:42 GMT
1 < ETag: W/"ef-7kclc8pzXTvQiPUaEOf6j95iFaE"
1 < Vary: Accept-Encoding
1 < set-cookie: sails.sid=s%3A6G_FShPRZH4V1G-tVDfUEEfMwQQmolo5.T2Cb37zqYA21FTyRyIGutVWQWo9ta4EWiod36%2FkM88I; Path=/; HttpOnly
{
"gzipped": true,
"headers": {
"x-forwarded-proto": "https",
"x-forwarded-port": "443",
"host": "postman-echo.com",
"x-amzn-trace-id": "Root=1-5eb58662-c4aaeec26efd116ac0544a18",
"accept-encoding": "gzip",
"user-agent": "Apache-HttpClient/4.5.12 (Java/1.8.0_252)"
},
"method": "GET"
}
The curl response header is
curl --location --request GET 'https://postman-echo.com/gzip' \
> --header 'Accept-Encoding: gzip' -I
HTTP/2 200
date: Fri, 08 May 2020 16:21:53 GMT
content-type: application/json; charset=utf-8
content-length: 220
content-encoding: gzip
etag: W/"dc-BuD8DN1qXT7trYUQtZOuSvbq1pM"
vary: Accept-Encoding
set-cookie: sails.sid=s%3Aj86lznX3nK20fnEN4B3nbHESrfWqVJ3M.236VrsmQp7V%2F7%2BrvG%2FEtlc9yUVLTtylh1yyIAdQJSiY; Path=/; HttpOnly
This seems to be the way the Apache HttpClient works or how it is configured for Karate. I just found you get the header back with karate-jersey:
1 > GET https://postman-echo.com/gzip
1 > Accept: */*
1 > Accept-Encoding: gzip
1 > User-Agent: Jersey/2.30 (HttpUrlConnection 1.8.0_231)
22:40:48.981 [ForkJoinPool-1-worker-1] DEBUG com.intuit.karate - response time in milliseconds: 1177.37
1 < 200
1 < Connection: keep-alive
1 < Content-Encoding: gzip
1 < Content-Length: 248
1 < Content-Type: application/json; charset=utf-8
1 < Date: Fri, 08 May 2020 17:10:48 GMT
1 < ETag: W/"f8-sigbV4PuNI2Fx08AqzMEqW1WIYY"
1 < Vary: Accept-Encoding
So if Jersey is ok for the rest of your tests, maybe that's all you need. Getting this to work for karate-apache is not a priority for me so if you or anyone else is willing to investigate or fix it, that would be great.

UI automation code on a frame, works fine in Chrome/MSEdge but fails in Firefox and Safari

I'm using Karate v0.9.6.RC1. The code is something like this:
* switchFrame(1)
And input('input[name='cardnumber']','xxxxxxx')
This works fine in Chrome or Edge browser but fails in Firefox or Safari. I tried using different methods like Click, Input, Retry etc after switching to frame but Firefox/Safari doesn't even recognise the object. Also tried different locators. It fails with the below error:
21:14:08.687 request:
101 > POST http://localhost:4444/session/803f524c-3eda-8d46-b1f3-b7ee4c9bc83a/element
101 > Accept-Encoding: gzip,deflate
101 > Connection: Keep-Alive
101 > Content-Length: 59
101 > Content-Type: application/json; charset=UTF-8
101 > Host: localhost:4444
101 > User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_242)
{"using":"css selector","value":"input[name='cardnumber']"}
21:14:08.692 response time in milliseconds: 4.54
101 < 404
101 < cache-control: no-cache
101 < content-length: 302
101 < content-type: application/json; charset=utf-8
101 < date: Sun, 12 Apr 2020 13:14:08 GMT
{"value":{"error":"no such element","message":"Unable to locate element:
input[name='cardnumber']","stacktrace":"WebDriverError#chrome://marionette/content/error.js:175:5\nNoSuchElementError#chrome://marionette/content/error.js:387:5\nelement.find/
21:14:08.692 http response code: 404, response: {"value":{"stacktrace":"WebDriverError#chrome://marionette/content/error.js:175:5\nNoSuchElementError#chrome://marionette/content/error.js:387:5\nelement.find/ POST http://localhost:4444/session/803f524c-3eda-8d46-b1f3-b7ee4c9bc83a/element
102 > Accept-Encoding: gzip,deflate
102 > Connection: Keep-Alive
102 > Content-Length: 59
102 > Content-Type: application/json; charset=UTF-8
102 > Host: localhost:4444
102 > User-Agent: Apache-HttpClient/4.5.12 (Java/1.8.0_242)
{"using":"css selector","value":"input[name='cardnumber']"}
I'm not sure if I'm missing something here. Any inputs would be appreciated.
Yes I don't think the FF and Safari browsers implement frame-switching correctly. I could be wrong, but having tried a bit and given up - you are welcome to dig into the code / spec and fix this. PR-s welcome !
I also suggest exploring if you can achieve this via JS, here are some ideas: https://stackoverflow.com/a/60800181/143475
Note that Karate is very easy to contribute to, we have a detailed guide: https://github.com/intuit/karate/wiki/Developer-Guide

Creating a user using the SonarQube API returns a 401

I'm trying to create a user using the SaonarQube API (version 6.2 or up).
I have setup a SoapUI project that contains a few test scripts. One of them is login in and creating a user. this one returns a 401 whe the user creation call is done.
The login is used for other calls as well and proves to work. Except for the create user call. The account used to login to SoarQube is member of the System Administror groups.
Below is the raw request.
POST http://localhost:9000/api/users/create HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 47
Host: localhost:9000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Cookie: JWT-SESSION=eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJBV0ExaGFtX2hnNWdHUWtNNVRHSiIsInN1YiI6ImFkbWluIiwiaWF0IjoxNTEyNzI2NDQwLCJleHAiOjE1MTI5ODU2NDAsImxhc3RSZWZyZXNoVGltZSI6MTUxMjcyNjQ0MDM4MywieHNyZlRva2VuIjoicHRwcXRlYmtzYTR2MTlhaTk3anV0bnVlZW8ifQ.waHqOsMJ9P6FyIOUWuVODl5QcW-IJp10G6oUAvy1DWk; XSRF-TOKEN=ptpqtebksa4v19ai97jutnueeo
Cookie2: $Version=1
login=user01&name=name01&password=%21P%40ssw0rd
Below is the raw resoonse
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Length: 0
Date: Fri, 08 Dec 2017 09:47:20 GMT
Any suggestions are welcome.
BTW: I can create the user using the same values using the UI so there is no issue with he user information, at least it seams so.
Update 1:
Added raw request with querystring parameters
POST http://localhost:9000/api/users/create?login=user01&name=name01&password=%21P%40ssw0rd HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 0
Host: localhost:9000
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Cookie: JWT-SESSION=eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJBV0JHZkVGY0h3bW5UZ0V5QklJNyIsInN1YiI6ImFkbWluIiwiaWF0IjoxNTEzMDExMDM2LCJleHAiOjE1MTMyNzAyMzYsImxhc3RSZWZyZXNoVGltZSI6MTUxMzAxMTAzNjQyNCwieHNyZlRva2VuIjoibmIzdmlpcjAyZmZ1ODJnMzNtdW1hYWdkN3QifQ.ur8eZkW1CwNinx4tInFsbkGLQTHQ6yFjheRfup8Z4fQ; XSRF-TOKEN=nb3viir02ffu82g33mumaagd7t
Cookie2: $Version=1
It's not possible to use the generated cookie by a web request in a console request (it could be considered as an attack).
You need either to :
Specify a user token (recommended way)
Specify a login/password

will Accept Http Headers digest any other formats other than the one specified?

Per my understanding:
the Accept header is used by HTTP clients to tell the server what content types they'll accept. The server will then send back a response, which will include a Content-Type header telling the client what the content type of the returned content actually is.
With this understanding, I tried the following:
curl -X GET -H "Accept: application/xml" http://www.google.com -v
* About to connect() to www.google.com port 80 (#0)
* Trying 173.194.33.81...
* connected
* Connected to www.google.com (173.194.33.81) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8y zlib/1.2.5
> Host: www.google.com
> Accept: application/xml
>
< HTTP/1.1 200 OK
< Date: Tue, 02 Sep 2014 17:58:05 GMT
< Expires: -1
< Cache-Control: private, max-age=0
< Content-Type: text/html; charset=ISO-8859-1
< Set-Cookie: PREF=ID=5c30672b67a74789:FF=0:TM=1409680685:LM=1409680685:S=PsGclk3vR4HWjann; expires=Thu, 01-Sep-2016 17:58:05 GMT; path=/; domain=.google.com
< Set-Cookie: NID=67=rPuxpwUu5UNuapzCdbD5iwVyjjC9TzP_Ado29h3ucjEq4A_2qkSM4nQM3RO02rfyuHmrh-hvmwmgFCmOvISttFfHv06f8ay4_6Gl4pXRjqxihNhJSGbvujjDRzaSibfy; expires=Wed, 04-Mar-2015 17:58:05 GMT; path=/; domain=.google.com; HttpOnly
< P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."
< Server: gws
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: SAMEORIGIN
< Alternate-Protocol: 80:quic
< Transfer-Encoding: chunked
<
<!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="en"><
As you can notice in the response, I am sent Content-Type: text/html; charset=ISO-8859-1 which is not what I asked for?
why does a different representation (HTML in this case) is sent, although I asked for xml?
Thanks
From RFC 2616:
If an Accept header field is present,
and if the server cannot send a response which is acceptable
according to the combined Accept field value, then the server SHOULD
send a 406 (not acceptable) response.
Here, "should" means that Google aren't actually obliged to throw a 406 error. But since you're receiving an HTML response, it has effectively the same meaning.

First request from BizTalk WCF-Custom adapter not pre-authenticated

The first request (or batch of requests) I send from a WCF-Custom adapter using the wsHttpBinding (also tried basicHttp) does not include the Authorization Header.
Request 1 Headers
POST https://axis2service.com/HttpSoap12Endpoint/ HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Host: axis2service.com
Content-Length: 556
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
The service returns a 401 to which I respond with the below.
Request 2 Headers
POST https://axis2service.com/HttpSoap12Endpoint/ HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
Authorization: Basic XXXXXX
Host: axis2service.com
Content-Length: 556
Expect: 100-continue
Accept-Encoding: gzip, deflate
To which the axis2 on apache service responds with a 504 and Connection: close
This seems to be a known issue, how can I make request 1 include the Authorization header every time?
Note: The request 1 headers only get sent on the first request after a Host Instance restart. All subsequent requests from the adapter use the request 2 headers therefore bypassing the handshake stage.