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

Mimetype application/x-zip-compressed interpreted as a text field #3200

Open
Dennis4b opened this issue Nov 8, 2024 · 3 comments · May be fixed by #3203
Open

Mimetype application/x-zip-compressed interpreted as a text field #3200

Dennis4b opened this issue Nov 8, 2024 · 3 comments · May be fixed by #3203
Labels
💎 Bounty bug Something isn't working

Comments

@Dennis4b
Copy link
Contributor

Dennis4b commented Nov 8, 2024

I am running into an issue where parsed form fields (using .body.asMultipartFormStream) are recognized/decoded as FormField.Text, when Windows browsers (seen with Chrome and Edge) attach files with mimetype application/x-zip-compressed instead of application/zip. This means the binary file data is coerced into a string and mangled and unusable.

The Mediatypes are generated from jshttp which does not include this mimetype, which would be one thing that could address this issue, but there seems to be the intention to fall back to application/octet-stream which however is not happening, instead falling back to a non-binary Text type thereby mangling the data irreversibly.

Specifically in FormField.scala:

      contentType      = extract._2
        .flatMap(x => MediaType.forContentType(x.value))
        .getOrElse(MediaType.application.`octet-stream`)

however in MediaType.forContentType(...):

contentTypeMap.get(contentTypeLC).orElse(parseCustomMediaType(contentTypeLC))

which does:

def parseCustomMediaType(customMediaType: String): Option[MediaType] = {
    val contentTypeParts = customMediaType.split('/')
    if (contentTypeParts.length == 2) {
      val subtypeParts = contentTypeParts(1).split(';')
      if (subtypeParts.length >= 1) {
        Some(
          MediaType(
            mainType = contentTypeParts.head,
            subType = subtypeParts.head,
            parameters = if (subtypeParts.length >= 2) parseOptionalParameters(subtypeParts.tail) else Map.empty,
          ),
        )
      } else None
    } else None
  }

which is going to return a MediaType with binary set to false and not fall back to application/octet-stream.

I do prefer preserving the mimetype the browser set as opposed to setting it to application/octet-stream, since I can deal with that in my app, but the data should IMHO be treated as binary unless certain it really is text.

That would mean that parseCustomMediaType would always explicitly set binary=true if the mimetype does not start with text/ (and possibly other mimetype families known to be text)

@Dennis4b Dennis4b added the bug Something isn't working label Nov 8, 2024
@jdegoes
Copy link
Member

jdegoes commented Nov 9, 2024

/bounty $75

Copy link

algora-pbc bot commented Nov 9, 2024

💎 $75 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #3200 with your implementation plan
  2. Submit work: Create a pull request including /claim #3200 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-http!

Add a bountyShare on socials

Attempt Started (GMT+0) Solution
🟢 @varshith257 #3203

Copy link

algora-pbc bot commented Nov 9, 2024

💡 @varshith257 submitted a pull request that claims the bounty. You can visit your bounty board to reward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💎 Bounty bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants