3

I'm trying to add PUT and DELETE verbs to WEBrick. I don't need them to do anything. They just need to respond with a 200. Below is the script I am running. GET works, but DELETE returns 405 with a "unsupported method DELETE" message. Can anyone tell me what is wrong or missing with this code?

require 'webrick'

module WEBrick
  module HTTPServlet
    class ProcHandler
      alias do_PUT    do_GET
      alias do_DELETE do_GET
    end
  end
end

sRoot = "C:\\"

server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => sRoot

trap "INT" do server.shutdown end

server.start
Kent
  • 1,691
  • 4
  • 19
  • 27
  • You probably need to add PUT and DELETE to some list of allowed methods. Grep the source for "unsupported method". – Kimmo Lehto May 30 '14 at 06:07
  • 2
    That's an odd thing to do. Why Webrick and not something that was updated in the last ten years? Don't [Unicorn](http://unicorn.bogomips.org/) and [Thin](https://github.com/macournoyer/thin/) do this properly? – tadman May 30 '14 at 06:11
  • 1
    @tadman, webrick comes installed with Ruby. We don't need this for serving up actual web pages. Just as a simple HTTP endpoint for some very simple tests. Webrick wins in this case because it requires zero installation across the machines that will be using it. – Kent May 30 '14 at 14:46
  • That's just a minor advantage in terms of not having any dependencies, yet it's a massive disadvantage because it's barely functional by today's standards. If you can write your entire application without using one external dependency, that's interesting but highly unusual. – tadman May 30 '14 at 15:18
  • 1
    The script in this question (which by the way was "how do I get this working?") *is* the application. – Kent May 30 '14 at 18:41

3 Answers3

3

Looking at Rack's WEBrick implementation is also informative.

Rack overrides the WEBrick::HTTPServlet::AbstractServlet#service method.

An example:

require 'webrick'

class TestServer < WEBrick::HTTPServlet::AbstractServlet
  def service(request, response)
    response.body = "#{request.request_method}:\n\t" +
      "#{request.inspect.lines.to_a.join("\t")}"
  end
end

server = WEBrick::HTTPServer.new Port: 8000
server.mount '/', TestServer
trap 'INT' do server.shutdown end
server.start

curl -X DELETE localhost:8000

gives

DELETE:
  DELETE / HTTP/1.1
  User-Agent: curl/7.35.0
  Host: localhost:8000
  Accept: */*
nitrogen
  • 1,559
  • 1
  • 14
  • 26
  • instead if def service, i used def do_GET, and created alias for do_POST,do_PUT and do_DELETE pointing it – deepak Feb 20 '15 at 11:46
2

I figured it out. I had to add appropriate handlers to DefaultFileHandler. @kimmo, thanks for the tip!

require 'webrick'

module WEBrick
  module HTTPServlet
    class FileHandler
      alias do_PUT    do_GET
      alias do_DELETE do_GET
    end

    class DefaultFileHandler
      def do_DELETE(req, res)
        res.body = ''
      end

      def do_PUT(req, res)
        res.body = ''
      end
    end
  end
end

sRoot = "C:\\"

server = WEBrick::HTTPServer.new :Port => 8000, :DocumentRoot => sRoot

trap "INT" do server.shutdown end

server.start
Kent
  • 1,691
  • 4
  • 19
  • 27
1

Kent's answer didn't work for me...perhaps WEBrick has been updated...

But it did give me the clues.

  module HTTPServlet
    class ProcHandler
      alias do_PUT    do_GET
      alias do_DELETE do_GET
    end
  end

  @server = WEBrick::HTTPServer.new( config )
  @server.mount_proc '/' do | req, res |
    ...
  end

  @server.start

ruby 2.2.3p173

B Seven
  • 44,484
  • 66
  • 240
  • 385