Class: WSDL::Operation

Inherits:
Object
  • Object
show all
Defined in:
lib/wsdl/operation.rb

Overview

Represents a callable SOAP operation.

Constant Summary collapse

ENCODING =

Default XML encoding used in SOAP request headers.

Returns:

  • (String)
'UTF-8'
CONTENT_TYPE =

HTTP Content-Type base values keyed by SOAP version.

Returns:

  • (Hash{String => String})
{
  '1.1' => 'text/xml',
  '1.2' => 'application/soap+xml'
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(operation_info, parser_result, http, config: Config.new) ⇒ Operation

Returns a new instance of Operation.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/wsdl/operation.rb', line 19

def initialize(operation_info, parser_result, http, config: Config.new)
  @operation_info = operation_info
  @parser_result = parser_result
  @http = http
  @config = config

  @endpoint = operation_info.endpoint
  @soap_version = operation_info.soap_version
  @soap_action = operation_info.soap_action
  @encoding = ENCODING

  @request_document = nil
  @security = Security::Config.new
  @http_header_overrides = {}
end

Instance Attribute Details

#encodingObject

Returns the value of attribute encoding.



35
36
37
# File 'lib/wsdl/operation.rb', line 35

def encoding
  @encoding
end

#endpointObject

Returns the value of attribute endpoint.



35
36
37
# File 'lib/wsdl/operation.rb', line 35

def endpoint
  @endpoint
end

#format_xmlBoolean

Returns whether XML output is formatted with indentation.

Defaults to the client's Config#format_xml setting. Set per-operation via #format_xml= to override the client default for this operation only.

Examples:

Check the current setting

operation.format_xml  # => true (inherits from client config)

Override per-operation

operation.format_xml = false
operation.format_xml  # => false

Returns:

  • (Boolean)


95
96
97
# File 'lib/wsdl/operation.rb', line 95

def format_xml
  defined?(@format_xml) ? @format_xml : @config.format_xml
end

#soap_actionObject

Returns the value of attribute soap_action.



35
36
37
# File 'lib/wsdl/operation.rb', line 35

def soap_action
  @soap_action
end

#soap_versionObject

Returns the value of attribute soap_version.



35
36
37
# File 'lib/wsdl/operation.rb', line 35

def soap_version
  @soap_version
end

Instance Method Details

#contractWSDL::Contract::OperationContract

Returns canonical operation contract metadata.



110
111
112
# File 'lib/wsdl/operation.rb', line 110

def contract
  @contract ||= Contract::OperationContract.new(@operation_info)
end

#http_headersHash{String => String}

Returns the merged HTTP headers for the SOAP request.

Auto-generated headers (Content-Type, SOAPAction) are computed from the current SOAP version, action, and encoding. Any headers set via #http_headers= are merged on top, so user-provided values win on conflict while auto-generated defaults are preserved.

Returns:

  • (Hash{String => String})


175
176
177
178
179
180
181
182
183
184
185
186
187
188
# File 'lib/wsdl/operation.rb', line 175

def http_headers
  headers = {}
  content_type = [CONTENT_TYPE[soap_version], "charset=#{encoding}"]

  case soap_version
  when '1.1'
    headers['SOAPAction'] = soap_action.nil? ? '' : %("#{soap_action}")
  when '1.2'
    content_type << %(action="#{soap_action}") if soap_action && !soap_action.empty?
  end

  headers['Content-Type'] = content_type.join(';')
  headers.merge(@http_header_overrides)
end

#http_headers=(headers) ⇒ void

This method returns an undefined value.

Merges custom headers on top of auto-generated HTTP headers.

The provided headers are stored and merged over the auto-generated defaults each time #http_headers is called. User-provided values win on conflict. Call #reset! to clear overrides.

Parameters:

  • headers (Hash{String => String})


198
199
200
# File 'lib/wsdl/operation.rb', line 198

def http_headers=(headers)
  @http_header_overrides = headers
end

#input_styleString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Low-level input binding style from the WSDL.

Prefer #contract .style for public introspection.

Returns:

  • (String)

    e.g. document/literal



242
243
244
# File 'lib/wsdl/operation.rb', line 242

def input_style
  @operation_info.input_style
end

#invokeResponse

Invokes this SOAP operation.

Returns:

Raises:



219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/wsdl/operation.rb', line 219

def invoke
  ensure_request_definition!

  http_response = @http.post(endpoint, http_headers, to_xml)
  enforce_response_size_limit!(http_response)

  response = Response.new(
    http_response:,
    output_body_parts: @operation_info.output.body_parts,
    output_header_parts: @operation_info.output.header_parts,
    verification: @security.response_verification_options
  )

  @security.response_policy.enforce!(response)
  response
end

#output_styleString

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Low-level output binding style from the WSDL.

Prefer #contract .style for public introspection.

Returns:

  • (String)

    e.g. document/literal



252
253
254
# File 'lib/wsdl/operation.rb', line 252

def output_style
  @operation_info.output_style
end

#prepare { ... } ⇒ self

Prepares request envelope from DSL and validates it immediately.

Yields:

  • DSL prepare block

Returns:

  • (self)

Raises:



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
# File 'lib/wsdl/operation.rb', line 118

def prepare(&block)
  raise RequestDslError, 'operation.prepare requires a block' unless block

  if @request_document
    raise RequestDslError,
          'operation.prepare was already called. ' \
          'Use operation.reset! to clear the previous request before preparing a new one'
  end

  document = Request::Envelope.new
  security = Security::Config.new
  context = Request::DSLContext.new(document:, security:, limits: @config.limits)
  context.instance_exec(&block)

  validation_contract = request_validation_contract

  Request::Validator.new(
    contract: validation_contract,
    strict_schema: @config.strict_schema,
    schema_complete: schema_complete_for_validation?
  ).validate!(document)

  Request::SecurityConflictDetector.new(document:, security:).validate!

  @request_document = document
  @security = security
  self
end

#prepared?Boolean

Returns whether a request has been prepared via #prepare.

Returns:

  • (Boolean)


150
151
152
# File 'lib/wsdl/operation.rb', line 150

def prepared?
  !@request_document.nil?
end

#reset!self

Clears the prepared request, allowing #prepare to be called again. Also clears any custom HTTP header overrides set via #http_headers= and the per-operation #format_xml override.

Returns:

  • (self)


159
160
161
162
163
164
165
# File 'lib/wsdl/operation.rb', line 159

def reset!
  @request_document = nil
  @security = Security::Config.new
  @http_header_overrides = {}
  remove_instance_variable(:@format_xml) if defined?(@format_xml)
  self
end

#to_xmlString

Serializes the prepared request envelope to SOAP envelope XML.

Returns:

  • (String)


205
206
207
208
209
210
211
212
213
# File 'lib/wsdl/operation.rb', line 205

def to_xml
  ensure_request_definition!

  document = prepare_serializable_document(@request_document || Request::Envelope.new)
  serializer = Request::Serializer.new(document:, soap_version:, format_xml:)
  return serializer.serialize unless @security.configured?

  Security::SecurityHeader.new(@security).apply(serializer.to_document)
end