Bypass the OAS validation and trigger the MethodNotAllowed

When I changed the method from "GET" to "POST," I got "400 Bad Request," which is not good at all. I have a flow that will trigger if the user changes the method. I need to bypass the OAS validation so that the "method not allowed" error message appears in my response. I put the OAS validation policy in the Proxy Endpoint/PreFlow.

Screenshot 2022-12-16 111659.jpg

 

Screenshot 2022-12-16 111754.jpg

 

Screenshot 2022-12-16 112052.jpg

Solved Solved
0 4 749
1 ACCEPTED SOLUTION

When I try an OASValidation step, I get a verbose error message that indicates why the OASValidation has rejected my request. The message identifies that the path is wrong, or the verb is wrong, or whatever. Is that not what you see?

 

$ curl -i -X POST $endpoint/oas-test1/t1 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r1
x-request-id: c8ffd787-13f8-4629-a3c8-3945779db12f
content-length: 227
date: Wed, 21 Dec 2022 17:46:58 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{"fault":{"faultstring":"OASValidation OAS-1 with resource \"oas:\/\/test-spec1.yaml\": failed with reason: \"[ERROR - No API path found that matches request '\/t1'.: []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}

$ curl -i -X POST $endpoint/oas-test1/persons/13 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r1
x-request-id: e59332d6-5fc4-4a7b-86f7-73094771ca39
content-length: 232
date: Wed, 21 Dec 2022 17:47:09 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{"fault":{"faultstring":"OASValidation OAS-1 with resource \"oas:\/\/test-spec1.yaml\": failed with reason: \"[ERROR - POST operation not allowed on path '\/persons\/13'.: []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}

 

If you don't like the "standard" error messages that get generated from the policy, You can use FaultRules within the proxy to override them and substitute your own. To do that, introduce this in your proxy endpoint:

 

<ProxyEndpoint name="endpoint1">
  <Description>...</Description>
  <HTTPProxyConnection>
     ....
  </HTTPProxyConnection>

  <FaultRules>
    <FaultRule name='rule1'>
      <Step>
        <Name>JS-Override-Message</Name>
      </Step>
      <Condition>fault.name = "Failed" AND fault.subcategory = "OASValidationFailure"</Condition>
    </FaultRule>
  </FaultRules>
  ...

 

And the JavaScript step can look like this:

 

<Javascript name='JS-Override-Message' >
  <Source><![CDATA[
var r = context.getVariable('fault.reason');
var m = r.match(new RegExp('\\[ERROR - (.+?)\\..+'));
if (m) {
  r = {error: m[1]};
  context.setVariable('message.content', JSON.stringify(r, null, 2) + '\n');
}
  ]]>
  </Source>
</Javascript>

 

Basically, you are overriding the message content, without changing the 400 status code or "Bad Request" status string. The "400" and "Bad Request" seem appropriate to me.

When I do this I get this kind of result:

 

curl -i -X POST $endpoint/oas-test1/persons/13 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r7
x-request-id: 91a3dddd-0214-4f13-a038-37149537000a
content-length: 66
date: Wed, 21 Dec 2022 18:17:20 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{
  "error": "POST operation not allowed on path '/persons/13'"
}

 

For the curious, when the OASValidation step rejects an inbound request, it sets a fault. You can retrieve these context variables that reference it:

property name expected value
fault.name Failed
fault.reason OASValidation OAS-1 with resource "OAS-SPEC-HERE": failed with reason: "[ERROR - REASON-STRING-HERE: []]"
fault.category Step
fault.subcategory OASValidationFailure

View solution in original post

4 REPLIES 4

I am a little perplexed by your question. 

You have an OAS spec that disallows POST. 

You have an OASValidation policy , using that spec, in your proxy. 

When the client sends in a POST request, the proxy returns 400 Bad Request. 

That seems like the right thing.  You said "That is not good at all."  But that is the meaning of 400 - it is a way for the server to tell  the client that the  request sent by the client was invalid. 

I guess you want more elaborate information in the error message? Is that right? 

Yes thats correct

When I try an OASValidation step, I get a verbose error message that indicates why the OASValidation has rejected my request. The message identifies that the path is wrong, or the verb is wrong, or whatever. Is that not what you see?

 

$ curl -i -X POST $endpoint/oas-test1/t1 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r1
x-request-id: c8ffd787-13f8-4629-a3c8-3945779db12f
content-length: 227
date: Wed, 21 Dec 2022 17:46:58 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{"fault":{"faultstring":"OASValidation OAS-1 with resource \"oas:\/\/test-spec1.yaml\": failed with reason: \"[ERROR - No API path found that matches request '\/t1'.: []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}

$ curl -i -X POST $endpoint/oas-test1/persons/13 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r1
x-request-id: e59332d6-5fc4-4a7b-86f7-73094771ca39
content-length: 232
date: Wed, 21 Dec 2022 17:47:09 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{"fault":{"faultstring":"OASValidation OAS-1 with resource \"oas:\/\/test-spec1.yaml\": failed with reason: \"[ERROR - POST operation not allowed on path '\/persons\/13'.: []]\"","detail":{"errorcode":"steps.oasvalidation.Failed"}}}

 

If you don't like the "standard" error messages that get generated from the policy, You can use FaultRules within the proxy to override them and substitute your own. To do that, introduce this in your proxy endpoint:

 

<ProxyEndpoint name="endpoint1">
  <Description>...</Description>
  <HTTPProxyConnection>
     ....
  </HTTPProxyConnection>

  <FaultRules>
    <FaultRule name='rule1'>
      <Step>
        <Name>JS-Override-Message</Name>
      </Step>
      <Condition>fault.name = "Failed" AND fault.subcategory = "OASValidationFailure"</Condition>
    </FaultRule>
  </FaultRules>
  ...

 

And the JavaScript step can look like this:

 

<Javascript name='JS-Override-Message' >
  <Source><![CDATA[
var r = context.getVariable('fault.reason');
var m = r.match(new RegExp('\\[ERROR - (.+?)\\..+'));
if (m) {
  r = {error: m[1]};
  context.setVariable('message.content', JSON.stringify(r, null, 2) + '\n');
}
  ]]>
  </Source>
</Javascript>

 

Basically, you are overriding the message content, without changing the 400 status code or "Bad Request" status string. The "400" and "Bad Request" seem appropriate to me.

When I do this I get this kind of result:

 

curl -i -X POST $endpoint/oas-test1/persons/13 
HTTP/2 400 
content-type: application/json
apiproxy: oas-test1 r7
x-request-id: 91a3dddd-0214-4f13-a038-37149537000a
content-length: 66
date: Wed, 21 Dec 2022 18:17:20 GMT
via: 1.1 google
alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

{
  "error": "POST operation not allowed on path '/persons/13'"
}

 

For the curious, when the OASValidation step rejects an inbound request, it sets a fault. You can retrieve these context variables that reference it:

property name expected value
fault.name Failed
fault.reason OASValidation OAS-1 with resource "OAS-SPEC-HERE": failed with reason: "[ERROR - REASON-STRING-HERE: []]"
fault.category Step
fault.subcategory OASValidationFailure

Instead of bypassing the OAS validation, you could add your RF policy before the OAS Validation with a condition based on the request.verb