summaryrefslogtreecommitdiff
path: root/spec/unit/network/http/route_spec.rb
blob: 04f8f83889c32477ac058a6d3af7c7ec034fcee6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#! /usr/bin/env ruby
require 'spec_helper'
require 'puppet/indirector_testing'

require 'puppet/network/http'

describe Puppet::Network::HTTP::Route do
  def request(method, path)
    Puppet::Network::HTTP::Request.from_hash({
      :method => method,
      :path => path,
      :routing_path => path })
  end

  def respond(text)
    lambda { |req, res| res.respond_with(200, "text/plain", text) }
  end

  let(:req) { request("GET", "/vtest/foo") }
  let(:res) { Puppet::Network::HTTP::MemoryResponse.new }

  describe "an HTTP Route" do
    it "can match a request" do
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest})
      expect(route.matches?(req)).to be_true
    end

    it "will raise a Method Not Allowed error when no handler for the request's method is given" do
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest}).post(respond("ignored"))
      expect do
        route.process(req, res)
      end.to raise_error(Puppet::Network::HTTP::Error::HTTPMethodNotAllowedError)
    end

    it "can match any HTTP method" do
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest/foo}).any(respond("used"))
      expect(route.matches?(req)).to be_true

      route.process(req, res)

      expect(res.body).to eq("used")
    end

    it "processes DELETE requests" do
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest/foo}).delete(respond("used"))

      route.process(request("DELETE", "/vtest/foo"), res)

      expect(res.body).to eq("used")
    end

    it "does something when it doesn't know the verb" do
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest/foo})

      expect do
        route.process(request("UNKNOWN", "/vtest/foo"), res)
      end.to raise_error(Puppet::Network::HTTP::Error::HTTPMethodNotAllowedError, /UNKNOWN/)
    end

    it "calls the method handlers in turn" do
      call_count = 0
      handler = lambda { |request, response| call_count += 1 }
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest/foo}).get(handler, handler)

      route.process(req, res)
      expect(call_count).to eq(2)
    end

    it "stops calling handlers if one of them raises an error" do
      ignored_called = false
      ignored = lambda { |req, res| ignored_called = true }
      raise_error = lambda { |req, res| raise Puppet::Network::HTTP::Error::HTTPNotAuthorizedError, "go away" }
      route = Puppet::Network::HTTP::Route.path(%r{^/vtest/foo}).get(raise_error, ignored)

      expect do
        route.process(req, res)
      end.to raise_error(Puppet::Network::HTTP::Error::HTTPNotAuthorizedError)
      expect(ignored_called).to be_false
    end

    it "chains to other routes after calling its handlers" do
      inner_route = Puppet::Network::HTTP::Route.path(%r{^/inner}).any(respond("inner"))
      unused_inner_route = Puppet::Network::HTTP::Route.path(%r{^/unused_inner}).any(respond("unused"))

      top_route = Puppet::Network::HTTP::Route.path(%r{^/vtest}).any(respond("top")).chain(unused_inner_route, inner_route)
      top_route.process(request("GET", "/vtest/inner"), res)

      expect(res.body).to eq("topinner")
    end
  end
end