wso2 esb customURI / serviceURI与表达式 [英] wso2 esb customURI / serviceURI with expression

查看:127
本文介绍了wso2 esb customURI / serviceURI与表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实施ESB解决方案,以取代复杂Web服务体系结构的Web层部分。网络层只是接收来自客户端的请求,并分发给给定的一组应用层实例。

I am trying to implement ESB solution to replace a web-tier part of a complex web-service architecture. The web-tier just receives the request from clients and distributes to a given set of app-tier instances.

由于端点已经由客户端定义和使用,我必须按照此处所述使用 CustomURI方法构建ESB代理- http://achala11.blogspot.com/2012/08/access-wsdl-for-customuri-wso2-esb.html -公开端点和wsdl。

Since the end-points are already defined and used by clients, I had to build the ESB proxy using the "CustomURI" approach as described here - http://achala11.blogspot.com/2012/08/access-wsdl-for-customuri-wso2-esb.html - to expose the end-point and wsdl.

请注意,ServiceURI仅允许指定固定的上下文路径(如果我错了,请更正我)。例如:
如果WSDL端点为http:// localhost:8280 / CustomURL / Part1 / Part2?wsdl,则相应的ServiceURI条目为

Note that ServiceURI only allows to specify a fixed context path (correct me if I am wrong). For example: If WSDL end-point is http:// localhost:8280/CustomURL/Part1/Part2?wsdl, the corresponding ServiceURI entry is

<parameter name="ServiceURI">/CustomURL/Part1/Part2</parameter> 

我要使用的表达式是这样的:

What I want to use is an expression like this:

