Class: UU::OS::CMD::CommandHandler

Inherits:
Object
  • Object
show all
Defined in:
uu_os_cmd-2.2.5/lib/uu/os/cmd/command_handler.rb

Overview

Default command handler. As custom handler might be used any class (or object instance) which responds to at least one of methods defined in this class.

Constant Summary

NEXT =

Value to be returned by handler in case it does not know how to process given values and therefore processing should be delegated to next handler.

:__next__

Instance Method Summary (collapse)

Instance Method Details

- (Object, ...) handle_error(http_response, options)

Allows processing of command invocation error.

Parameters:

  • http_response (UU::OS::HTTP::HTTPResponse)

    Raw command response (read only). Note that in case response body is IO, once it is consumed it will not be available to next handlers in chain.

  • options (Hash)

    Additional options given for request (see CommandClient#invoke for details.)

Returns:

  • (Object, Symbol, Exception)

    Processed command error (including nil) or value of NEXT to pass processing to next handler. In case method returns instance of exception, it will be immediately raised.



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'uu_os_cmd-2.2.5/lib/uu/os/cmd/command_handler.rb', line 186

def handle_error(http_response, options)
  body = http_response.body
  body = body.read if body.respond_to? :read
  begin
    body = JSON.parse(body, symbolize_names: true)
    if body[:code] =~ /^UU.OS.IPC\//
      raise UU::OS::IPC::IPCError.new(body)
    elsif body[:code] =~ /^UU.OS.APPLICATION\//
      raise UU::OS::Application::ApplicationError.new(body)
    else
      raise UU::OS::CMD::CommandError.new(body)
    end
  rescue JSON::ParserError
    # In case body is not JSON, it is not exception raised by
    # our framework, but exception raised by infrastructure
    # (therefore it can be considered as IPC error).
    raise UU::OS::IPC::IPCError.new(body)
  end
end

- (Object, ...) handle_redirect(http_response, options)

Allows processing of HTTP redirection.

Parameters:

  • http_response (UU::OS::HTTP::HTTPResponse)

    Raw command response (read only). Note that in case response body is IO, once it is consumed it will not be available to next handlers in chain.

  • options (Hash)

    Additional options given for request (see CommandClient#invoke for details.)

Returns:

  • (Object, Symbol, Exception)

    Result of processed redirection (including nil) or value of NEXT to pass processing to next handler. In case method returns instance of exception, it will be immediately raised.

Raises:

  • (NotImplementedError)


214
215
216
# File 'uu_os_cmd-2.2.5/lib/uu/os/cmd/command_handler.rb', line 214

def handle_redirect(http_response, options)
  raise NotImplementedError, "Service #{http_response.request.url} responded with #{http_response.status}, but command redirection is not supported."
end

- (Object, ...) handle_request(payload, http_headers, http_parameters, options)

Allows to transform given payload as needed along with related modification of HTTP request headers and query.

Parameters:

  • payload (Object)

    Original request payload. Note that in case payload is IO (or structure containing IO) it might not be available to next handlers in chain once consumed (depends on support of :rewind operation).

  • http_headers (UU::OS::HTTP::HTTPHeaders)

    Modifiable original request headers.

  • http_parameters (UU::OS::HTTP::HTTPQuery)

    Modifiable original request query parameters.

  • options (Hash)

    Additional options given for request (see CommandClient#invoke for details.)

Returns:

  • (Object, Symbol, Exception)

    Transformed payload (including nil) or value of NEXT to pass processing to next handler. In case method returns instance of exception, it will be immediately raised.



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
# File 'uu_os_cmd-2.2.5/lib/uu/os/cmd/command_handler.rb', line 36

def handle_request(payload, http_headers, http_parameters, options)
  invocation_method = options[:invocation_method]
  if invocation_method == :get
    if payload.nil? || payload.kind_of?(Hash)
      # Let transformation of query parameters on HTTPClient
      return payload
    else
      raise TypeError, "Cannot transform #{payload.class} to query parameters."
    end
  elsif invocation_method == :post
    return payload if http_headers.contains(:content_type)
    binary_upload = options[:binary_upload] || false
    multipart_upload = options[:multipart_upload] || false
    if payload.kind_of? Hash
      binary_values = payload.select do |k, v|
        v.kind_of? UU::OS::Lang::BinaryValue
      end
      if binary_values.size == 1
        binary_name = binary_values.keys.last
      elsif binary_values.size > 1
        multiple_binary_value_error(payload)
      end
    elsif payload.kind_of? UU::OS::Lang::BinaryValue
      tmp_payload = payload
      payload = {}
      payload[DEFAULT_BINARY_PARAM_NAME] = tmp_payload
      binary_name = DEFAULT_BINARY_PARAM_NAME
    elsif binary_upload && (payload.kind_of?(IO) || payload.kind_of?(StringIO) || payload.kind_of?(Tempfile))
      bmp = {}
      bmp[:name] = (payload.name if payload.respond_to?(:name)) || (File.basename(payload) if payload.respond_to?(:path))
      bmp[:contentType] = payload.content_type if payload.respond_to?(:content_type)
      bmp[:size] = (payload.size if payload.respond_to?(:size)) || (payload.length if payload.respond_to?(:length))
      bmp[:content] = payload
      bv = UU::OS::Lang::BinaryValue.new(bmp)
      payload = {}
      payload[DEFAULT_BINARY_PARAM_NAME] = bv
      binary_name = DEFAULT_BINARY_PARAM_NAME
    end

    if !binary_name.nil?
      http_headers[:content_type] = 'multipart/form-data'
      bmp = payload.dup
      bmp[binary_name] = bmp.delete(binary_name)
      return bmp
    elsif multipart_upload
      http_headers[:content_type] = 'multipart/form-data'
      if payload.nil? || payload.kind_of?(Hash)
        # Let transformation of multipart on HTTPClient
        return payload
      else
        raise TypeError, "Cannot transform #{payload.class} to multipart message. Multipart support Hash only."
      end
    else
      http_headers[:content_type] = 'application/json'
      # Let transformation of JSON on HTTPClient
      return payload
    end
  else
    raise NotImplementedError, "#{options[:invocation_method].upcase} commands are not supported."
  end
end

- (Object, ...) handle_response(http_response, options)

Allows processing of raw response in order to return expected result.

Parameters:

  • http_response (UU::OS::HTTP::HTTPResponse)

    Raw command response (read only). Note that in case response body is IO, once it is consumed it will not be available to next handlers in chain.

  • options (Hash)

    Additional options given for request (see CommandClient#invoke for details.)

Returns:

  • (Object, Symbol, Exception)

    Processed command response (including nil) or value of NEXT to pass processing to next handler. In case method returns instance of exception, it will be immediately raised.



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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'uu_os_cmd-2.2.5/lib/uu/os/cmd/command_handler.rb', line 105

def handle_response(http_response, options)
  if http_response.status == 204
    return nil
  elsif options[:raw_response]
    # Do not touch body if raw response was requested
    if options[:stream_response]
      return http_response.body
    end
    # backward compatibility, new need to return String no mather if body is IO or String
    if http_response.body.respond_to? :read
      return http_response.body.read
    end
    return http_response.body
  elsif http_response.headers.contains(:content_disposition, 'attachment')
    # Legacy commands may send additional metadata header
     = http_response.headers[:uu_os_binary_data_info]
     &&= JSON.parse(Base64.decode64([0]), symbolize_names: true)
     ||= {}
    # Transform file/binary download into binary data structure
    binary = {name: nil, contentType: nil, size: nil, content: nil}
    if .has_key?(:name) || .has_key?(:fileName)
      binary[:name] = [:name] || [:fileName]
    elsif http_response.headers[:content_disposition][0] =~ /filename=([^;]+)/
      name = $1
      name = name[1..-2] if name =~ /^".*"$/
      binary[:name] = name
    end
    if .has_key?(:contentType)
      binary[:contentType] = [:contentType]
    elsif !http_response.headers[:content_type].nil?
      binary[:contentType] = http_response.headers[:content_type][0]
    end
    if .has_key?(:size)
      binary[:size] = [:size]
    elsif !http_response.headers[:content_length].nil?
      binary[:size] = http_response.headers[:content_length][0].to_i
    end
    binary[:content] = http_response.body
    return UU::OS::Lang::BinaryValue.new(binary)
  elsif options[:stream_response]
    # If stream was requested, it must be returned
    body = http_response.body
    if body.kind_of?String
      return StringIO.new(body)
    else
      return body
    end
  elsif http_response.headers.contains(:content_type, 'application/json')
    # In case content type is JSON, we should parse it
    json = http_response.body
    json = json.read if json.kind_of? IO
    json.force_encoding('UTF-8')
    if json.empty? || json =~ /^{"nil":"true"}$/i
      # Second condition is null serialized by JAXB
      result = nil
    elsif json =~ /^\".*\"$/
      # String value 
      return json[1..-2]
    else
      # Parse JSON (leave original value if parse is not possible)
      result = (JSON.parse(json, symbolize_names: true, quirks_mode: true) rescue json)
    end
    if UU::OS::CMD::CommandFutureActor.command_future?(result)
      actor = UU::OS::CMD::CommandFutureActor.new(result, options)
      return UU::OS::Lang::Future.new(actor)
    else
      return result
    end
  else
    # Don't know how to handle, custom handler implementation is needed.
    return http_response.body
  end
end