Cách tốt nhất để sử dụng SOAP với Ruby là gì?


91

Một khách hàng của tôi đã yêu cầu tôi tích hợp API của bên thứ 3 vào ứng dụng Rails của họ. Vấn đề duy nhất là API sử dụng SOAP. Về cơ bản, Ruby đã bỏ SOAP để ủng hộ REST. Họ cung cấp một bộ điều hợp Java dường như hoạt động với cầu nối Java-Ruby, nhưng chúng tôi muốn giữ tất cả trong Ruby, nếu có thể. Tôi đã xem xét soap4r, nhưng nó có vẻ có một danh tiếng hơi xấu.

Vậy cách tốt nhất để tích hợp các cuộc gọi SOAP vào một ứng dụng Rails là gì?

Câu trả lời:


36

Chúng tôi đã sử dụng lớp được xây dựng trong soap/wsdlDriver, thực sự là SOAP4R. Nó chậm, nhưng thực sự đơn giản. SOAP4R mà bạn nhận được từ gems / etc chỉ là phiên bản cập nhật của cùng một thứ.

Mã ví dụ:

require 'soap/wsdlDriver'

client = SOAP::WSDLDriverFactory.new( 'http://example.com/service.wsdl' ).create_rpc_driver
result = client.doStuff();

Đó là về nó


37
Một phần lý do tại sao đây là "Dog Slow" là bạn đang xây dựng proxy mỗi khi kết nối với dịch vụ. Bạn có thể tránh nỗi đau này bằng cách sử dụng wsdl2ruby để tạo proxy vĩnh viễn và sau đó gọi proxy được tạo trước.
Steve Weet 20/02/09

6
Chúng tôi có thể, nhưng điều đó có nghĩa là cài đặt wsdl2ruby, vân vân và vân vân. Đôi khi Chó chậm là tốt :-)
Orion Edwards

1
Nếu bạn cần xây dựng các lớp proxy cho Savon, bạn có thể làm theo cách tiếp cận của kredmer trong việc xây dựng các phương thức xà phòng ngay lập tức với sự trợ giúp của SoapUI để điền tên phương thức và không phải tạo trình phân tích cú pháp wsdl tùy chỉnh :). Thay vì lưu trữ tất cả các phương thức trong bộ nhớ, bạn có thể ghi vào tệp, đặc biệt nếu bạn có hàng tấn.
Dejan,

3
04/2015: Soap4r chết, trang web ngừng hoạt động. Có vẻ như Savon là lựa chọn phổ biến vào lúc này.
Puce

Tôi đã đào bới xung quanh trong không gian và phát hiện này soap4r-ng, điều đó vẫn được duy trì github.com/rubyjedi/soap4r
ghoti

170

Tôi đã xây dựng Savon để tương tác với các thiết bị web SOAP qua Ruby dễ dàng nhất có thể.
Tôi khuyên bạn nên kiểm tra nó.


5
+1 cho savon, không phải bash soap4r - nhưng tôi đã có trải nghiệm thực sự tồi tệ với nó. Thiếu tài liệu tốt và quá cồng kềnh.
konung

1
Đẹp! Thế giới SOAP trong ruby đã được cải thiện kể từ lần cuối cùng tôi đã phải sử dụng Soap4R để làm điều này (~ 18 months ago)
madlep

bất kỳ ai trong số các bạn vui lòng giúp tôi để đạt được api saber bằng cách sử dụng savon? Tôi có mã savon cung cấp cho tôi các phương thức sử dụng wsdl của SOAP nhưng tôi không thể gửi yêu cầu bằng savon ở định dạng xml.
Jai Kumar Rajput


5

Tôi cũng giới thiệu Savon . Tôi đã dành quá nhiều giờ để xử lý Soap4R mà không có kết quả. Thiếu nhiều chức năng, không có tài liệu.

Savon là câu trả lời cho tôi.



3

Chỉ cần sử dụng Savon để làm việc trong vòng 3 giờ.

Tài liệu Bắt đầu trên trang chủ của Savon thực sự rất dễ theo dõi - và thực sự khớp với những gì tôi đang thấy (không phải lúc nào cũng vậy)


2

Kent Sibilev từ Datanoise cũng đã chuyển thư viện Rails ActionWebService sang Rails 2.1 (trở lên). Điều này cho phép bạn hiển thị các dịch vụ SOAP dựa trên Ruby của riêng bạn. Anh ấy thậm chí còn có chế độ thử nghiệm / giàn giáo cho phép bạn kiểm tra các dịch vụ của mình bằng trình duyệt.


2

Tôi đã sử dụng SOAP trong Ruby khi tôi phải tạo một máy chủ SOAP giả cho các bài kiểm tra chấp nhận của mình. Tôi không biết đây có phải là cách tốt nhất để tiếp cận vấn đề hay không, nhưng nó đã hiệu quả với tôi.

