Repository: sinatra/sinatra (Ruby)

Issue:
Built content_type are malformed
I encountered this while looking into https://github.com/prometheus/prometheus/issues/15777. It appears that a comma (`,`) is used as a separator in the `Content-Type` header instead of a semicolon (`;`).

here:
https://github.com/sinatra/sinatra/blob/7b50a1bbb5324838908dfaa00ec53ad322673a29/lib/sinatra/base.rb#L399-L403

All definitions I've seen use a semicolon (`;`) and apparently the RFC that initially mentioned a comma has since published an errata.

More details here:
https://stackoverflow.com/questions/35761248/which-separator-should-be-used-in-the-content-type-header-for-a-multipart-data-r

Not sure why the other consumers are ok with it, maybe less strict parsing? Do you think this is something that can be adjusted?

---

By the way, we're looking for someone interested in contributing to the Prometheus Ruby Client, particularly for these [changes](https://github.com/prometheus/client_ruby/issues/306), it revolves around parsers and content negotiation. Please let me know if you're interested.


Discussion: I'm not quite sure I get the problem. Can you provide an example Sinatra application and example requests demonstrating the issue?
https://gitlab.com/gitlab-org/ruby/gems/gitlab-exporter/-/blob/f16670c44a4a26393f780512d3ff669aa74d2cf6/lib/gitlab_exporter/web_exporter.rb#L136 which triggers the Prometheus issue I linked, which is due to how Sinatra builds the header I think (fct in `sinatra/lib/sinatra/base.rb` I shared)
Thanks for the link, that's useful context. It would be helpful if you provide what I asked. Also what you expect the output to be instead. 
I felt I made a good effort highlighting the exact util that I think is responsible of the wrong formatting: using `,` instead of `;` as separators.
What I can say more is that for the test

https://github.com/sinatra/sinatra/blob/7b50a1bbb5324838908dfaa00ec53ad322673a29/test/helpers_test.rb#L700-L710

I expect `'foo/bar;level=1; charset=utf-8'` instead of `'foo/bar;level=1, charset=utf-8'` as the final content-type.

I still don't think providing `example Sinatra application and example requests demonstrating the issue` will have any addition here.

Maybe others can help with that if you consider it to be a requirement.
Thanks for linking the test, I was not aware of it. That makes it clear.

If we look at the [blame view](https://github.com/sinatra/sinatra/blame/7b50a1bbb5324838908dfaa00ec53ad322673a29/test/helpers_test.rb#L700-L710) it was written 13-14 years ago. Was the RFC changed after that?
> More details here:
> https://stackoverflow.com/questions/35761248/which-separator-should-be-used-in-the-content-type-header-for-a-multipart-data-r

This doesn't look like the same case we're looking at here?
> All definitions I've seen use a semicolon (`;`) and apparently the RFC that initially mentioned a comma has since published an errata.

@machine424 You seem well read-up on this issue... can you share which RFCs we should lean on for this? I want to make it clear what the right thing to do is, but at the same time consider backwards compatibility.

Also, if this should be changed in Sinatra, a pull request is very much appreciated. The Sinatra project does not see many contributions these days and there are no team of maintainers actively fixing bugs. I'm here responding to most things, and I can work on making sure Sinatra keeps working with new releases of Ruby and Rack, but beyond that, my time is limited. Thanks for your help.
@stanhu anyone from GitLab able to help out with this issue?
@dentarg See https://github.com/sinatra/sinatra/pull/2081.



Fix (patch):
diff --git a/lib/sinatra/base.rb b/lib/sinatra/base.rb
index f0bccd8ae..fe9c0537e 100644
--- a/lib/sinatra/base.rb
+++ b/lib/sinatra/base.rb
@@ -396,11 +396,11 @@ def content_type(type = nil, params = {})
       end
       params.delete :charset if mime_type.include? 'charset'
       unless params.empty?
-        mime_type << (mime_type.include?(';') ? ', ' : ';')
+        mime_type << ';'
         mime_type << params.map do |key, val|
           val = val.inspect if val.to_s =~ /[";,]/
           "#{key}=#{val}"
-        end.join(', ')
+        end.join(';')
       end
       response['content-type'] = mime_type
     end