-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add MIME registry #5765
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
Add MIME registry #5765
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| foo/bar foo |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,176 @@ | ||
| require "./spec_helper" | ||
| require "mime" | ||
|
|
||
| module MIME | ||
| def self.initialized | ||
| @@initialized | ||
| end | ||
|
|
||
| def self.reset | ||
| @@initialized = false | ||
| @@types = {} of String => String | ||
| @@types_lower = {} of String => String | ||
| @@extensions = {} of String => Set(String) | ||
| end | ||
| end | ||
|
|
||
| describe MIME do | ||
| it ".from_extension" do | ||
| MIME.from_extension(".html").partition(';')[0].should eq "text/html" | ||
| MIME.from_extension(".HTML").partition(';')[0].should eq "text/html" | ||
|
|
||
| expect_raises KeyError do | ||
| MIME.from_extension(".fooobar") | ||
| end | ||
| MIME.from_extension(".fooobar", "default/fooobar").should eq "default/fooobar" | ||
| MIME.from_extension(".fooobar") { "default/fooobar" }.should eq "default/fooobar" | ||
| end | ||
|
|
||
| it ".from_extension?" do | ||
| MIME.from_extension?(".html").should eq MIME.from_extension(".html") | ||
| MIME.from_extension?(".HTML").should eq MIME.from_extension(".HTML") | ||
|
|
||
| MIME.from_extension?(".fooobar").should be_nil | ||
| end | ||
|
|
||
| it ".from_filename" do | ||
| MIME.from_filename("test.html").should eq MIME.from_extension(".html") | ||
| MIME.from_filename("foo/bar.not-exists", "foo/bar-exist").should eq "foo/bar-exist" | ||
| MIME.from_filename("foo/bar.not-exists") { "foo/bar-exist" }.should eq "foo/bar-exist" | ||
| end | ||
|
|
||
| it ".from_filename" do | ||
| MIME.from_filename?("test.html").should eq MIME.from_extension(".html") | ||
| end | ||
|
|
||
| describe ".register" do | ||
| it "registers new type" do | ||
| MIME.register(".Custom-Type", "text/custom-type") | ||
|
|
||
| MIME.from_extension(".Custom-Type").should eq "text/custom-type" | ||
| MIME.from_extension(".custom-type").should eq "text/custom-type" | ||
| MIME.extensions("text/custom-type").should eq Set{".Custom-Type"} | ||
|
|
||
| MIME.register(".custom-type2", "text/custom-type") | ||
| MIME.extensions("text/custom-type").should eq Set{".Custom-Type", ".custom-type2"} | ||
|
|
||
| MIME.register(".custom-type", "text/custom-type-lower") | ||
| MIME.from_extension(".custom-type").should eq "text/custom-type-lower" | ||
| MIME.from_extension(".Custom-Type").should eq "text/custom-type" | ||
| end | ||
|
|
||
| it "fails for invalid extension" do | ||
| expect_raises ArgumentError, "Extension does not start with a dot" do | ||
| MIME.register("foo", "text/foo") | ||
| end | ||
|
|
||
| expect_raises ArgumentError, "String contains null byte" do | ||
| MIME.register(".foo\0", "text/foo") | ||
| end | ||
| end | ||
| end | ||
|
|
||
| describe ".extensions" do | ||
| it "lists extensions" do | ||
| MIME.extensions("text/html").should contain ".htm" | ||
| MIME.extensions("text/html").should contain ".html" | ||
| end | ||
|
|
||
| it "returns empty set" do | ||
| MIME.extensions("foo/bar").should eq Set(String).new | ||
| end | ||
|
|
||
| it "recognizes overridden types" do | ||
| MIME.register(".custom-type-overridden", "text/custom-type-overridden") | ||
| MIME.register(".custom-type-overridden", "text/custom-type-override") | ||
|
|
||
| MIME.extensions("text/custom-type-overridden").should eq Set(String).new | ||
| end | ||
| end | ||
|
|
||
| it "parses media types" do | ||
| MIME.register(".parse-media-type1", "text/html; charset=utf-8") | ||
| MIME.extensions("text/html").should contain (".parse-media-type1") | ||
|
|
||
| MIME.register(".parse-media-type2", "text/html; foo = bar; bar= foo ;") | ||
| MIME.extensions("text/html").should contain (".parse-media-type2") | ||
|
|
||
| MIME.register(".parse-media-type3", "foo/bar") | ||
| MIME.extensions("foo/bar").should contain (".parse-media-type3") | ||
|
|
||
| MIME.register(".parse-media-type4", " form-data ; name=foo") | ||
| MIME.extensions("form-data").should contain (".parse-media-type4") | ||
|
|
||
| MIME.register(".parse-media-type41", %(FORM-DATA;name="foo")) | ||
| MIME.extensions("form-data").should contain (".parse-media-type41") | ||
|
|
||
| MIME.register(".parse-media-type5", %( FORM-DATA ; name="foo")) | ||
| MIME.extensions("form-data").should contain (".parse-media-type5") | ||
|
|
||
| expect_raises ArgumentError, "Invalid media type" do | ||
| MIME.register(".parse-media-type6", ": inline; attachment; filename=foo.html") | ||
| end | ||
|
|
||
| expect_raises ArgumentError, "Invalid media type" do | ||
| MIME.register(".parse-media-type7", "filename=foo.html, filename=bar.html") | ||
| end | ||
|
|
||
| expect_raises ArgumentError, "Invalid media type" do | ||
| MIME.register(".parse-media-type8", %("foo; filename=bar;baz"; filename=qux)) | ||
| end | ||
|
|
||
| expect_raises ArgumentError, "Invalid media type" do | ||
| MIME.register(".parse-media-type9", "x=y; filename=foo.html") | ||
| end | ||
|
|
||
| expect_raises ArgumentError, "Invalid media type" do | ||
| MIME.register(".parse-media-type10", "filename=foo.html") | ||
| end | ||
| end | ||
|
|
||
| it ".load_mime_database" do | ||
| MIME.from_extension?(".bar").should be_nil | ||
| MIME.from_extension?(".fbaz").should be_nil | ||
|
|
||
| MIME.load_mime_database IO::Memory.new <<-EOF | ||
| foo/bar bar | ||
| foo/baz baz fbaz #foobaz | ||
| # foo/foo foo | ||
| EOF | ||
|
|
||
| MIME.from_extension?(".bar").should eq "foo/bar" | ||
| MIME.from_extension?(".fbaz").should eq "foo/baz" | ||
| MIME.from_extension?(".#foobaz").should be_nil | ||
| MIME.from_extension?(".foobaz").should be_nil | ||
| MIME.from_extension?(".foo").should be_nil | ||
| end | ||
|
|
||
| describe ".init" do | ||
| it "loads defaults" do | ||
| MIME.reset | ||
| MIME.init | ||
| MIME.initialized.should be_true | ||
| MIME.from_extension(".html").partition(';')[0].should eq "text/html" | ||
| ensure | ||
| MIME.reset | ||
| end | ||
|
|
||
| it "skips loading defaults" do | ||
| MIME.reset | ||
| MIME.init(load_defaults: false) | ||
| MIME.initialized.should be_true | ||
| MIME.from_extension?(".html").should be_nil | ||
| ensure | ||
| MIME.reset | ||
| end | ||
|
|
||
| it "loads file" do | ||
| MIME.reset | ||
| MIME.initialized.should be_false | ||
| MIME.init(datapath("mime.types")) | ||
| MIME.from_extension?(".foo").should eq "foo/bar" | ||
| ensure | ||
| MIME.reset | ||
| end | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| module Crystal::System::MIME | ||
| # Load MIME types from operating system source. | ||
| # def self.load | ||
| end | ||
|
|
||
| {% if flag?(:unix) %} | ||
| require "./unix/mime" | ||
| {% elsif flag?(:win32) %} | ||
| require "./win32/mime" | ||
| {% else %} | ||
| {% raise "No Crystal::System::Mime implementation available" %} | ||
| {% end %} | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| module Crystal::System::MIME | ||
| MIME_SOURCES = { | ||
|
straight-shoota marked this conversation as resolved.
|
||
| "/etc/mime.types", # Linux | ||
| "/etc/httpd/mime.types", # Apache on Mac OS X | ||
| "/usr/local/etc/mime.types", # FreeBSD | ||
| "/usr/share/misc/mime.types", # OpenBSD | ||
| "/etc/httpd/conf/mime.types", # Apache | ||
| "/etc/apache/mime.types", # Apache 1 | ||
| "/etc/apache2/mime.types", # Apache 2 | ||
| "/usr/local/lib/netscape/mime.types", # Netscape | ||
| "/usr/local/etc/httpd/conf/mime.types", # Apache 1.2 | ||
| } | ||
|
|
||
| # Load MIME types from operating system source. | ||
| def self.load | ||
| MIME_SOURCES.each do |path| | ||
| next unless ::File.exists?(path) | ||
| ::File.open(path) do |file| | ||
| ::MIME.load_mime_database file | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That should work the other way around: That would avoid the circular dependency that
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't like the circular dependency either. But the fact that It could certainly be reversed if That's how I chose to implement it and I think it should stay this way. But I won't hurt about changing if requested.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's similar with
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what makes me wary is that something from Crystal::System is initializing an external namespace; and ::MIME should initialize itself using Crystal::System. I wish we could find a better way.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could pull the platform-dependent initialization implementations out of |
||
| end | ||
| rescue | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| module Crystal::System::MIME | ||
| # Load MIME types from operating system source. | ||
| def self.load | ||
| # TODO: MIME types in Windows are provided by the registry. This needs to be | ||
| # implemented when registry access it is available. | ||
| # Until then, there will no system-provided MIME types in Windows. | ||
| end | ||
| end |
Uh oh!
There was an error while loading. Please reload this page.