<parameter name="ServiceURI">/CustomURL/*</parameter>

表示上下文路径中所有以/ CustomURL开头的请求都将由代理处理。在代理内部,我喜欢将上下文URI传播到send块中定义的端点。我想我找到了一种RESTful的方式(无法使其完全正常工作)来完成我在这里尝试做的事情。如您所见,我可以在api中指定上下文,然后使用resource的url-mapping选项将所有请求路由到api块。稍后,我尝试使用 http端点方法来构建附加了contextURI的端点。

to indicate that all requests that starts with /CustomURL in the context path will be handled by the proxy. Inside the proxy, I like to propagate the context URI to the endpoint defined in the send block. I think I found a RESTful way (didn't get it to work completely) of doing what I am trying to do here. As you can see, I can specify a context in the api and then use url-mapping option of resource to route all request to the api block. Later I am trying to use the "http endpoint" approach to construct the endpoint with the contextURI appended.

<api xmlns="http://ws.apache.org/ns/synapse" name="customService1" context="/CustomServices">
<resource methods="POST" url-mapping="/*">
  <inSequence>
     <log level="custom">
        <property name="uri.var.servicepath" expression="get-property('To')"/>
     </log>
     <send>
        <endpoint name="HTTPEndpoint">
           <http method="POST" uri-template="http://localhost:8001/{uri.var.servicepath}"/>
        </endpoint>
     </send>
  </inSequence>
  <outSequence>
     <send/>
  </outSequence>
</resource>
</api>

我希望您可以为我提供类似的SOAP服务解决方案-一种指定contextURI和然后将contextURI包含到代理将请求发送到的最终端点。请注意,端点将是条目列表(负载平衡条目),但是为了简单起见,我只在上面保留了一个端点条目。

I hope you can help me with a similar solution for SOAP services - a way to specify a contextURI and then include the contextURI to the final endpoint that the proxy will send the request to. Note that the endpoints will be a list of entries (load balanced entries), but to keep things simple, I just kept one endpoint entry above.

推荐答案

我发现了一个更干净/更好的解决方案-它只是上述答案的增强版本。

I found a cleaner/better solution - it is just an enhanced version of the above answer.

主要挑战是获得SOAP WSDL和服务端点(Context URI)的工作不会像代理服务方法那样强制执行。 请注意,如果您可以与contextURI WSO2团队合作(/ services //),您无需执行任何这些操作。标准文档将包含所有内容

The main challenge is to get the SOAP WSDL and the Service endpoint (Context URI) work without forcing it like it happens on a proxy service approach. Note that if you can work with the contextURI WSO2 team suggests (/services//), you don't have to do any of these. The standard documentation will have all the details you need.

逻辑是:

定义3个序列(我将它们分为三个,但是您也可以将所有这些都放在一个序列中。)

Define 3 sequences (I split them into three, but you can put all these in just one sequence as well).

主序列 (标准内置一个-如果请求未遵循ESB中已定义的代理服务规则,则该序列将获取所有流量。在主序列中,我们只是将所有传入的请求路由到另一个序列,在该序列中进行过滤/条件路由。

main sequence (the standard built-in one - this is the sequence that gets all traffic if a request doesn't follow proxy service rules already defined in ESB). In main sequence, we just route all the incoming requests to another sequence where we do the filtering/conditinal routing.

<sequence name="main">
  <in>
     <log level="full"/>
     <sequence key="routing_seq"/>
  </in>
  <out>
     <send/>
  </out>
  <description>The main sequence for the message mediation</description>
</sequence>

* routing_sequence *
就像在第一个答案中一样,我们将根据请求中的上下文URI将传入请求路由到其他特殊序列。

*routing_sequence* Just like in the first answer, we are going to route the incoming requests to other special sequences based on the context URI in the request.

<sequence xmlns="http://ws.apache.org/ns/synapse" name="routing_seq">
   <in>
      <log level="custom">
         <property xmlns:ns="http://org.apache.synapse/xsd" name="Current URL" expression="get-property('To')"/>
      </log>
      <conditionalRouter continueAfter="false">
         <conditionalRoute breakRoute="false" asynchronous="false">
            <condition>
               <or>
                  <match type="url" regex="/firstService/10\.06/.*"/>
                  <match type="url" regex="/firstServiceVariant/.*"/>
               </or>
            </condition>
            <target sequence="firstService_seq"/>
         </conditionalRoute>
         <conditionalRoute breakRoute="false" asynchronous="false">
            <condition>
                  <match type="url" regex="/secondService.*"/>
            </condition>
            <target sequence="second_seq"/>
         </conditionalRoute>
      </conditionalRouter>
   </in>
</sequence>

* firstservice_seq *

现在,我们准备处理传入的请求-请注意,在上一步中,我们将应用程序标识为 firstservice。您可以在此处收到两种请求-一种是针对WSDL的请求,另一种是肥皂请求

Now we are ready to handle the incoming request - note that we identified the application as "firstservice" in the previous step. There are two kinds of requests you can receive here - one is for WSDL and the other one is a soap request

<sequence xmlns="http://ws.apache.org/ns/synapse" name="firstService_seq">
   <in>

     <property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>

     <!-- We are checking whether the request ends with a ?wsdl or .xsd -->
     <!-- For that we are using the context URI present in the 'To' field -->
     <!-- if it is a wsdl or xsd request, we are converting it to a HTTP GET method -->
     <!-- and sending to the final endpoint. All soap operation requests are sent as HTTP POST -->


     <switch xmlns:ns="http://org.apache.synapse/xsd" source="get-property('To')">
        <case regex=".*(?:\?[Ww][Ss][Dd][Ll]|\.[Xx][Ss][Dd])\s*$">
           <property name="HTTP_METHOD" value="GET"/>
           <property name="messageType" value="text/xml"/>
           <send receive="wsdl_transformer_seq">
              <endpoint key="local-enrty-firstservice-ep-key"/>
           </send>
           <drop/>
        </case>
        <!-- default means non-wsdl/non-xsd - which means a regular soap operation on the service -->
        <default>
           <property name="HTTP_METHOD" value="POST"/>
           <send>
              <endpoint key="local-enrty-firstservice-ep-key"/>
           </send>
        </default>
     </switch>

   </in>
   <out>
      <send/>
   </out>
</sequence>

希望您阅读序列定义中的注释。如您所见,我正在将wsdl和xsd请求转换为HTTP GET,以避免在应用程序层造成任何混乱,否则,可能会从流中的某个地方注入一些垃圾SOAP正文部分。

Hope you read the comments in the sequence definition. As you can see, I am converting the wsdl and xsd requests into HTTP GET to avoid any confusion at the app-tier as otherwise, there could be some junk SOAP body parts get injected from somewhere in the flow).

基本上,我们检查 To属性,其中包含上下文URI,例如/firstservice/10.06/service?WSDL(如果它是WSDL请求)或/firstservice/10.06/service-如果是SOAP请求。根据该值,我们决定如何处理请求。

So basically, we check the 'To' property which contains a Context URI like /firstservice/10.06/service?WSDL (if it was a WSDL request) or /firstservice/10.06/service - if it was a SOAP request. Based on the value, we decide what to do with the request.

请注意wsdl逻辑中的以下部分:

Note the below section in the wsdl logic:

<send receive="wsdl_transformer_seq">
              <endpoint key="local-enrty-firstservice-ep-key"/>
           </send>
           <drop/>
 </send>

发生的事情是,当我们从端点拉下wsdl时(我将稍后解释),schemaLocation和soap:address字段包含处理请求的实际服务器实例的信息(主机名和端口)。这是不想要的结果,因为您将内部详细信息暴露给客户和其他人。所以我们应该掩盖它。这样做的方法是在WSO2中使用特殊功能。在发送中,您可以指定另一个序列,该序列将在发送到客户端之前接收结果。或多或少就像您在序列中定义< out> 部分。由于我们不希望所有请求都进行这种特殊处理,因此我们没有定义仅应用于wsdl / xsd请求的特殊序列。在 wsdl_transformer_seq 中,我们使用XSLT更改wsdl或xsd响应中存在的主机名和端口。

What happens is that when we pull the wsdl from the endpoint (which I will explain shortly), schemaLocation and soap:address fields contain the information (hostname and port) of actual server instance that processed the request. This is an unwanted result as you are exposing your internal details to the clients and others. So we should mask it. The way to do that is to use a special feature in WSO2. In a send, you can specify another sequence that will receive the results of the send before it goes to the client. It is more or less like you define an <out> portion in a sequence. Since we don't want this particular manipulation happen to all requests, we are not defining a special sequence that gets applied to only wsdl/xsd reqeusts. In the wsdl_transformer_seq, we use XSLT to change the hostname and port present in the wsdl or xsd response.

wsdl_transformer_seq >

<sequence name="wsdl_transformer_seq">
  <xslt xmlns:ns="http://org.apache.synapse/xsd"
        key="xslt-url-manipulator"
        source="/"/>
  <send/>
</sequence>

请注意,我将这些条目(例如xslt转换器)外部化并通过本地条目加载它们注册表。

Note that I externalized these entries (xslt transformer for example) and get them loaded through a local-entry registry.

  <localEntry key="xslt-url-manipulator"
           src="file:repository/myapp/resources/transform/url-in-wsdl-transform.xslt"/>

现在 url-in-wsdl-transform.xslt

<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                  xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
                  version="2.0">
     <xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
     <xsl:param name="newURL">https://services.mycompany.com</xsl:param>
     <xsl:template match="@*|node()">
        <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
     </xsl:template>
     <xsl:template match="soap:address/@location">
        <xsl:attribute name="location">
           <xsl:value-of select="replace(.,'https?://[^/]*',$newURL)"/>
        </xsl:attribute>
     </xsl:template>
     <xsl:template match="xs:import/@schemaLocation">
        <xsl:attribute name="schemaLocation">
           <xsl:value-of select="replace(.,'https?://[^/]*',$newURL)"/>
        </xsl:attribute>
     </xsl:template>
  </xsl:stylesheet>

请注意名称- https://services.mycompany.com -在上面的xslt中。您可以将其更改为所需的格式,wsdl和xsd中的schemaLocation和soap:address字段现在将在host:port区域中使用

Note the name - https://services.mycompany.com - in the xslt above. You can change it to whatever you want and the schemaLocation and soap:address fields in the wsdl and xsd will now use that in the host:port area

local-enrty-firstservice-ep-key
注意,这也是一个外部加载的文件-就像上面的xslt条目一样。因此,我将只发布actul外部文件的内容。

And finally the endpoint local-enrty-firstservice-ep-key Note that this as well is an externally loaded file - just like the xslt entry above. So I will only post the content of the actul external file.

这是一个很难解决的问题,我不得不仔细研究WSO2源代码并找出一些未记录的功能。嗯,它在WSO2世界中是未记录的,但是在WSO2中使用的是第三方库,该库具有许多未在WSO2中发布的功能。
请注意,端点指向应用程序层实例,我们使用roundrobin算法将流量分配给avilalble应用程序层实例。

This was a tough cookie and I had to dig through WSO2 source code and figure out some "undocumented" features. Well, it is "undocumented" in WSO2 world, but documented otherwise as WSO2 uses a third-party library which has many features that are not published in WSO2. Note that the endpoint points to the app-tier instances and we use the roundrobin algorithm to distribute the traffic to the avilalble app-tier instances.

<endpoint xmlns="http://ws.apache.org/ns/synapse">
  <loadbalance algorithm="org.apache.synapse.endpoints.algorithms.RoundRobin">
     <endpoint name="firsthost_5012">
        <http uri-template="http://firsthost.com:5012{+uri.var.servicepath}"/>
     </endpoint>
     <endpoint name="firsthost_5022">
        <http uri-template="http://firsthost.com:5022{+uri.var.servicepath}"/>
     </endpoint>
  </loadbalance>
  <property xmlns:ns="http://org.apache.synapse/xsd"
            name="uri.var.servicepath"
            expression="get-property('To')"/>
</endpoint>

这里发生了很多魔术-
首先我们将上下文uri保存为特殊的变量uri.var.servicepath
现在,我们将其与WSO 4.7.0及更高版本中可用的新 http端点功能一起使用。

There is lot of magic happens here - First we save the context uri to a special variable called uri.var.servicepath Now we will use that with the new "http endpoint" feature available from WSO 4.7.0 onwards.

http端点使用uri-template-您可以在其中动态构建端点。因此,我不必在配置中指定上下文URI-
因此,我们进入ESB的原始请求就是这样的:

http endpoint uses uri-template - where you can dynamically construct the endpoint. So I don't have to specify the context URI in the configuration - So let us say the original request we got into ESB was like this:

< a href = http://esbhost.com:8280/firstservice/10.06/service rel = nofollow> http://esbhost.com:8280/firstservice/10.06/service

这里的上下文uri是 /firstservice/10.06/service-因此我们希望将其附加到实际的应用层服务器URL。换句话说,我希望它成为 http://firsthost.com:5022/firstservice/10.06/ service

The context uri here is "/firstservice/10.06/service" - so we want this to be appended to the actual app-tier server url. In other words, I want it to become http://firsthost.com:5022/firstservice/10.06/service

在http端点中,它使我们可以使用前面定义的特殊变量uri.var.servicepath。

In http endpoint, it allows us to use the special variable - uri.var.servicepath that we defined earlier.

      <http uri-template="http://firsthost.com:5022{+uri.var.servicepath}"/>

因为uri.var.servicepath开头已经包含'/',所以我没有单独指定。但是请注意括号中的+号。那是做什么用的?嗯-事实证明,WSO2使用了有趣的第三方库-该死的uri处理器-它主要用于RESTful API。不幸的是,如果您这样简单地使用该字段,请 http://firsthost.com:5022 {uri.var。 servicepath},第三方库会将上下文uri中存在的特殊字符转换为它们的http安全等效项-类似于%20f或类似的东西。所以我们的网址现在变成http://://host.5022%20ffirstservice%20f10.06 ....-不好。好了,这是第三党库中的特殊功能,可以节省您的一天。如果在特殊变量的开头加上+,则该翻译将被关闭;)-瞧-我们得到了想要的东西。

since uri.var.servicepath already contains a '/' at the beginning, I am not specifying separately. But note the + sign in the brackets. What is that for? hmmm - well, it turned out that WSO2 uses the interesting third-party library - "damn good uri processor" - it is mainly used for RESTful APIs. Unfortunately, if you plainly use the field like this, http://firsthost.com:5022{uri.var.servicepath}, the 3rd party library will convert the special characters present in the context uri to their http safe equivalent - something like %20f or whatever. So our url now becomes http ://firsthost:5022%20ffirstservice%20f10.06.... - it is not good. Well here comes the special feature in the 3rd party library that saves the day. If you put a + at the beginning of the special variable, this translation is turned off ;) - voila - we got what we wanted.

就是这样。我将尝试在下面发布完整的配置(减去在以上各节中可以找到的外部条目)

So that is it folks. I will try to post the full configuration below (minus the externalized entries that you can find in the above sections)

<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
   <registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
      <parameter name="cachableDuration">15000</parameter>
   </registry>
   <localEntry key="xslt-url-manipulator"
               src="file:repository/myapp/resources/transform/url-in-wsdl-transform.xslt"/>
   <localEntry key="local-enrty-firstservice-ep-key"
               src="file:repository/myapp/resources/endpoint/firstservice-endpoints.xml">
   </localEntry>
   <sequence xmlns="http://ws.apache.org/ns/synapse" name="routing_seq">
   <in>
      <log level="custom">
         <property xmlns:ns="http://org.apache.synapse/xsd" name="context URI" expression="get-property('To')"/>
      </log>
      <conditionalRouter continueAfter="false">
         <conditionalRoute breakRoute="false" asynchronous="false">
            <condition>
               <or>
                  <match type="url" regex="/firstService/10\.06/.*"/>
                  <match type="url" regex="/firstServiceVariant/.*"/>
               </or>
            </condition>
            <target sequence="firstService_seq"/>
         </conditionalRoute>
         <conditionalRoute breakRoute="false" asynchronous="false">
            <condition>
                  <match type="url" regex="/secondService.*"/>
            </condition>
            <target sequence="second_seq"/>
         </conditionalRoute>
      </conditionalRouter>
   </in>
   </sequence>
   <sequence name="wsdl_transformer_seq">
      <xslt xmlns:ns="http://org.apache.synapse/xsd"
            key="xslt-url-manipulator"
            source="/"/>
      <send/>
   </sequence>
   <sequence name="fault">
      <log level="full">
         <property name="MESSAGE" value="Executing default 'fault' sequence"/>
         <property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
         <property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
      </log>
      <drop/>
   </sequence>
   <sequence name="firstservice_seq">
      <in>
         <property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
         <switch xmlns:ns="http://org.apache.synapse/xsd" source="get-property('To')">
            <case regex=".*(?:\?[Ww][Ss][Dd][Ll]|\.[Xx][Ss][Dd])\s*$">
               <property name="HTTP_METHOD" value="GET"/>
               <property name="messageType" value="text/xml"/>
               <send receive="wsdl_transformer_seq">
                  <endpoint key="local-enrty-firstservice-ep-key"/>
               </send>
               <drop/>
            </case>
            <default>
               <property name="HTTP_METHOD" value="POST"/>
               <send>
                  <endpoint key="local-enrty-firstservice-ep-key"/>
               </send>
            </default>
         </switch>
      </in>
   </sequence>
   <sequence name="main">
      <in>
         <filter xmlns:ns="http://org.apache.synapse/xsd"
                 source="get-property('To')"
                 regex="http://localhost:9000.*">
            <then>
               <send/>
            </then>
            <else/>
         </filter>
         <sequence key="routing_seq"/>
      </in>
      <out>
         <send/>
      </out>
      <description>The main sequence for the message mediation</description>
   </sequence>
</definitions>

我知道这是一篇非常冗长的文章-但想为那些关心的人解释细节。
希望能对某人有所帮助。

I know it is a very lengthy post - but wanted to explain the details for those who care. Hope it helps someone.

这篇关于wso2 esb customURI / serviceURI与表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