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

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

问题描述

我正在尝试实施 ESB 解决方案来替换复杂 Web 服务架构的 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 传播到发送块中定义的端点.我想我找到了一种 RESTful 方式(没有让它完全工作)来做我在这里想做的事情.如您所见,我可以在 api 中指定一个上下文,然后使用资源的 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 和服务端点(上下文 URI)正常工作,而不像在代理服务方法上那样强制它工作.请注意,如果您可以使用 WSO2 团队建议的 contextURI (/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).

所以基本上,我们检查包含上下文 URI 的To"属性,例如/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>

注意上面的 xslt 中的名称 - https://services.mycompany.com.您可以将其更改为您想要的任何内容,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 条目一样.所以我只会发布实际外部文件的内容.

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.

这是一个艰难的 cookie,我不得不深入研究 WSO2 源代码并找出一些未记录"的功能.好吧,它在 WSO2 世界中是未记录的",但由于 WSO2 使用了第三方库,该库具有许多未在 WSO2 中发布的功能,因此另有记录.请注意,端点指向应用层实例,我们使用循环算法将流量分配到可用的应用层实例.

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:

http://esbhost.com:8280/firstservice/10.06/service

这里的上下文 uri 是/firstservice/10.06/service" - 所以我们希望将它附加到实际的应用层服务器 url.换句话说,我希望它变成 http://firsthost.com:5022/firstservice/10.06/服务

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},第 3 方库会将上下文 uri 中存在的特殊字符转换为它们的 http 安全等效字符 - 例如 %20f 或其他.所以我们的 url 现在变成 http://firsthost: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天全站免登陆