0

I can't get Webrick to work with the servlet HTTPServlet::CGIHandler--I get an EACCES error:

[2012-12-06 01:38:02] ERROR CGIHandler: /tmp/cgi-bin:
/Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:46:in `exec': Permission denied - /tmp/cgi-bin (Errno::EACCES)
    from /Users/7stud/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/1.9.1/webrick/httpservlet/cgi_runner.rb:46:in `<main>'
[2012-12-06 01:38:02] ERROR CGIHandler: /tmp/cgi-bin exit with 1
[2012-12-06 01:38:02] ERROR Premature end of script headers: /tmp/cgi-bin
localhost - - [06/Dec/2012:01:38:02 MST] "GET /cgi/my_prog.cgi HTTP/1.1" 500 326
- -> /cgi/my_prog.cgi

Here are the permissions I set:

~/ruby_programs$ cd /
/$ ls -al tmp
lrwxr-xr-x@ 1 root  wheel  11 Jul  3  2011 tmp -> private/tmp

/$ cd tmp
/tmp$ ls -al
total 0
drwxrwxrwt  8 root   wheel  272 Dec  6 01:08 .
drwxr-xr-x@ 6 root   wheel  204 Mar 27  2010 ..
drwxr-xr-x  3 7stud  wheel  102 Dec  6 01:25 cgi-bin

/tmp$ cd cgi-bin/
/tmp/cgi-bin$ ls -al my_prog.cgi 
-rwxr-xr-x  1 7stud  wheel  123 Dec  6 01:09 my_prog.cgi

My server program(1.rb):

#!/usr/bin/env ruby
require 'webrick'
include WEBrick

port = 12_000
dir = Dir::pwd 

server = HTTPServer.new(
  :Port           => port,
  :DocumentRoot   => dir + "/html"
)

server.mount("/cgi", HTTPServlet::CGIHandler, "/tmp/cgi-bin")
puts "Listening on port: #{port}"

Signal.trap('SIGINT') { server.shutdown }
server.start

Running my server program:

~/ruby_programs$ ruby 1.rb 
[2012-12-06 01:37:58] INFO  WEBrick 1.3.1
[2012-12-06 01:37:58] INFO  ruby 1.9.3 (2012-04-20) [x86_64-darwin10.8.0]
Listening on port: 12000
[2012-12-06 01:37:58] INFO  WEBrick::HTTPServer#start: pid=4260 port=12000

I entered this address in my browser:

http://localhost:12000/cgi/my_prog.cgi

This was displayed in my browser:

Internal Server Error

Premature end of script headers: /tmp/cgi-bin WEBrick/1.3.1 (Ruby/1.9.3/2012-04-20) at localhost:12000

Here's my cgi script(/tmp/cgi-bin/my_prog.cgi):

#!/usr/bin/env ruby

require 'cgi'
cgi = CGI.new
puts cgi.header
puts "<html><body>Hello Webrick</body></html>"
7stud
  • 46,922
  • 14
  • 101
  • 127

2 Answers2

1

The only way I can get WEBrick to execute cgi files in a directory other than the root, is to use the HTTPServlet::FileHandler servlet:

port = 12_500
...

cgi_dir = File.expand_path("~/ruby_programs/cgi-bin")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)

Then the url used to execute a .cgi file located in the cgi_dir is:

http://localhost:12500/cgi/my_prog.cgi

Apparently, when you write:

server = HTTPServer.new(
  :Port           => port,
  :DocumentRoot   => "./html"  #Regular files served/.cgi files executed out of this dir
)

Webrick automatically "mounts" an HTTPServlet::FileHandler to handle requests to the :DocumentRoot directory, e.g.

http://localhost:12500/my_html.htm

which will serve files out of the ./html directory (i.e. a directory called html located below the directory from which your program is running). The HTTPServlet::FileHandler will also execute files in that directory if they have a .cgi extension.

If you explicitly use mount() to add an HTTPServlet::FileHandler to another directory, e.g.

cgi_dir = File.expand_path("~/ruby_programs/cgi-bin")
server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)

then WEBrick will also serve files from that directory and execute files in that directory that have a .cgi extension.

I haven't found a way to configure WEBrick to only serve files out of the :DocumentRoot directory and only execute .cgi files in another directory.

See "Gnome's Guide to WEBrick" here:

http://microjet.ath.cx/webrickguide/html/

7stud
  • 46,922
  • 14
  • 101
  • 127
1

In my case I had similar problems because of incorrect file permissions and really incorrect headers. Permissions of CGI-script should be like this:

~/ruby_projects/cgi_webrick/cgi
ls -l
-rwxr-xr-x 1 me me  112 Sep 20 20:29 test.cgi

My server code looks very similar (placed in ~/ruby_projects/cgi_webrick/), but with different handler.

#!/usr/bin/env ruby

require 'webrick'

server = WEBrick::HTTPServer.new :Port => 1234 
server.mount "/", WEBrick::HTTPServlet::FileHandler , './'
trap('INT') { server.stop }
server.start

If you run server script ruby my_server_script.cgi, it will serve any scripts from root or other directory. In my case I can access http://localhost:1234/cgi/test.cgi (script placed in cgi subfolder), and http://localhost:1234/test.cgi (placed in the root directory from which server is started).

My test script:

#!/usr/bin/ruby

require 'cgi'

cgi = CGI.new
puts cgi.header
puts "<html><body>This is a test</body></html>"
kovpack
  • 4,905
  • 8
  • 38
  • 55
  • **but with different handler: `WEBrick::HTTPServlet::FileHandler`** That's the same handler, I just used the line `include WEBrick`, which allowed me to lop off the leading 'WEBrick::': `server.mount("/cgi", HTTPServlet::FileHandler, cgi_dir)` – 7stud Sep 20 '14 at 18:49