Tôi đã sử dụng đá quý Sinatra (tôi đã viết về cách tạo điểm cuối giả mạo với Sinatra tại đây ) cho máy chủ và cả Nokogiri cho nội dung XML (SOAP đang làm việc với XML).

Vì vậy, ngay từ đầu, tôi đã tạo hai tệp (ví dụ: config.rb và responsees.rb), trong đó tôi đã đặt các câu trả lời được xác định trước mà máy chủ SOAP sẽ trả về. Trong config.rb, tôi đã đặt tệp WSDL, nhưng dưới dạng một chuỗi.

@@wsdl = '<wsdl:definitions name="StockQuote"
         targetNamespace="http://example.com/stockquote.wsdl"
         xmlns:tns="http://example.com/stockquote.wsdl"
         xmlns:xsd1="http://example.com/stockquote.xsd"
         xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
         xmlns="http://schemas.xmlsoap.org/wsdl/">
         .......
      </wsdl:definitions>'

Trong responsees.rb, tôi đã đặt các mẫu phản hồi mà máy chủ SOAP sẽ trả về cho các tình huống khác nhau.

@@login_failure = "<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Body>
        <LoginResponse xmlns="http://tempuri.org/">
            <LoginResult xmlns:a="http://schemas.datacontract.org/2004/07/WEBMethodsObjects" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
                <a:Error>Invalid username and password</a:Error>
                <a:ObjectInformation i:nil="true"/>
                <a:Response>false</a:Response>
            </LoginResult>
        </LoginResponse>
    </s:Body>
</s:Envelope>"

Vì vậy, bây giờ hãy để tôi chỉ cho bạn cách tôi đã thực sự tạo máy chủ.

require 'sinatra'
require 'json'
require 'nokogiri'
require_relative 'config/config.rb'
require_relative 'config/responses.rb'

after do
# cors
headers({
    "Access-Control-Allow-Origin" => "*",
    "Access-Control-Allow-Methods" => "POST",
    "Access-Control-Allow-Headers" => "content-type",
})

# json
content_type :json
end

#when accessing the /HaWebMethods route the server will return either the WSDL file, either and XSD (I don't know exactly how to explain this but it is a WSDL dependency)
get "/HAWebMethods/" do
  case request.query_string
    when 'xsd=xsd0'
        status 200
        body = @@xsd0
    when 'wsdl'
        status 200
        body = @@wsdl
  end
end

post '/HAWebMethods/soap' do
request_payload = request.body.read
request_payload = Nokogiri::XML request_payload
request_payload.remove_namespaces!

if request_payload.css('Body').text != ''
    if request_payload.css('Login').text != ''
        if request_payload.css('email').text == some username && request_payload.css('password').text == some password
            status 200
            body = @@login_success
        else
            status 200
            body = @@login_failure
        end
    end
end
end

Tôi hy vọng bạn sẽ thấy điều này hữu ích!



0

Tôi đã sử dụng lệnh gọi HTTP như bên dưới để gọi phương thức SOAP,

require 'net/http'

class MyHelper
  def initialize(server, port, username, password)
    @server = server
    @port = port
    @username = username
    @password = password

    puts "Initialised My Helper using #{@server}:#{@port} username=#{@username}"
  end



  def post_job(job_name)

    puts "Posting job #{job_name} to update order service"

    job_xml ="<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns=\"http://test.com/Test/CreateUpdateOrders/1.0\">
    <soapenv:Header/>
    <soapenv:Body>
       <ns:CreateTestUpdateOrdersReq>
          <ContractGroup>ITE2</ContractGroup>
          <ProductID>topo</ProductID>
          <PublicationReference>#{job_name}</PublicationReference>
       </ns:CreateTestUpdateOrdersReq>
    </soapenv:Body>
 </soapenv:Envelope>"

    @http = Net::HTTP.new(@server, @port)
    puts "server: " + @server  + "port  : " + @port
    request = Net::HTTP::Post.new(('/XISOAPAdapter/MessageServlet?/Test/CreateUpdateOrders/1.0'), initheader = {'Content-Type' => 'text/xml'})
    request.basic_auth(@username, @password)
    request.body = job_xml
    response = @http.request(request)

    puts "request was made to server " + @server

    validate_response(response, "post_job_to_pega_updateorder job", '200')

  end



  private 

  def validate_response(response, operation, required_code)
    if response.code != required_code
      raise "#{operation} operation failed. Response was [#{response.inspect} #{response.to_hash.inspect} #{response.body}]"
    end
  end
end

/*
test = MyHelper.new("mysvr.test.test.com","8102","myusername","mypassword")
test.post_job("test_201601281419")
*/

Hy vọng nó giúp. Chúc mừng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.