Can Content-Disposition filename be used for text fields in multipart forms with Spring Webclient? - spring

Working with the Service-Now API (for example) requires the request to provide the following:
POST /api/now/attachment/upload HTTP/1.1
Host: somehost.testenv.com
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MadHyZrFTrZu0gW
cache-control: no-cache
Content-Disposition: form-data; name="table_name"
some_table
Content-Disposition: form-data; name="table_sys_id"
82c9aca7kljasdfkljhasdfec8dfdb61d961920
Content-Disposition: form-data; name="uploadFile"; filename="undefined"
Content-Type: file
------WebKitFormBoundary7MA4YWxkTrZu0gW—
The above is generated from using Postman and providing form-data key value pairs.
However, based off the abstract of the RFC that defines Content-Disposition: https://www.rfc-editor.org/rfc/rfc2183.
Two values for this
header field are described in this memo; one for the ordinary linear
presentation of the body part, and another to facilitate the use of
mail to transfer files.
The Content-Disposition class used in Spring Webflux (https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/http/ContentDisposition.html) contains only an internal field for "filename" that is a string.
Is the ContentDisposition class in org.springframework.http missing a component as per RFC-2183 regarding a standard value (ordinary linear presentation of the body part)?
The HTTP request that is generated by the spring code automagically is as follows:
POST /api/now/attachment/upload HTTP/1.1
user-agent: ReactorNetty/0.7.9.RELEASE
transfer-encoding: chunked
host: somehost.testenv.com
accept: */*
accept-encoding: gzip
Content-Type: multipart/form-data;boundary=o-0JsSvUdGo98NDHJSWTwjvgzlRSXsmJ98-pWQ;charset=UTF-8
This is the source code that generates the above HTTP request:
MultipartBodyBuilder mbuilder = new MultipartBodyBuilder();
mbuilder.part("table_name", snConfig.getChangeRecordTableName());
mbuilder.part("table_sys_id", result.get(0).getSysId());
mbuilder.part("uploadFile", someFile);
return client.post()
.uri(snConfig.getEndpointAttachmentUpload())
.contentType(MediaType.MULTIPART_FORM_DATA)
.syncBody(mbuilder.build())
.retrieve()
.bodyToMono(AttachmentUploadResult.class);
It looks like the code is storing all of the MultipartBodyBuilder components into a single multipart/form-data, which is not the same format as the working HTTP Request.
However, even by manually providing the Content-Disposition headers, one can only create a name/value pair where the value is the "filename".
Is Content-Disposition missing functionality? Is this possible with WebClient?

Looks like this isn't supported within WebClient after digging on this for a long while.

Related

Nifi/Minifi: How to read multipart/form-data request

I'm using HandleHttpRequest processor to receive a request with Content-Type: multipart/form-data. The request contains a text param and a file (Content-Type: image/jpeg). How can I read this parameters, and put them into attributes?

Mail RFC embedded image using cid for text/plain

While I remember email messages could contain embedded images in HTML and plain text I noted today Outlook 2013 and Windows 10 Mail app does not display it.
Is this something the RFC standard has removed the "[cid:]" definition?
Below is the formatted mail:
(save as *.eml to display its content)
MIME-Version: 1.0
Date: Tue, 6 Feb 2018 10:12:53 +0100
From: Test User 2 <test.user2#lab.local>
Subject: TEst in plain text
Thread-Topic: TEst in plain text
To: Test User 1 <test.user1#lab.local>
Content-Type: multipart/mixed;
boundary="_60A9E784-DBBE-4378-9A84-01D36C2226AF_"
--_60A9E784-DBBE-4378-9A84-01D36C2226AF_
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset="utf-8"
test
[cid:BBCLOGO#23AD2D600E]
--_60A9E784-DBBE-4378-9A84-01D36C2226AF_
Content-Type: image/jpg; name="23AD2D600EF4C69FF4D5479A8BB7FE73.jpg"
Content-ID: <BBCLOGO#23AD2D600E>
Content-Transfer-Encoding: base64
Content-Disposition: inline;
filename="23AD2D600EF4C69FF4D5479A8BB7FE73.jpg"
/9j/4AAQSkZJRgABAgAAZABkAAD/2wBDAAIBAQEBAQIBAQIDAgECAwMCAgICAwMDAwMDAwMFAwQE
BAQDBQUFBgYGBQUHBwgIBwcKCgoKCgwMDAwMDAwMDAz/2wBDAQICAgQDBAcFBQcKCAcICgwMDAwM
DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCAAyADIDAREA
AhEBAxEB/8QAHAAAAgIDAQEAAAAAAAAAAAAAAAcFCAIEBgMJ/8QAOBAAAQIFAQYBBw0BAAAAAAAA
AQIDAAQFBhETBwgSITFRQTQ1QmFicYEUFiIyMzZDY3KEkZSh8P/EABoBAAIDAQEAAAAAAAAAAAAA
AAAFAgMEBgH/xAAnEQACAgECBQMFAAAAAAAAAAAAAQIRAwQxBRIhUYEyQcEiYZHw8f/aAAwDAQAC
EQMRAD8A+mmqvvHWUJw1V94KAk7YtG67zmzJWzJuTTqcaikBKUIz041rwlOccsmKsmWONXJ0SjBy
2Oxn93W76Lbc3cVbmWwZZovCUkm1zLyiPROAgD1kE4HOMsdfCUkkvguenaVsXeqvvG+jOGqvvBQB
qr7wUBjABtUOmKrVak6MhXAubfalgrGcF1wIzj4xGcuVN9j2Kt0Wyt23KPalIaodCZSxT2RhKU9V
HxUo+Kj4kxzGTI5u2NYxUVSN6IEhBbzVl0e3Lgkq7R2ksCqJeMwy2MI1WSjKwByBUFjOPEZ6kw74
dmc4tP2MGpgk7XuLKGJmCAAgAmNnzM1MX1R0SbZdmBOSywhHMkIeSs/wBmKs7ShK+xPH6kWyjmBq
EACd3tZeZXLUKbSgmTbVNtrc9ELcDSkpPrIQT8Ia8La+rwY9WthLw3MYQAEAEhalbNtXNT7g4StM
nMNTCm0nBWlCwpSQT0yMiIZYc8Wu6JQlTTLbsPszTCJmXUFsOJC0LT0UlQyCPeI5dqhsZx4Ak962
4kO1GmWq0DxMoXPPHIxl06SBjuAhR+MOOGY+jl4MWql1SFDDQyBAAQAEAFm9hE9P1HZVSX6ivjcS
h1htRAB0mX1stg47JSB7hHO62KWV0MsDuCOvjKXFV9rdQqFR2lVp6pK4nkTb0ujljDTKy00AB7CR
7+sdLpYpY412FeV3JnOxeVhABk006+4llhJW8shKUJBJJPIAAQN0B3dm7u9+3OUTFUbFJpZwS5OA
6xHssjCs/qKYxZdfCG3Vl8NPKX2LDUyny9Jp0vS5QYlJZtEu0D4IbSEJ/wAEIZS5nYwSpUe8eHor
9tmw2rXxWPnVbLzQqGkhp6UeyjULecKS5zGSCBggDl1hlo9Ysa5ZbGXNgcnaErcNqXHak38iuOSd
lH8kJ1kkJXjqULH0VD1pJhvjyxmri7McoOO5HxMiOfdf+zd82dXOnnXw6/lwp4j5+P6bNN4+Rxwp
NgQAEABABD3591pryD6o8++RdfxItwepb+NyGTb28lZP6Hl//ft46L87fvkWH//Z
--_60A9E784-DBBE-4378-9A84-01D36C2226AF_--
You're referring to RFC 2387, "The MIME Multipart/Related Content-type"
To refer to an attachment by the value of its Content-ID (CID) MIME header field, it's as simple as:
<img src="cid:BBCLOGO#23AD2D600E">
Note that your body must be HTML, such as Content-Type: text/html; chaset="us-ascii", as indicated by RFC 2045 §5.
Outlook should do this automatically when you place images in your message body. If you need further help configuring that, there is probably a more appropriate Q&A site than (the programming-centric) Stack Overflow.

Getting Jmeter to generate the boundary dashes in the Content-Type header (eg boundary=--V0a4bfux...)

This what my HTTP request is generating
Content-Type: multipart/form-data; boundary=V0a4bfuxfGhaH_Voo_Gu6oAEtj5FJNcp; charset=UTF-8
However, when compared to the POST data, it is lacking the 2 dashes in the front, which causes the server to reject the request:
--V0a4bfuxfGhaH_Voo_Gu6oAEtj5FJNcp
Content-Disposition: form-data; data="dataToBeSent"
--V0a4bfuxfGhaH_Voo_Gu6oAEtj5FJNcp--
How do I get Jmeter to generate the dashes in the header?
(besides from manually creating the multipart form)
Note:
I am using the 'Use multipart/formdata for POST' option.
If I intercept the request and manually add the dashes in the header, the
server accepts the request.
You don't need to generate these values, the solution is to tick Use multipart/form-data for POST box in the HTTP Request sampler (or in the HTTP Request Defaults)
If you have any definition of Content-Type header in the HTTP Header Manager - you need to remove it and let JMeter generate appropriate Content-Type header on its own.
The header doesn't need the dashes. This is simply how multipart/form-data works. The body is built as follows:
--<boundary>
<headers>
<content>
--<boundary>
<headers>
<content>
--<boundary>--
The -- part indicates a new part starts. The body ends with ---- to indicate no new parts will follow.

JMeter Multipart JSON Request Form Data

I am trying to construct a HTTP Request through JMeter that uses a multipart data body.
I have a HTTP Header Manager that has COntent-Type set to multipart/form-data; boundary=AaB03x. I selected 'Use multipart/form-data for POST'.
I then have a data body created as,
`-----------------------------AaB03x
Content-Type: application/json
Content-Disposition: form-data; name="part1"
{"jsonKey1": "JsonValue1" }
-----------------------------AaB03x
Content-Type: application/json
Content-Disposition: form-data; name="part2"
{
"jsonKey2": "JsonValue2"
}
-----------------------------AaB03x
Content-Type: application/octet-stream
Content-Disposition: form-data; name="part3"
File Content here!!!!
-----------------------------AaB03x`
When I run this, I see that the request doesnt send the body correctly, instead it just sends some random data as,
POST data:
--vKOghkU7riRQbaANmmGpMs7j9TxCTUp3S2T0vE--
And gives an error response of,
`{"errorMsg":"Unable read headers from MultipartStream.","messageCode":"UnableReadHeadersFromMultipartStream","httpStat us":"BAD_REQUEST","requestName":"RequestName"}`
My second question is:
the part3 of the request sends a file to upload. Can I pass the file path somehow?
Given you set your own boundary and build your request manually I believe you need to uncheck Use multipart/form-data for POST in the HTTP Request Sampler
If your file encoding isn't very "exotic" you can try using __FileToString() function just instead of File Content here!!!!.
Looking into RFC 7578, it seems you also need a trailing -- at the end of the last line
You should try sending your JSON data as parameters. Also put your file path in the section for that... And even some servers don't actually need MIME type explicitly declared, you can check yours with some online tool like this one.
Your HTTP Request could look smethnig like:

WebApi: */* media type handling

