Marco
Marco

Reputation: 155

Why does my multi part post request fail when sending from Marklogic instead of a browser form?

I am trying to send a multi part post request from my local Marklogic server using this xquery script:

xquery version "1.0-ml";

let $uri := "http://uri_to_service" 

let $data := 
'------WebKitFormBoundaryq3PKI0zfbTv08rDu

Content-Disposition: form-data; name="projectId"

1DBC9DEE-6B5D-0001-D76C-13F516502B00
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="language"

de
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

Das ist ein Test.
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="submit"

Submit
------WebKitFormBoundaryq3PKI0zfbTv08rDu--
'

let $options :=
    <options xmlns="xdmp:http">
        <authentication method="basic">
            <username>abc</username>
            <password>123</password>
        </authentication>
        <data>{$data}</data>
        <headers>
            <Connection>keep-alive</Connection>
            <Cache-Control>max-age=0</Cache-Control>
            <Accept>text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8</Accept>
            <Origin>null</Origin>
            <User-Agent>Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36</User-Agent>
            <Content-Type>multipart/form-data; boundary=----WebKitFormBoundaryq3PKI0zfbTv08rDu</Content-Type>
            <Accept-Encoding>gzip,deflate,sdch</Accept-Encoding>
            <Accept-Language>en-US,en;q=0.8,de;q=0.6</Accept-Language>
       </headers>
    </options>

return 
    xdmp:http-post($uri, $options)

In Wireshark I see the following outgoing request:

POST /api/extract HTTP/1.1
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryq3PKI0zfbTv08rDu
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,de;q=0.6
From: [email protected]
Host: some_service_uri
Content-Length: 509
Authorization: Basic some_basic_code

------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="projectId"

1DBC9DEE-6B5D-0001-D76C-13F516502B00
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="language"

de
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

Das ist ein Test.
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="submit"

Submit
------WebKitFormBoundaryq3PKI0zfbTv08rDu--
HTTP/1.1 400 Bad Request
Server: nginx/1.6.1
Date: Fri, 22 Aug 2014 14:18:47 GMT
Content-Type: text/html;charset=utf-8
Content-Length: 1246
Connection: keep-alive
Set-Cookie: JSESSIONID=B677A4E57DB4E8E8076EB4C9DD3E0AF4; Path=/extractor

<html><head><title>Apache Tomcat/6.0.36 - Error report</title><style><!--H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR {color : #525D76;}--></style> </head><body><h1>HTTP Status 400 - Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly</h1><HR size="1" noshade="noshade"><p><b>type</b> Status report</p><p><b>message</b> <u>Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: Stream ended unexpectedly</u></p><p><b>description</b> <u>The request sent by the client was syntactically incorrect.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/6.0.36</h3></body></html>

As you can see, the request is failing for some reason.

Then I tried the same request from Chrome Browser with a small html form.

<html>
<head>
    <title>Test Form</title>
</head>
<body>

    <form action="service_uri" method="post" enctype="multipart/form-data">
        <input type="text" name="projectId" value="1DBC9DEE-6B5D-0001-D76C-13F516502B00">
        <input type="text" name="language" value="de">
        <label for="file">Filename:</label>
        <input type="file" name="file" id="file"><br>
        <input type="submit" name="submit" value="Submit">
    </form>

</body>
</html>

The browser asks me for username/password and everything goes fine.

In Wireshark I can see:

POST /api/extract HTTP/1.1
Host: some_service_uri
Connection: keep-alive
Content-Length: 527
Cache-Control: max-age=0
Authorization: Basic some_basic_code
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: null
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.143 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryq3PKI0zfbTv08rDu
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,de;q=0.6
Cookie: JSESSIONID=469591D4A83F24BB77547B6C235F25B7

------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="projectId"

1DBC9DEE-6B5D-0001-D76C-13F516502B00
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="language"

de
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain

Das ist ein Test.
------WebKitFormBoundaryq3PKI0zfbTv08rDu
Content-Disposition: form-data; name="submit"

Submit
------WebKitFormBoundaryq3PKI0zfbTv08rDu--
HTTP/1.1 200 OK
Server: nginx/1.6.1
Date: Fri, 22 Aug 2014 13:38:04 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive

80
{"text":"Das ist ein Test.\n","metadata":{},"document":{"freeTerms":[{"textValue":"test","score":100,"frequencyInDocument":1}]}}
0

Why is my request failing when send from Marklogic? Based on the outgoing request (captured by Wireshark) I can find no difference, except Content-Length.

What is happening? Or what could be the reason? Could encoding change the Content-Length?

Upvotes: 2

Views: 1245

Answers (1)

mblakele
mblakele

Reputation: 7842

The server error was Stream ended unexpectedly so content-length seems like a good candidate: 527 vs 509.

Rather than writing your own multipart code, have you tried this library? https://github.com/ableasdale/consultant-tools/blob/da92815e1322fe8e479ba2ba3741857670498c2a/src/main/resources/modules/example/lib-multipart-post.xqy

One key difference is that it uses https://docs.marklogic.com/xdmp:multipart-encode

Upvotes: 1

Related Questions