วิธีที่ดีที่สุดในการใช้ SOAP กับ Ruby คืออะไร?


91

ลูกค้าของฉันได้ขอให้ฉันรวม API ของบุคคลที่สามเข้ากับแอพ Rails ของพวกเขา ปัญหาเดียวคือ API ใช้ SOAP Ruby ได้ทิ้ง SOAP โดยทั่วไปเพื่อให้ REST พวกเขามีอะแดปเตอร์ Java ที่เห็นได้ชัดว่าใช้งานได้กับ Java-Ruby bridge แต่เราต้องการเก็บทั้งหมดไว้ใน Ruby ถ้าเป็นไปได้ ฉันมองเข้าไปใน soap4r แต่ดูเหมือนว่าจะมีชื่อเสียงที่ไม่ดีเล็กน้อย

แล้ววิธีที่ดีที่สุดในการรวมการโทร SOAP เข้ากับแอพ Rails คืออะไร?

คำตอบ:


36

เราใช้soap/wsdlDriverคลาสในตัวซึ่งจริงๆแล้วคือ SOAP4R สุนัขมันช้า แต่เรียบง่ายจริงๆ SOAP4R ที่คุณได้รับจากอัญมณี / ฯลฯ เป็นเพียงเวอร์ชันอัปเดตของสิ่งเดียวกัน

รหัสตัวอย่าง:

require 'soap/wsdlDriver'

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

เกี่ยวกับมัน


37
สาเหตุส่วนหนึ่งที่เป็น "Dog Slow" คือคุณกำลังสร้างพร็อกซีทุกครั้งที่คุณเชื่อมต่อกับบริการ คุณสามารถหลีกเลี่ยงความเจ็บปวดนี้ได้โดยใช้ wsdl2ruby เพื่อสร้างพร็อกซีอย่างถาวรจากนั้นเรียกใช้พร็อกซีที่สร้างไว้ล่วงหน้า
Steve Weet

7
เราทำได้ แต่นั่นหมายถึงการติดตั้ง wsdl2ruby ไปเรื่อย ๆ บางครั้ง Dog Slow ก็ใช้ได้ :-)
Orion Edwards

1
หากคุณต้องการสร้างคลาสพร็อกซีสำหรับ Savon คุณสามารถทำตามแนวทางของ kredmer ในการสร้างวิธีการทำสบู่ได้ทันทีด้วยความช่วยเหลือของ SoapUI เพื่อเติมชื่อเมธอดและไม่ต้องสร้างตัวแยกวิเคราะห์ wsdl ที่กำหนดเอง :) แทนที่จะเก็บวิธีการทั้งหมดไว้ในหน่วยความจำคุณสามารถเขียนลงไฟล์โดยเฉพาะอย่างยิ่งถ้าคุณมีจำนวนมาก
Dejan

3
04/2015: Soap4r ตายแล้วเว็บไซต์ไม่ทำงาน ดูเหมือนว่า Savon จะเป็นตัวเลือกทั่วไปในขณะนี้
Puce

ฉันขุดไปรอบ ๆ ในพื้นที่นี้และค้นพบ soap4r-ng ซึ่งยังคงได้รับการดูแลอยู่github.com/rubyjedi/soap4r
Ghoti

170

ฉันสร้างSavonเพื่อให้โต้ตอบกับเว็บเซิร์ฟเวอร์ SOAP ผ่าน Ruby ได้ง่ายที่สุด
ฉันขอแนะนำให้คุณลองดู


5
+1 สำหรับ savon ไม่ใช่ทุบ soap4r - แต่ฉันมีประสบการณ์ที่แย่มากกับมัน ขาดเอกสารที่ดีและยุ่งยากเกินไป
konung

1
ดี! โลก SOAP ในทับทิมดีขึ้นตั้งแต่ครั้งที่แล้วที่ฉันต้องใช้ Soap4R เพื่อทำสิ่งนี้ (~ 18 เดือนที่แล้ว)
madlep

ท่านใดช่วยกด saber api โดยใช้ savon ได้ไหม ฉันมีรหัสที่ savon ให้วิธีการโดยใช้ wsdl ของ SOAP แต่ฉันไม่สามารถส่งคำขอโดยใช้ savon ในรูปแบบ xml ได้
Jai Kumar Rajput


5

ฉันแนะนำซาวอนด้วย ฉันใช้เวลาหลายชั่วโมงเกินไปในการพยายามจัดการกับ Soap4R โดยไม่มีผลลัพธ์ ขาดการทำงานอย่างมากไม่มีเอกสาร

ซาวอนคือคำตอบสำหรับฉัน



3

เพิ่งให้ข้อมูลของฉันใช้งานได้ภายใน 3 ชั่วโมงโดยใช้ Savon

เอกสารการเริ่มต้นใช้งานในหน้าแรกของ Savon นั้นง่ายต่อการติดตามและตรงกับสิ่งที่ฉันเห็น (ไม่ใช่เช่นนั้นเสมอไป)


2

Kent Sibilev จากDatanoiseได้ย้ายไลบรารี Rails ActionWebService ไปยัง Rails 2.1 (ขึ้นไป) สิ่งนี้ช่วยให้คุณสามารถเปิดเผยบริการ SOAP ของคุณเองได้ เขายังมีโหมดนั่งร้าน / ทดสอบซึ่งช่วยให้คุณทดสอบบริการของคุณโดยใช้เบราว์เซอร์


2

ฉันใช้ SOAP ใน Ruby เมื่อฉันต้องสร้างเซิร์ฟเวอร์ SOAP ปลอมสำหรับการทดสอบการยอมรับของฉัน ฉันไม่รู้ว่านี่เป็นวิธีที่ดีที่สุดในการแก้ไขปัญหาหรือไม่ แต่มันได้ผลสำหรับฉัน

ฉันใช้ Sinatra gem (ฉันเขียนเกี่ยวกับการสร้างจุดสิ้นสุดจำลองด้วย Sinatra ที่นี่ ) สำหรับเซิร์ฟเวอร์และNokogiriสำหรับสิ่ง XML (SOAP ทำงานร่วมกับ XML)

ดังนั้นในตอนแรกฉันได้สร้างไฟล์สองไฟล์ (เช่น config.rb และ responses.rb) ซึ่งฉันได้ใส่คำตอบที่กำหนดไว้ล่วงหน้าซึ่งเซิร์ฟเวอร์ SOAP จะส่งคืน ในconfig.rbฉันได้ใส่ไฟล์ WSDL แต่เป็นสตริง

@@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>'

ในresponses.rbฉันได้ใส่ตัวอย่างสำหรับการตอบสนองที่เซิร์ฟเวอร์ SOAP จะส่งคืนสำหรับสถานการณ์ต่างๆ

@@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>"

ตอนนี้ให้ฉันแสดงให้คุณเห็นว่าฉันสร้างเซิร์ฟเวอร์ได้อย่างไร

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

ฉันหวังว่าคุณจะพบว่าสิ่งนี้มีประโยชน์!



0

ฉันใช้การโทร HTTP เหมือนด้านล่างเพื่อเรียกวิธี 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")
*/

หวังว่าจะช่วยได้ ไชโย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.