middleman / middleman

Hand-crafted frontend development
https://middlemanapp.com
MIT License
7.04k stars 746 forks source link

link_to 'http://example.com/index.html' failed when set :relative_links, true #1195

Closed kidwm closed 9 years ago

kidwm commented 10 years ago
URI::InvalidComponentError at /
bad component(expected absolute path component): ./

it seems link_to 'anyhost/*.html' will trigger this to fail.

bhollis commented 10 years ago

Could you post the full stack trace?

kidwm commented 10 years ago
URI::InvalidComponentError at /
bad component(expected absolute path component): ./

Ruby    /usr/share/ruby/uri/generic.rb: in check_path, line 824
Web GET localhost/
Jump to:

GETPOSTCookiesENV
Traceback (innermost first)

/usr/share/ruby/uri/generic.rb: in check_path
          raise InvalidComponentError,...
/usr/share/ruby/uri/generic.rb: in path=
      check_path(v)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/util.rb: in url_for
          uri.path = relative_path_from_resource(this_resource, resource_url, effective_relative)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-more/core_extensions/default_helpers.rb: in url_for
      ::Middleman::Util.url_for(self, path_or_resource, options_with_resource)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-more/core_extensions/default_helpers.rb: in link_to
        args[url_arg_index] = url_for(url, options)...
/home/wm/Projects/osdc.tw/source/layouts/layout.haml: in block (2 levels) in singleton class
                                = link_to image_tag('sponsors/' + link.id + '.png', :alt => link.title), link.link...
/home/wm/Projects/osdc.tw/source/layouts/layout.haml: in each
                        - data.relation.sponsors.each do |link|...
/home/wm/Projects/osdc.tw/source/layouts/layout.haml: in block in singleton class
                        - data.relation.sponsors.each do |link|...
/home/wm/.gem/ruby/gems/tilt-1.4.1/lib/tilt/template.rb: in call
      method.bind(scope).call(locals, &block)...
/home/wm/.gem/ruby/gems/tilt-1.4.1/lib/tilt/template.rb: in evaluate
      method.bind(scope).call(locals, &block)...
/home/wm/.gem/ruby/gems/tilt-1.4.1/lib/tilt/haml.rb: in evaluate
        super...
/home/wm/.gem/ruby/gems/tilt-1.4.1/lib/tilt/template.rb: in render
      evaluate scope, locals || {}, &block...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/rendering.rb: in render_individual_file
          content = template.render(context, locs, &block)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/rendering.rb: in render_template
            content = render_individual_file(layout_path, locs, opts, context) { content }...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/sitemap/resource.rb: in block in render
          app.render_template(source_file, locs, opts, blocks)...
/home/wm/.gem/ruby/gems/activesupport-3.2.16/lib/active_support/notifications.rb: in instrument
          yield payload if block_given?...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/util.rb: in instrument
        ::ActiveSupport::Notifications.instrument(suffixed_name, payload, &block)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/application.rb: in instrument
    delegate :instrument, :to => ::Middleman::Util...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/sitemap/resource.rb: in instrument
      delegate :logger, :instrument, :to => :app...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/sitemap/resource.rb: in render
        instrument 'render.resource', :path => relative_source  do...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/request.rb: in process_request
            output = resource.render do...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/request.rb: in block in call!
            process_request(env, req, res)...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/request.rb: in catch
          catch(:halt) do...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/request.rb: in call!
          catch(:halt) do...
/home/wm/.gem/ruby/gems/middleman-core-3.2.2/lib/middleman-core/core_extensions/request.rb: in call
          dup.call!(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/builder.rb: in call
      to_app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/urlmap.rb: in block in call
        return app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/urlmap.rb: in each
      @mapping.each do |host, location, match, app|...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/urlmap.rb: in call
      @mapping.each do |host, location, match, app|...
/home/wm/.gem/ruby/gems/rack-livereload-0.3.15/lib/rack/livereload.rb: in _call
        status, headers, body = result = @app.call(env)...
/home/wm/.gem/ruby/gems/rack-livereload-0.3.15/lib/rack/livereload.rb: in call
      dup._call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/showexceptions.rb: in call
      @app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/head.rb: in call
    status, headers, body = @app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/lint.rb: in _call
      status, headers, @body = @app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/lint.rb: in call
      dup._call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/builder.rb: in call
      to_app.call(env)...
/home/wm/.gem/ruby/gems/rack-1.5.2/lib/rack/handler/webrick.rb: in service
        status, headers, body = @app.call(env)...
/usr/share/ruby/webrick/httpserver.rb: in service
      si.service(req, res)...
/usr/share/ruby/webrick/httpserver.rb: in run
          server.service(req, res)...
/usr/share/ruby/webrick/server.rb: in block in start_thread
          block ? block.call(sock) : run(sock)...
codyrobbins commented 9 years ago

I’m also running into this problem. I have relative_links set to true in my configuration but I have some Markdown that contains a few absolute links. If the path of an absolute link happens to match a resource that exists in the Middleman site, whether or not the absolute link contains a host component (i.e., even if it is links to an external site), the Kramdown renderer is attempting to pass the absolute links through link_to and it’s dying.

So, for example, if I have the following Markdown

[Link](http://google.com/test.html)

and I have a file in my Middleman site named test.html, then Kramdown attempts to rewrite that absolute link by passing it through link_to—even though that’s an absolute link to an external site that shouldn’t be rewritten.

I tried to work around this by adding {:relative='false'} in the Markdown. But url_for would have to be changed here to something like relative = options[:relative] || options['relative'] == 'true' for this to work. The best solution would be to fix url_for so that it doesn’t attempt to rewrite external absolute links. It does raise an exception here if the URL has a host component, but that doesn’t get triggered if relative_links is set globally in the configuration rather than passed as an option to link_to.

As an aside, all of the automatic link munging stuff Middleman does is super annoying and I really wish there was a way to turn it off across the board. I’m not using link_to in any of my templates because it’s an unnecessary level of indirection for my purposes. If this was a full Rails app then URL helpers would gain you things like not having to explicitly specify URLs in link_to and form_for helpers and whatnot, but in Middleman it just adds another layer of abstraction without any advantages.

For example, there’s absolutely no reason to use link_to like this

<%= link_to('About', '/about.html') %>

when instead you could simply do

%a{href: '/about.html'} About

It just muddies the waters.

This is all fine and dandy—I don’t need link_to so I’m simply not using it in my project. The problem is, however, things like the line mentioned above where Markdown links are surreptitiously passed through link_to anyways. Anywhere I use Markdown in my site the link_to helper is covertly applying its weird link munging whether I want it or not and as far as I’m aware there’s no way to disable it.

There are places in my site where for various reasons I want to use relative links and other places I want to use absolute ones. Without being able to turn off this authoritarian application of link_to I can’t just write my markup how I need it—it has to all be relative or all be absolute.

For the time being I’ve simply avoided using Markdown for links like this.

tdreyno commented 9 years ago

Good research. We'll prioritize fixing this.

codyrobbins commented 9 years ago

I’ve made a change to a fork I’m using for my project and it seems to resolve the issue for my case. There’s a lot going on in this url_for method so I’m not confident enough to try to put together a pull request, but maybe this will help:

https://github.com/codyrobbins/middleman/commit/16ffdf83a757e8cc6698d773cb280cd634d5118c

tdreyno commented 9 years ago

Fixed, will go out in next release or use MM from github for now.