1

How can I use local resources like css, js, png, etc. within a dynamically rendered page using webrick? In other words, how are things like Ruby on Rails linking made to work? I suppose this is one of the most basic things, and there should be a simple way to do it.

Possible Solution

I managed to do what I wanted using two servlets as follows:

require 'webrick' 

class WEBrick::HTTPServlet::AbstractServlet
  def do_GET request, response
    response.body = '<html>
      <head><base href="http://localhost:2000"/></head>
      <body><img src="path/image.png" /></body>
    </html>'
  end
end

s1 = WEBrick::HTTPServer.new(Port: 2000, BindAddress: "localhost")
s2 = WEBrick::HTTPServer.new(Port: 3000, BindAddress: "localhost")
%w[INT TERM].each{|signal| trap(signal){s1.stop}}
%w[INT TERM].each{|signal| trap(signal){s2.shutdown}}
s1.mount("/", WEBrick::HTTPServlet::FileHandler, '/')
s2.mount("/", WEBrick::HTTPServlet::AbstractServlet)

Thread.new{s1.start}
s2.start

Is this the right way to do it? I do not feel so. In addition, I am not completely satisfied with it. For one thing, I do not like the fact that I have to specify http://localhost:2000 in the body. Another is the use of thread does not seem right. Is there a better way to do this? If you think this is the right way, please answer so.

sawa
  • 165,429
  • 45
  • 277
  • 381
  • How does it "not work"? Do you get an error? Do you get something? What do you get? What did you expect? – Jakob S Jun 08 '11 at 08:14
  • Just a thought, but check the file's permissions to make sure it's readable by the server (not just by you). – hoff2 Jun 08 '11 at 16:44
  • @centipedefarmer The permission is okay. I can correctly see the picture when I right click on the image and do 'view image info'. – sawa Jun 08 '11 at 20:23
  • I finally found out a way to do it. I added that as an answer. – sawa Jun 09 '11 at 06:49

4 Answers4

2

Generally speaking, because of security concerns browsers likely won't link to local files (using file:// schema) from an internet site (using http:// or https:// schema). See Can Google Chrome open local links?. This is unrelated to any server side technology.

Outside of that, it seems your server is working perfectly. You've made it so it responds to all requests with a HTML page containing a link to /. When you click on that link, something does indeed happen; a request is sent and you are served the same page again.

It kind of sounds like you want to expose your entire filesystem via HTTP. If that is what you're trying to accomplish, you can simply get away with not mounting a servlet:

server = WEBrick::HTTPServer.new(Port: 3000, BindAddress: "localhost", DocumentRoot: "/")
%w[INT TERM].each{|signal| trap(signal){server.shutdown}}
server.start
Community
  • 1
  • 1
Jakob S
  • 19,575
  • 3
  • 40
  • 38
  • Thanks for answering. I was starting to get aware of the security thing. Chosing the root directory is just an example. I want to render a page that has links to certain directories on my local computer. I also want to embed images from my local computer, which I tried with `` in a similar way, but didn't succeed. – sawa Jun 08 '11 at 13:46
  • 1
    You can do this with a static HTML page, that you just open in the browser. That won't hit the security issues. Alternatively, you need to expose the necessary files/directories via your HTTP server and link to them without file:// – Jakob S Jun 08 '11 at 14:09
  • I added a working code to my question, which will probably make it clear what I wanted. If you can help me, it will be appreciated. – sawa Jun 09 '11 at 05:38
1

Try code like this:

require 'webrick'

class WEBrick::HTTPServlet::AbstractServlet
  def do_GET request, response
    if request.unparsed_uri == "/"
      response.body = '<html><body><a href = "/path/to/file">test</a></body></html>'
    end
  end
end

server = WEBrick::HTTPServer.new(Port: 3000, BindAddress: "localhost", DocumentRoot: "/")
%w[INT TERM].each { |signal| trap(signal) { server.shutdown } }
server.mount("/", WEBrick::HTTPServlet::AbstractServlet)
server.start

This works for me, I'm not sure why but it seems to work whenever I call at least one method on the request object.

robbrit
  • 17,560
  • 4
  • 48
  • 68
  • Alright, I updated a response with something that seems to work. – robbrit Jun 08 '11 at 03:49
  • I tried your code with `/path/to/file` as `/`, but it does not work. Am I doing something wrong? – sawa Jun 08 '11 at 04:53
  • I added a working code to my question, which will probably make it clear what I wanted. If you can help me, it will be appreciated. – sawa Jun 09 '11 at 05:39
1

It sounds like you are confusing web pages that are served vs. pages that are opened by the browser directly from your drive, and how file: differs from http:, https:, and ftp:.

file: is a locally available resource when a page is directly opened from the drive. The others are remotely available resources when a page is served from a httpd host.

The browser can't tell that a page from a server came from your drive; It only knows it got it from a server, somewhere, and doesn't know or care whether that server is on the same hardware. Browsers will not allow access to local resources from remotely retrieved pages. That was an exploit that was closed years ago.

See RFC 1738's specification 3.10 FILES for file: URLs for the official statements.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
  • Okay, let's forget about opening with `file:`. When we access a server's `index.html` page, we can access various files like `css`, `js`, `png`. How can we do that when the main page is dynamically generated and served with WEBrick? I suppose this shoud be possible. That is the second part of what I want to do. – sawa Jun 08 '11 at 19:57
  • I added a working code to my question, which will probably make it clear what I wanted. If you can help me, it will be appreciated. – sawa Jun 09 '11 at 05:38
0

I finally found out that I can mount multiple servlets on a single server. It took a long time until I found such example.

require 'webrick' 

class WEBrick::HTTPServlet::AbstractServlet
  def do_GET request, response
    response.body = '<html>
      <head><base href="/resource/"/></head>
      <body>
        <img src="path_to_image/image.png";alt="picture"/>
        <a href="path_to_directory/" />link</a>
        ...
      </body>
    </html>'
  end
end

server = WEBrick::HTTPServer.new(Port: 3000, BindAddress: "localhost")
%w[INT TERM].each{|signal| trap(signal){server.shutdown}}
server.mount("/resource/", WEBrick::HTTPServlet::FileHandler, '/')
server.mount("/", WEBrick::HTTPServlet::AbstractServlet)
server.start

The path /resource/ can be anything else. The link will now correctly redirect to the expected directory, showing that there is no access permission, which indicates that things are working right; it's now just a matter of permission.

sawa
  • 165,429
  • 45
  • 277
  • 381