1

I am using Karate version 1.3.1 for our projects. Currently we have a use case to test an API which is taking a file and a metadata as part of the request.

we are using multipart file and field to write our feature file, but it seems when we check the POsT call on report we don’t see the metadata which is a Json going as part of the request.

As per the suggestion in link: https://github.com/karatelabs/karate/issues/1710

we tried the other approach to use multipart file and value as a parameter but it did not work for us.

Is there any other way to implement this on karate?

note: postman is working without any issues and we get a response too

please help if anyone has faced or resolved this.

Below is my feature file:

def temp = { 'upload': ['name':'test', 'org':123, 'branch': 'xyz', 'amount': 100], 'info': 8900, 'id': 123}

Given url "http://11.111.1.111:1111"

And path "/api/v1/upload

header Content-Type = 'multipart/form-data'

And multipart file file = {read: 'classpath:resources/file/file1.txt', filename: 'file1.txt'}

And multipart file metadata = {value: '#(temp)}

And method POST

print response

Note: I also tried * multipart field metadata = temp (but no luck here)

Response:

content-disposition: form-data; name= file; filename="file1.txt"
content-type: text/plain; charset= UTF-8
content-length: 5300
Completed: true
IsInMemory: true

content-disposition: form-data; name= metadata; filename=""
content-type: application/json; charset= UTF-8
content-length: 100
Completed: true
IsInMemory: true

The issue is when I run the feature file on Karate the api returns me 200 with a blank response. Response: { }

but when the same is executed from Postman it returns me response Response from postman: {id:123, status: ‘Done’}

also I tried the same request with Java okhttpClient request and it worked fine and gave me the expected response.

Is there anything which I am missing while running from Karate?

Implementation of Java Class for OkHttpClient (WORKING):

import okhttp3.*;

import java.io.File;
import java.io.IOException;
import java.util.Map;

public class OkHttpHelper {
    private OkHttpClient client;

    public OkHttpHelper() {
        client = new OkHttpClient();
    }

    public String executeMultipartRequest(String url, Map<String, String> fields, Map<String, String> files) throws IOException {
        MultipartBody.Builder requestBodyBuilder = new MultipartBody.Builder().setType(MultipartBody.FORM);

        // Add fields
        if (fields != null) {
            for (Map.Entry<String, String> field : fields.entrySet()) {
                requestBodyBuilder.addFormDataPart(field.getKey(), null, RequestBody.create(MediaType.parse("application/json"), field.getValue()));
            }
        }

        // Add files
        if (files != null) {
            for (Map.Entry<String, String> file : files.entrySet()) {
                File uploadFile = new File(file.getValue());
                requestBodyBuilder.addFormDataPart(file.getKey(), uploadFile.getName(),
                        RequestBody.create(MediaType.parse("text/plain"), uploadFile));
            }
        }

        RequestBody requestBody = requestBodyBuilder.build();

        // Print requestBody content
        System.out.println("Request Body: " + requestBodyToString(requestBody));

        Request request = new Request.Builder()
                .url(url)
                .post(requestBody)
                .build();

        try (Response response = client.newCall(request).execute()) {
            return response.body().string();
        }
    }

    private String requestBodyToString(RequestBody requestBody) throws IOException {
        Buffer buffer = new Buffer();
        requestBody.writeTo(buffer);
        return buffer.readUtf8();
    }
}

Feature file looks like below:

Feature: Multipart Request with OkHttp

Background:
* def OkHttpHelper = Java.type('com.example.OkHttpHelper')
* def okHttpHelper = new OkHttpHelper()

Scenario: Send Multipart Request
    * def url = 'https://example.com/upload'
    And def fields = { "metadata": '{"key1": "value1"}' }
    And def files = { "file": "path/to/file1.txt" }
    When def response = okHttpHelper.executeMultipartRequest(url, fields, files)
    Then print response

** CURL Command from POSTMAN**

curl -X POST \
  http://11.111.11.111:1111/api/v1/fileupload
  -H 'Accept: */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Cache-Control: no-cache' \
  -H 'Connection: keep-alive' \
  -H 'Content-Length: 5800' \
  -H 'Content-Type: multipart/form-data; boundary=---------23434234234343' \
  -H 'Host: 11.111.11.111:1111' \
  -H 'Postman-Token: XXXXXX-xxxx-xxxx-xxxx-Xxxxxxx,XXXXXXXX' \
  -H 'User-Agent: PostmanRuntime/X.XX.X' \
  -H 'cache-control: no-cache' \
  -H 'content-type: multipart/form-data; boundary=---------23434234234343' \
  -F file@/C:/Test/Sample/file1.txt \
  -F ‘metadata’= { "metadata": '{"key1": "value1"}' }

  • I personally can't give you any more pointers other than thread you have linked already. this may be a little bit of work, but I recommend going through this as well: https://github.com/karatelabs/karate/issues/1645#issuecomment-862502881 - you can't expect people to troubleshoot this without being able to see what your server expects. you can try pasting a cURL export from postman and see if that provides any clues – Peter Thomas Jun 24 '23 at 14:29
  • @PeterThomas : thanks for your response, I have gone through the above thread, for now I have written a separate helper to use OkhttpClient and calling that function in my Feature file. I will try to figure out why the Apache http client was not working with our multipart API request and share my feedback once I have any breakthrough – automation.ninja.08 Jun 25 '23 at 14:03
  • this is not about the apache http client, it is simply that you did not use the right field-names and content-types. who knows, it may not even be a multi-part upload, and you haven't provided any information or cURL example. you could post your okhttp code and remove the actual URL, that would certainly help - but glad you have a workaround. – Peter Thomas Jun 25 '23 at 14:47
  • @PeterThomas: I have updated the question with the okhttpHelper implementation. Please suggest if you see any issues and let me know if there is anything if I was missing while using karate multipart – automation.ninja.08 Jun 25 '23 at 17:15
  • Also added the curl command with the question – automation.ninja.08 Jun 25 '23 at 18:10
  • the okhttp code says `field1`, `file1` - but the curl says: `file`, `metadata`. so which one is correct ? – Peter Thomas Jun 26 '23 at 04:35
  • @PeterThomas: it was just a sample with dummy values I have updated, I had just updated the implementation as well as the sample curl command – automation.ninja.08 Jun 26 '23 at 13:01

1 Answers1

0

As far as I can tell, this should work:

* url 'https://httpbin.org/anything'
* multipart file file = { read: 'myfile.txt' }
* multipart field metadata = { some: 'data' }
* method post

You can experiment by pointing your okhttp or postman test to https://httpbin.org/anything and see what are the differences. The response will tell you all the field values and file values sent in the request.

Peter Thomas
  • 54,465
  • 21
  • 84
  • 248