Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for verbatim multipart/related S/MIME uploads #135

Closed
pke opened this issue Mar 19, 2021 · 5 comments
Closed

Support for verbatim multipart/related S/MIME uploads #135

pke opened this issue Mar 19, 2021 · 5 comments

Comments

@pke
Copy link

pke commented Mar 19, 2021

The library already supports 2 variants of multipart uploads, which covers most use-cases.

I have a third use-case now and wonder if this can be already done with the library or would become a feature request.

I have to upload S/MIME multipart/related bodies which I already prepare myself and place them in the apps storage folder like this YYYYMMDDHHMMSSMS-<guid>.upload The content of this file is the multipart/related body that needs to be uploaded. It must not be base64 encoded or anything.

Does this already work when pointing the request to this local file and setting the Content-Type header to multipart/related?

@edeckers
Copy link
Owner

edeckers commented Mar 20, 2021

Hi @pke , thank you for opening this issue! Indeed, this is a use-case that is not supported by the library; unfortunately your suggested workaround won't work, because the multipart/form-data header is hardcoded and also because your file will be treated as any other regular file instead of an HTTP request.

As I see it, there are two ways to facilitate what you're looking for:

  1. Add a verbatimRequest or rawRequest method which sends a file supposedly containing a raw HTTP request to the target server
  2. Extend the already existing upload facilities, by allowing you to set the multipart/related header and have the library add predictable Content-ID's to every part of the request

If I understand you correctly, you're suggesting (1)? Personally I'm leaning towards (2), since it fits better with the current premise of the library, which is to aid in building requests. Would (2) be a workable compromise for your needs or am I missing a crucial detail?

@edeckers edeckers self-assigned this Mar 20, 2021
@pke
Copy link
Author

pke commented Mar 20, 2021

Thanks for your quick an thorough response.

I need this for S/MIME uploads. But I think that's out of scope for this lib. It could however help in composition of the multi layered related parts. Below you find a typical body of such message.

The "smime.signed" is its own multipart inside the wrapping "smime.parts" part.

smime.parts
  smime.signed
Content-Type: multipart/related; boundary="===============smime.parts=="
Accept: application/json

Content-Type: multipart/related; boundary="===============smime.parts=="

--===============smime.parts==
Content-Type: multipart/signed; boundary="===============smime.signed=="

--===============smime.signed==
Content-Type: application/json

{}
--===============smime.signed==
Content-Type: application/x-pkcs7-signature

--===============smime.signed==--
--===============smime.parts==
Content-Type: application/x-pkcs7-mime; name="smime.p7m"
Content-Disposition: attachment; filename="smime.p7m"
Content-Transfer-Encoding: base64


--===============smime.parts==
Content-Type: application/octet-stream
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="test.png"

iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGklEQVR42mNk+M/yn4ECwDhqwKgBowYMFwMAH1MgMcb8V4MAAAAASUVORK5CYII=
--===============smime.parts==--

Especially for big files the requirement of S/MIME to encode the attachments in BASE64 makes it less than ideal in an app world, where this increases the apps memory consumption a lot (base64 being 1.3 bigger than the binary data).
So the perfect way would be if the library would upload the first parts right away and then for the attachment(s) read a file from the file system (using a user supplied async function?) in multiple of 3 byte tuplets, base64 encode the buffer and send the buffer over the wire. This way no base64 of XX MiB files has to happen in RN memory.

I am not sure about the S/MIME protocol if the signing parts could also be sent last?

Does this make sense?

I think for now I could also just not use the multipart feature and upload the body as I have it already prepared?

@edeckers
Copy link
Owner

Your comment makes total sense to me, and I think it would be a nice feature to add to the library. I'm still pondering what solution to go with though.

As for your suggested workaround: every upload request is mapped to a multipart body, so this won't work. This is what happens:

const request0 = {
  absoluteFilePath,
  method: 'POST',
  mimeType: 'multipart/related; boundary="===============smime.parts=="',
  url: 'http://192.168.0.147:8080',
};

const uploadResult = await BlobCourier.uploadBlob(request0)
ely@xps-ely ~ nc -l 8080
POST / HTTP/1.1
Content-Type: multipart/form-data; boundary=b3e08e48-cfca-4423-a141-e1386c4bd0bb
Content-Length: 1015
Host: 192.168.0.147:8080
Connection: Keep-Alive
Accept-Encoding: gzip
User-Agent: okhttp/3.14.9

--b3e08e48-cfca-4423-a141-e1386c4bd0bb
Content-Disposition: form-data; name="file"; filename="test.upload"
Content-Type: multipart/related; boundary="===============smime.parts=="
Content-Length: 765

(...)

It makes a good point for the verbatimBody or rawBody solution we talked about earlier in this thread though, because that would definitely solve your problem right now.

I'll let you know what I decide on soon!

@edeckers
Copy link
Owner

I decided to implement both discussed solutions (#137 and #138); #137 will probably be the first one I'll work on.

@edeckers edeckers removed their assignment Mar 21, 2021
@edeckers
Copy link
Owner

Closing this in favor of the issues mentioned in my last coment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants