OSB - Processing Http errors from Restful service in Proxy Service - rest

I'm invoking a REST service from an OSB Proxy Service, which is working fine if the rest service response is a valid response, i.e., there's no errors. However if the rest service replies with an http error code (e.g. 400 Bad Request), I'm not able to capture anything else except the http error code:
$fault variable in OSB:
<con:fault xmlns:con="http://www.bea.com/wli/sb/context">
<con:errorCode>BEA-382502</con:errorCode>
<con:reason>
OSB Service Callout action received an error response
</con:reason>
<con:details>
<con1:ErrorResponseDetail xmlns:con1="http://www.bea.com/wli/sb/stages/transform/config">
<con1:http-response-code>400</con1:http-response-code>
</con1:ErrorResponseDetail>
</con:details>
<con:location>
<con:node>PipelinePairNode1</con:node>
<con:pipeline>PipelinePairNode1_request</con:pipeline>
<con:stage>stage1</con:stage>
<con:path>request-pipeline</con:path>
</con:location>
</con:fault>
But the rest service, is not only replying with 400 Bad Request, but also adding a message:
<Error>
<Message>The message header contains an invalid brand code.</Message>
</Error>
Which I'm not able to process in my proxy service. Does anyone knows if it is possible to access this message details in OSB or is it a limitation?
The rest service is clearly sending the message, because invoking it directly through soap-ui I'll get the following response:
HTTP/1.1 400 Bad Request
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 84
Content-Type: application/xml; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Mon, 09 Feb 2015 16:15:32 GMT
<Error><Message>The message header contains an invalid brand code.</Message></Error>
Thanks

I've just found out this is an OSB bug, in case of an HTTP Error code 400 being returned, if the http-content is "Application/XML" the message is ignored.
Oracle released a Patch at the end of last month to fix this issue, which I've tested and it works. I can get the message details in the $body variable now.
Patch: 16986497

If I understand your question, you want to get in addition to the http code, the message error?
I think you should use, in your message flow, an errorHandler , so that you can catch the error and do whatever you want with.

The proxy service operation selection algorithm cannot determine the operation name from the request or returns an invalid operation (one which is not in the WSDL or null). Possible reasons include the following:
An error occurs while computing the operation.
The operation selection algorithm returns null.
The operation selection algorithm returns an operation that is not of the of the operations declared by the WSDL.
Source

Related

spring gateway always returns 301, how to continue processing

This is clarification of the OP
I have a spring gateway that uses eureka server to route requests to registered spring boot eureka clients.
What I am seeing is that every request results in a 301 redirect containing a Location header. It seems that because the request is received on https://my-api.io/payment/payment-intent spring-gateway looks it up based upon these rules:
server.forward-headers-strategy=framework
feign.hystrix.enabled=false
spring.cloud.config.discovery.enabled = true
....
spring.cloud.gateway.routes[11].id=orders-service
spring.cloud.gateway.routes[11].uri=lb://orders-service
spring.cloud.gateway.routes[11].predicates[0]=Path=/payment/**,/order/**
spring.cloud.gateway.routes[11].predicates[1]=Method=GET, POST
spring.cloud.gateway.routes[11].predicates[2]=Header=APIKEY, (.*)
spring.cloud.gateway.routes[11].filters[0]=AuthorizationHeaderFilter
## these next two apparently have no impact
spring.cloud.gateway.routes[11].filters[1]=RewritePath=/(?<segment>.*),/payment/$\{segment},/order/$\{segment}
spring.cloud.gateway.routes[11].filters[2]=RedirectTo=301, lb://orders-service
And then returns the Response Headers:
Server: awselb/2.0
Date: Tue, 24 Jan 2023 17:58:36 GMT
Content-Type: text/html
Content-Length: 134
Connection: keep-alive
Location: https://my-api.io:8081/payment/payment-intent
If I enable "follow redirects" in Postman or curl, then it works fine. But that won't work in a mobile app, so I really need to have spring-gateway just route the call on first pass. I don't know if this is because the routes.uri defines the as coming from the load-balancer (since ports are dynamic and there are likely multiple instances) url so it seems like a different url or what.
I am desperately trying to find a way so that the request is just processed and not bounced back with a 301.
Now that I have context around the issue it turns out the issue was not with Spring Gateway since its just a passthru (after some validation). Thanks to spencergibb I was able to rule out gateway and realize it was a forwarding issue in AWS.

How to hide stack trace of Kafka connect api unhandled exception

As part of registering connectors in distributed mode, when some invalid json payload is passed in API request , I am getting error in response with full stack trace, which is not desirable in my case.
Response example:
HTTP/1.1 500 Internal Server Error Connection: close Date: Fri, 26 Jul 2019 08:27:17 GMT Content-Type: application/json Content-Length: 443 Server: Jetty(9.4.11.v20180605)
{"error_code":500,"message":"Cannot construct instance of `java.util.LinkedHashMap` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('')\n at [Source: (org.glassfish.jersey.message.internal.ReaderInterceptorExecutor $UnCloseableInputStream); line: 2, column: 46] (through reference chain: org.apache.k afka.connect.runtime.rest.entities.CreateConnectorRequest[\"config\"])"}
Is there any way to hide or shorten the full stack trace.
Note: I am using Hortonworks Kafka package.
The REST API returns what the REST API returns :)
So you could either (a) stop sending invalid JSON ;) (b) compile your own version of Kafka and disable the bits of output you don't want returned.

TFS Web Calling an external REST Service throws 401 error

When creating a web hook within TFS (to access an external rest service url), I get a 401 error when testing (within the TFS application). I think call is not hitting API at all.
Below is the response I can see
Status Code: 401
Reason Phrase: Unauthorized
HTTP Version: 1.1
Headers:
{
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate
WWW-Authenticate: NTLM
X-Powered-By: ASP.NET
X-UA-Compatible: IE=EmulateIE8
Date: Fri, 30 Mar 2018 21:05:26 GMT
Content-Length: 1293
Content-Type: text/html
}
Any help would be appreciated!
The error ID 401 usually related to the authorization.
You could first use postman to double check user ID access to the API.
Also use week hook to access some other rest service url such as the example in Web Hooks. This will narrow down if the issue related to rest service url.
Besides try to use Basic Authentication, you can use alternate account instead. How to please take a look at:Protecting a VSTS Web Hook with Basic Authentication

API Gateway Mock Integration Fails with 500

I have an API Gateway integration for a method/resource which works when I call it from the API but not when I actually call it:
$ aws apigateway test-invoke-method --rest-api-id $REST_API_ID \
--resource-id $RESOURCE_ID --http-method GET | jq -r .log,.body
This works out fine and I get the following output:
Tue May 16 17:46:42 UTC 2017 : Starting execution for request: test-invoke-request
Tue May 16 17:46:42 UTC 2017 : HTTP Method: GET, Resource Path: /status.json
Tue May 16 17:46:42 UTC 2017 : Method request path: {}
Tue May 16 17:46:42 UTC 2017 : Method request query string: {}
Tue May 16 17:46:42 UTC 2017 : Method request headers: {}
Tue May 16 17:46:42 UTC 2017 : Method request body before transformations:
Tue May 16 17:46:42 UTC 2017 : Endpoint response body before transformations:
Tue May 16 17:46:42 UTC 2017 : Endpoint response headers: {}
Tue May 16 17:46:42 UTC 2017 : Method response body after transformations: { "statusCode": 200 }
Tue May 16 17:46:42 UTC 2017 : Method response headers: {Content-Type=application/json}
Tue May 16 17:46:42 UTC 2017 : Successfully completed execution
Tue May 16 17:46:42 UTC 2017 : Method completed with status: 200
{ "statusCode": 200 }
However, I cannot access this at my URL, which is api.naftuli.wtf/v1/status.json. I have stages defined at glhf, stable, and v1, so by replacing that, you will see different responses. I just simply want a dummy response that returns a 200 JSON blob.
My Terraform for the resources is here as a Gist. Hopefully this fully shows my API Gateway configuration.
If I test invoke this from the CLI or from the web console, I get back what is expected. However, if I curl this from my deployed API at api.naftuli.wtf, I don't get anything nice:
$ for stage in glhf stable v1 ; do
> url="https://api.naftuli.wtf/${stage}/status.json"
> echo "${url}:"
> curl -i -H 'Content-Type: application/json' \
> https://api.naftuli.wtf/${stage}/status.json
> echo -e '\n
> done
https://api.naftuli.wtf/glhf/status.json:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:38 GMT
x-amzn-RequestId: 712ba52b-3a80-11e7-9fec-b79b62d3bf7f
X-Cache: Error from cloudfront
Via: 1.1 da7a5d0ed7f424609000879e43743066.cloudfront.net (CloudFront)
X-Amz-Cf-Id: hBwlbPCP9n2rlz53I-Qb9KoffHB_FoxUCZUaJYNnU3XhCWuMpQTP1Q==
{"message": "Internal server error"}
https://api.naftuli.wtf/stable/status.json:
HTTP/1.1 403 Forbidden
Content-Type: application/json
Content-Length: 23
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:38 GMT
x-amzn-RequestId: 71561066-3a80-11e7-9b00-6700be628328
x-amzn-ErrorType: ForbiddenException
X-Cache: Error from cloudfront
Via: 1.1 0c146399837c7d36c1f0f9d2636f8cf8.cloudfront.net (CloudFront)
X-Amz-Cf-Id: ITX765xD8s4sNuOdXaJ2kPvqPo-w_dsQK3Sq_No130FAHxFuoVhO8w==
{"message":"Forbidden"}
https://api.naftuli.wtf/v1/status.json:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
Content-Length: 36
Connection: keep-alive
Date: Tue, 16 May 2017 21:41:39 GMT
x-amzn-RequestId: 7185fa99-3a80-11e7-a3b1-2f9e659fc361
X-Cache: Error from cloudfront
Via: 1.1 586f1a150b4ba39f3a668b8055d4d5ea.cloudfront.net (CloudFront)
X-Amz-Cf-Id: dvnOa1s-YlwLSNzBfVyx5tSL6XrjFJM4_fES7MyTofykB3ReU5R1fg==
{"message": "Internal server error"}
My understanding of stages were that they were additional path prefixes to the base path under which all API resources were available. If I had a stage called v1 with a path of /v1, I'd expect that an API Gateway resource for status.json will be basically mapped under /v1, yielding /v1/status.json.
I may be misunderstanding how API Gateway base path mappings and stages work, but CloudWatch tells me that the call is at least happening, though failing for some obscure reason:
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Verifying Usage Plan for request: c5be3842-6af4-4725-a34f-d6eea8042d17. API Key: API Stage: tcips69qx2/prod_v1
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) API Key authorized because method 'GET /status.json' does not require API Key. Request will not contribute to throttle or quota limits
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Usage Plan check succeeded for API Key and API Stage tcips69qx2/prod_v1
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Starting execution for request: c5be3842-6af4-4725-a34f-d6eea8042d17
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) HTTP Method: GET, Resource Path: /v1/status.json
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Execution failed due to configuration error: statusCode should be an integer which defined in request template
21:41:39(c5be3842-6af4-4725-a34f-d6eea8042d17) Method completed with status: 500
Apparently only traffic across the V1 stage is getting through to CloudWatch logs. I have a misconfiguration somewhere and I can't seem to find it.
Can you try and change you request template in the integration request setup to this:
{
"statusCode": 200
}
API Gateway looks for the status code to return in the response in your integration request template. The response is generated by the mapping template in the integration response. I can see from your terraform setup that you are loading the output json file in the integration request template. This is content API Gateway does not expect.
With Mock Integration Amazon API Gateway there are 2 common reasons for 500 Internal Server error.
Check the mapping template in Integration Request and ensure that you are passing statusCode as an integer to the MOCK Integration endpoint.
{
"statusCode": <Integer_Status_code>
}
Note: Make sure that status code is passed as integer not string.
Correct : 200 Incorrect : "200"
Mock Integrations do not support the binary content. If the API is enabled with bixnary support and has application/json or */* set as binaryMediaTypes, MOCK Integration endpoints would throw a 500 Internal server error when trying to transform the content.
A workaround is to update the contentHandling property of the MOCK Integration to CONVERT_TO_TEXT
Read more here :- https://cloudnamaste.com/500-internal-server-error-mock-integration/
For my case, when I deploy the lambda with serverless framework, the OPTIONS returns 200 when called. However, when I configure manually on AWS API Gateway, it returns 500 Internal Server Error.
When I check the execution log of API gateway, it said
(ee0a42d9-2cfc-4788-8679-00fbd7938cf1) Method request body before transformations: [Binary Data]
(ee0a42d9-2cfc-4788-8679-00fbd7938cf1) Execution failed due to configuration error: Unable to transform request
(ee0a42d9-2cfc-4788-8679-00fbd7938cf1) Gateway response body:
{
"message": "Internal server error"
}
After you create the Resources and OPTIONS methods, select the OPTIONS method then
At Method Execution --> Integration Request --> expand the Mapping Templates, choose "When no template matches the request Content-Type header". Add or select "application/json" in the Content-Type. Click the "application/json", and in the Generate template, paste
{statusCode: 200} without any double quote. Note, if the {"statusCode": 200} exists but with double quote, remove it to be the same as above. Then Save it
At Method Execution --> Integration Response --> expand the 200 response status --> Mapping Template --> Add or select "application/json" in the Content-Type. Make sure that the Generate template box is empty. Then Save it
At Method Execution --> Method Response --> expand the 200 response. In Response Headers for 200, add three headers: Access-Control-Allow-Headers, Access-Control-Allow-Methods, and Access-Control-Allow-Origin. Leave the Response Body for 200 to be empty
Action --> Enable CORS for the Resource
Action --> Deploy API
You have at least two distinct problems with your configuration.
First, one of your three base path mappings doesn't match the way you're trying to invoke your API. Note that the base paths don't have to be the same as your stage names, but they can be if you desire. Since your base path mappings include base paths and stage names, API Gateway is expecting the invoke path to include a base path mapping and not a stage, so it is interpreting the [glhf stable v1] portion of your path as a base path and looking for the corresponding base path mapping entry to determine the API and stage to use. This works fine for the v1 and glhf base paths which return 500 (indicating a different problem). The stable base path (in https://api.naftuli.wtf/stable/status.json) returns a 403 Forbidden because there is no base path of "stable" defined for the domain name api.naftuli.wtf. The stable stage is mapped to the "latest" base path, so calling https://api.naftuli.wtf/latest/status.json should be the way to call the stable stage. This doesn't currently work, and I don't know why. If you tell me what region your running this in, I can look-up the config and do more digging.
The second problem is indicated by the following entry from your CloudWatch logs:
Execution failed due to configuration error: statusCode should be an integer which defined in request template
Can you check that your integration request template (in the file your reference in "${file("${path.module}/files/status.json")}") contains "statusCode: 200" as a top level attribute.
I also found it surprising that you're using the same file for a request template and a response template.
Having had the identical errors I found what helped me solve this issue was to delete my OPTIONS request definition in the AWS Console. I then followed the console's "Enable CORS" form which created a new OPTIONS method.
I subsequently ran terraform plan and looked at the diff between my OPTIONS defintion and theirs. Given that the AWS Console created OPTIONS method worked I applied the changes.
Using terraform 0.12 or greater makes this possible as the terraform plan output detail is more fine grained.
I was doing this in CloudFormation.
It took me a while to get it and the accepted answer here was extremely helpful, but a little vague, so adding some more info.
Stefano Buliani's answer, in CloudFormation YAML, looks like:
RequestTemplates:
application/json: |
{ statusCode: 200 }
What was especially weird here was apparently, the fix was simply to create a deployment using the AWS CLI for each of the stages. Apparently, Terraform was not updating or re-kicking deployments on changes, and so my changes never got out.
I had a similar problem and eventually figured out that my client was using a different content type than I expected. I had foolishly assumed it would use application/json, but it was some custom json thing. In my setup, API Gateway is logging to cloudwatch, which is where I found the content type it received from the client. Once I updated the content type in the request template of the mock integration, things worked as expected.