In my application I'm making some javascript requests to my Api Controllers to get some html formatted strings. When those requests are made with Accept: */* HTTP header (jQuery $.get method), so by default JsonMediaTypeFormatter is used and the data is returned with Content-Type: application/json in JSON format.
What I would like is to handle */* requests as text/html. So I tried to create a custom MediaTypeFormatter that supports */* media type, but it gives me the following error
The 'MediaTypeHeaderValue' of */* cannot be used as a supported
media type because it is a media range.`
Alternatively I could always provide correct expected data types in my requests, but I'm curious if there's a way to handle */* media types.
The above behavior is due to the following:
The default con-neg algorithm in Web API has the following precedence order of choosing the formatter for response:
Formatter match based on Media Type Mapping.
Formatter match based on Request Accept header's media type.
Formatter match based on Request Content-Type header's media type.
Formatter match based on if it can serialize the response data’s Type.
Now, JsonMediaTypeFormatter comes with a built-in media type mapping called XmlHttpRequestHeaderMapping which inspects an incoming request and sees if the request has the header x-requested-with: XMLHttpRequest and also if there is no accept header or if the Accept header is only having */*.
Since your request is mostly probably looking like below, according to the precedence order JsonMediaTypeFormatter is chosen as the one writing the response:
GET /api/something
Accept: */*
x-requested-with: XMLHttpRequest
A solution for your issue would be is to explicitly ask for "text/html" as this is what you are expecting.
GET /api/something
Accept: text/html
x-requested-with: XMLHttpRequest
Couple of very old blog posts about Content negotiation that I wrote:
http://blogs.msdn.com/b/kiranchalla/archive/2012/02/25/content-negotiation-in-asp-net-mvc4-web-api-beta-part-1.aspx
http://blogs.msdn.com/b/kiranchalla/archive/2012/02/27/content-negotiation-in-asp-net-mvc4-web-api-beta-part-2.aspx
Great question.
You can't set */* to be a supported media type, but what you can do is set your formatter to be the first one. Web API will pick the first formatter in the formatter collection that can write out the type if there is no Accept header or if the Accept header is */*.
So you'd want to configure your Web API like this:
config.Formatters.Insert(0, new MyHtmlFormatter());

Resources