简体   繁体   中英

Spring RestTemplate: getting 403 forbidden for multipart/form-data but working with curl

I am using spring rest-template to POST request form-data of 1 file and 1 string parameter, here is code:

    HttpHeaders headers = new HttpHeaders();
    headers.set("Authorization", "Bearer ...");
    httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
    File file=new File("src\main\resources\test.json");
    BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
    byte[] fileBytes = toByteArray(in);

    MultiValueMap<String, String> fileMap = new LinkedMultiValueMap<>();
    ContentDisposition contentDisposition = ContentDisposition
            .builder("form-data")
            .name("file")
            .filename("test.json")
            .build();
    fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString());
    fileMap.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
    org.springframework.http.HttpEntity<byte[]> fileEntity =
            new org.springframework.http.HttpEntity<>(fileBytes, fileMap);

    MultiValueMap< String, Object > body = new LinkedMultiValueMap<>();
    body.add("stringFormInput", "xyz");
    body.add("file", fileEntity);
    org.springframework.http.HttpEntity< MultiValueMap< String, Object > > entity =
            new org.springframework.http.HttpEntity<>(body, httpHeaders);

    ResponseEntity< JsonNode > responseEntity =
            restTemplate.postForEntity("https://uploadFile", entity, JsonNode.class);

But I'm getting 403 FORBIDDEN response

However, If I use curl command below, it executes successfully

curl --location --request POST 'https://uploadFile' \
--header 'Content-Type: multipart/form-data' \
--header 'Authorization: Bearer ...' \
--form 'file=@/D:/resources/test.json' \
--form 'stringFormInput=xyz' \

I also tried with httpClient , still, it is 403 with no any cause message

HttpPost post = new HttpPost("https://uploadFile");
post.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA_VALUE);
post.setHeader(HttpHeaders.AUTHORIZATION, "Bearer ...");

File file=new File("src\main\resources\test.json");
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
builder.addBinaryBody("file", file, ContentType.DEFAULT_BINARY, "test.json");
builder.addTextBody("stringFormInput", "xyz", ContentType.DEFAULT_BINARY);
HttpEntity entity = builder.build();

post.setEntity(entity);
HttpClient httpClient = HttpClientBuilder.create().build();
HttpResponse response = httpClient.execute(post);

EDIT

For now I did a workaround by executing curl from JAVA

    File file=new File("src\main\resources\test.json");
    String[] command = {"curl", "--location",
            "--request", "POST", "https://uploadFile",
            "--header", "Content-Type: multipart/form-data",
            "--header", "Authorization: Bearer ...",
            "-F", "file=" + "@"+file.getPath(),
            "--form", "stringFormInput=xyz"};

    ProcessBuilder builder = new ProcessBuilder(command);
    builder.redirectErrorStream(true);

    String curlResult = "";
    String line = "";

    try {
        Process process = builder.start();
        BufferedReader r = new BufferedReader(new InputStreamReader(process.getInputStream()));
        while (true) {
            line = r.readLine();
            if (line == null) {
                break;
            }
            curlResult = curlResult + line;
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

So I faced a similar problem that cURL was executing properly but Spring code was giving 403. The problem lies with the target which is receiving this request. Few web servers like Nginx required mandatory headers like "User-Agent" by default which can be disabled.

By default, Spring doesn't pass any extra header. Try adding "User-Agent" if the target is using Ngnix or find what web server they are using.

Sharing my code for reference.

  1. This code gave 403

    HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);

  2. this code worked fine.

    HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA); httpHeaders.add("User-Agent", "PostmanRuntime/7.26.3");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM