How to make Apigee 4.23 (OPDK) allow HTTP 405 response from backend that doesn't have the ALLOW header?

1.7k views Asked by At

My backend server returns HTTP 405 back to Apigee 4.23 (OPDK) for a particular request. However, the backend fails to set the "ALLOW" header that the standard says that a 405 response should include.

Instead of fixing my backend (due to some constraints on touching a long running code base), I would like to handle this scenario in my proxy TargetEndpoint Response flow and add the ALLOW header. However, it looks like Apigee 4.23 (OPK) wouldn't let me do this and it sends the following response back to client:

HTTP/1.1 502 Bad Gateway
Content-Type: application/json
Content-Length: 139

{
  "fault":{
    "faultstring":"Received 405 Response without Allow Header",
    "detail": {
      "errorcode":"protocol.http.Response405WithoutAllowHeader"
    }
  }
}

I followed the documentation regarding setting the "success.codes" property on the TargetEndpoint:

<HTTPTargetConnection>
        <Properties>
            <Property name="success.codes">405</Property>
        </Properties>
        <URL>https://my.backend.url</URL>
</HTTPTargetConnection>

Still getting same error. How do I solve this ? Am using Apigee 4.23 (On Premises Deployment Kit)

3

There are 3 answers

1
Mike Malloy On

HTTP.ignore.allow_header.for.405 is checked only at system level not for each proxy. Instead of treating 405 as success in the proxy, you can treat that as a fault and handle it in the fault flow.

<FaultRules>
    <FaultRule name="defaultFaultHandling">
        <Step>
            <Name>AssignMessage-1</Name>
        </Step>
</FaultRule>
</FaultRules>

Where in AssignMessage he can add Allow header and return the response to client.

 <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<AssignMessage async="false" continueOnError="false" enabled="true" name="AssignMessage-1">
    <DisplayName>AssignMessage-1</DisplayName>
    <FaultRules/>
    <Properties/>

       <Set>
          <Headers> <Header name="Allow">GET, PUT</Header>   </Headers>      

      </Set>

    <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    <AssignTo createNew="true" transport="http" type="response"/>
</AssignMessage>
0
HusnainKhan On

I could handle this using a flow CatchAll as the last flow in Flows

<Flows>
  <!--
    ...
    -->
  <Flow name="CatchAll">
    <Request>
      <Step>
        <Name>raiseMethodNotAllowedFaultResponse</Name>
      </Step>
    </Request>
    <Response/>
  </Flow>
</Flows>

The correspondig raise fault policy

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RaiseFault async="false" continueOnError="false" enabled="true" name="raiseMethodNotAllowedFaultResponse">
  <DisplayName>raiseMethodNotAllowedFaultResponse</DisplayName>
<Properties/>
<FaultResponse>
    <Set>
      <Headers>
        <Header name="Allow">POST</Header>
      </Headers>
      <Payload contentType="text/plain">Method Not Allowed</Payload>
      <StatusCode>405</StatusCode>
      <ReasonPhrase>Method Not Allowed</ReasonPhrase>
    </Set>
  </FaultResponse>
<IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
</RaiseFault>
0
Jagjyot On

You can use the success codes property in the following way. Also we do not have an equivalent property for HTTP.ignore.allow_header.for.405 for Target Endpoint.

Test

Instead of using the below

        <HTTPTargetConnection>
           <Properties>
             <Property name="success.codes">405</Property>
           </Properties>
         <URL>https://my.backend.url</URL>
        </HTTPTargetConnection>

Use the below and let me know if it works or not:

             <HTTPTargetConnection>
                  <Properties>
                     <Property name="additional.success.codes">405</Property>
                  </Properties>
                <URL>https://my.backend.url</URL>
             </HTTPTargetConnection>