403 forbidden message while executing a rest message through Jmeter

I am trying to test a Rest service through HTTP sampler using Jmeter. The first sampler generates a token and I am using this token for authorization in the header manager of another HTTP sampler "GetUserandPolicies"(Rest WS request) using RegEx and ForEach controller. I can see in the view results tree that RegEx is working fine passing the actual token to the next request. But the Rest Request is failing giving a response message as Forbidden and Response Code 403 which means that the server is able to recognise the request but denying the access.There is no port number for this HTTP sampler which I suspect would be the culprit. But, the same test is passing with another tool (iTKO LISA) without any port value. Both the samplers "TokenGeneration" and "GetUserandPolicies" have no port values. I need some help on this. I am using the POST method in the HTTP sampler
Please find the sampler result:
Thread Name: Thread Group 1-1
Sample Start: 2014-01-13 12:12:29 IST
Load time: 1390
Latency: 1390
Size in bytes: 382
Headers size in bytes: 354
Body size in bytes: 28
Sample Count: 1
Error Count: 1
Response code: 403
Response message: Forbidden
Response headers:
HTTP/1.1 403 Forbidden
Server: Apache-Coyote/1.1
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, OPTIONS
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Authorization, X-Requested-With, Content-Type
Content-Type: text/plain;charset=UTF-8
Content-Length: 28
Date: Mon, 13 Jan 2014 06:42:30 GMT
HTTPSampleResult fields:
ContentType: text/plain;charset=UTF-8
DataEncoding: UTF-8
Looking into Access-Control-Allow-Headers: Authorization, X-Requested-With, Content-Type stanza I guess that you're missing proper Authorization header.
In regards to empty port everything is fine, it defaults to port 80 in case of HTTP and 443 in case of HTTPS
There are 2 options on how you can deal with Basic HTTP Authentication:
Pass username and password in URL like protocol://username:password#host:port/path
i.e. http://user:pass#your.server.com/somelocation
Use JMeter HTTP Authorization Manager to construct required "Authorization" header for you.
In case if your authentication system uses other approaches, i.e. Cookie-based, NTLM or Kerberos it's still possible but a little bit more tricky. If so - update this post with all details you can get (i.e. request details) and don't hesitate to leave a comment requesting for more input