File: http_error.rb

package info (click to toggle)
ruby-azure-storage-common 2.0.1-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 496 kB
  • sloc: ruby: 3,022; makefile: 7
file content (135 lines) | stat: -rw-r--r-- 5,020 bytes parent folder | download | duplicates (3)
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#-------------------------------------------------------------------------
# # Copyright (c) Microsoft and contributors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#--------------------------------------------------------------------------
require 'azure/core/error'
require 'nokogiri'
require 'json'

module Azure
  module Core
    module Http
      # Public: Class for handling all HTTP response errors
      class HTTPError < Azure::Core::Error

        # Public: Detail of the response
        #
        # Returns an Azure::Core::Http::HttpResponse object
        attr :http_response

        # Public: The request URI
        #
        # Returns a String
        attr :uri

        # Public: The HTTP status code of this error
        #
        # Returns a Fixnum
        attr :status_code

        # Public: The type of error
        #
        # http://msdn.microsoft.com/en-us/library/azure/dd179357
        #
        # Returns a String
        attr :type

        # Public: Description of the error
        #
        # Returns a String
        attr :description

        # Public: Detail of the error
        #
        # Returns a String
        attr :detail

        # Public: The header name whose value is invalid
        #
        # Returns a String
        attr :header

        # Public: The invalid header value
        #
        # Returns a String
        attr :header_value

        # Public: Initialize an error
        #
        # http_response - An Azure::Core::HttpResponse
        def initialize(http_response)
          @http_response = http_response
          @uri = http_response.uri
          @status_code = http_response.status_code
          parse_response
          # Use reason phrase as the description if description is empty
          @description = http_response.reason_phrase if (@description.nil? || @description.empty?) && http_response.reason_phrase
          super("#{type} (#{status_code}): #{description}")
        end

        # Extract the relevant information from the response's body. If the response
        # body is not an XML, we return an 'Unknown' error with the entire body as
        # the description
        #
        # Returns nothing
        def parse_response
          if @http_response.body && @http_response.respond_to?(:headers) && @http_response.headers['Content-Type']
            if @http_response.headers['Content-Type'].include?('xml')
              parse_xml_response
            elsif @http_response.headers['Content-Type'].include?('json')
              parse_json_response
            end
          else
            parse_unknown_response
          end
        end

        def parse_xml_response
          document = Nokogiri.Slop(@http_response.body)

          @type = document.css('code').first.text if document.css('code').any?
          @type = document.css('Code').first.text if document.css('Code').any?
          @description = document.css('message').first.text if document.css('message').any?
          @description = document.css('Message').first.text if document.css('Message').any?
          @header = document.css('headername').first.text if document.css('headername').any?
          @header = document.css('HeaderName').first.text if document.css('HeaderName').any?
          @header_value = document.css('headervalue').first.text if document.css('headervalue').any?
          @header_value = document.css('HeaderValue').first.text if document.css('HeaderValue').any?

          # service bus uses detail instead of message
          @detail = document.css('detail').first.text if document.css('detail').any?
          @detail = document.css('Detail').first.text if document.css('Detail').any?
        end

        def parse_json_response
          odata_error = JSON.parse(@http_response.body)['odata.error']
          @type = odata_error['code']
          @description = odata_error['message']['value']
        end

        def parse_unknown_response
          @type = 'Unknown'
          if @http_response.body
            @description = "#{@http_response.body.strip}"
          end
        end

        def inspect
          string = "#<#{self.class.name}:#{self.object_id} "
          fields = self.instance_variables.map{|field| "#{field}: #{self.send(field.to_s.delete("@")).inspect}"}
          string << fields.join(", ") << ">"
        end
      end
    end
  end
end