API Connect 5 - Error attempting to read the urlopen response data - api

I'm trying to create a REST API from a SOAP Service using IBM API Connect 5. I have followed all the steps described in this guide (https://www.ibm.com/support/knowledgecenter/en/SSFS6T/com.ibm.apic.apionprem.doc/tutorial_apionprem_expose_SOAP.html).
So, after dragging the web service block from palette, ensuring the correctness of endpoint and publishing the API, I have tried to call the API from the browser. Unfortunately, the API return the following message:
<errorResponse>
<httpCode>500</httpCode>
<httpMessage>Internal Server Error</httpMessage>
<moreInformation>Error attempting to read the urlopen response
data</moreInformation>
</errorResponse>
To testing purpose, I have logged the request and I have tried the request on SOAPUI. The service return the response correctly.
What is the problem?

In my case, the problem was in the backend charset (Content-Type: text/xml;charset=iso-8859-1).
For example, backend returns text/xml in German (or French). Api Connect cannot process character ü. It needs Content-Type: text/xml;charset=UTF-8.

I had a similar issue, in my case was the accept. if you have an Invoke and the content-type or the accept, is not matching the one of the request, or the response that you got, APIC is getting mad.

Please, check if the formats to send (contentType) and receive (accept) are the same of that your API expected. In my case the error occurs because the API returns a String and my default code is configured to receive a JSON body.
//define a JSON-PLAIN TEXT protocol
private HttpEntity<String> httpEntityWithBody(Object objToParse){
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + "xxx token xxx");
headers.set("Accept", MediaType.TEXT_PLAIN_VALUE);
headers.setContentType(MediaType.APPLICATION_JSON);
Gson gson = new GsonBuilder().create();
String json = gson.toJson(objToParse);
HttpEntity<String> httpEntity = new HttpEntity<String>(json, headers);
return httpEntity;
}
//calling the API to APIC...
ParameterizedTypeReference<String> responseType = new
ParameterizedTypeReference<String>(){};
ResponseEntity<String> result =
rest.exchange(builder.buildAndExpand(urlParams).toUri(), HttpMethod.PUT, httpEntityWithBody(myDTO), responseType);
String statusCode = result.getStatusCodeValue();
String message = result.getBody();

Related

Webhook call failed. Error: Failed to parse webhook JSON response: Expect message object but got: [Chinese letters]

I'm building my own WebhookClient for dialog flow. My code is the following (using Azure Functions, similar to Firebase Functions):
module.exports = async function(context, req) {
const agent = new WebhookClient({ request: context.req, response: context.res });
function welcome(agent) {
agent.add(`Welcome to my agent!!`);
}
let intentMap = new Map();
intentMap.set("Look up person", welcome);
agent.handleRequest(intentMap);
}
I tested the query and the response payload looks like this:
{
"fulfillmentText": "Welcome to my agent!!",
"outputContexts": []
}
And the headers in the response look like this:
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Date: Tue, 11 Dec 2018 18:16:06 GMT
But when I test my bot in dialog flow, it returns the following:
Webhook call failed. Error: Failed to parse webhook JSON response:
Expect message object but got:
"笀ഀ਀  ∀昀甀氀昀椀氀氀洀攀渀琀吀攀砀琀∀㨀 ∀圀攀氀挀漀洀攀 琀漀 洀礀 愀最攀渀琀℀℀∀Ⰰഀ਀  ∀漀甀琀瀀甀琀䌀漀渀琀攀砀琀猀∀㨀 嬀崀ഀ਀紀".
There's Chinese symbols!? Here's a video of me testing it out in DialogFlow: https://imgur.com/yzcj0Kw
I know this should be a comment (as it isn't really an answer), but it's fairly verbose and I didn't want it to get lost in the noise.
I have the same problem using WebAPI on a local machine (using ngrok to tunnel back to Kestrel). A friend of mine has working code (he's hosting in AWS rather than Azure), so I started examining the differences between our responses. I've notice the following:
This occurs with Azure Functions and WebAPI (so it's not that)
The JSON payloads are identical (so it's not that)
Working payload isn't chunked
Working payload doesn't have a content type
As an experiment, I added this code to Startup.cs, in the Configure method:
app.Use(async (context, next) =>
{
var original = context.Response.Body;
var memory = new MemoryStream();
context.Response.Body = memory;
await next();
memory.Seek(0, SeekOrigin.Begin);
if (!context.Response.Headers.ContentLength.HasValue)
{
context.Response.Headers.ContentLength = memory.Length;
context.Response.ContentType = null;
}
await memory.CopyToAsync(original);
});
This code disables response chunking, which is now causing a new and slightly more interesting error for me in the google console:
*Webhook call failed. Error: Failed to parse webhook JSON response: com.google.gson.stream.MalformedJsonException: Unterminated object at line 1 column 94 path $.\u0000\\"\u0000f\u0000u\u0000l\u0000f\u0000i\u0000l\u0000l\u0000m\u0000e\u0000n\u0000t\u0000M\u0000e\u0000s\u0000s\u0000a\u0000g\u0000e\u0000s\u0000\\"\u0000.\
I thought this could be encoding at first, so I stashed my JSON as a string and used the various Encoding classes to convert between them, to no avail.
I fired up Postman and called my endpoint (using the same payload as Google) and I can see the whole response payload correctly - it's almost as if Google's end is terminating the stream part-way through reading...
Hopefully, this additional information will help us figure out what's going on!
Update
After some more digging and various server/lambda configs, I spotted this post here: https://github.com/googleapis/google-cloud-dotnet/issues/2258
It turns out that json.net IS the culprit! I guess it's something to do with the formatters on the way out of the pipeline. In order to prove this, I added this hard-coded response to my POST controller and it worked! :)
return new ContentResult()
{
Content = "{\"fulfillmentText\": null,\"fulfillmentMessages\": [],\"source\": null,\"payload\": {\"google\": {\"expectUserResponse\": false,\"userStorage\": null,\"richResponse\": {\"items\": [{\"simpleResponse\": {\"textToSpeech\": \"Why hello there\",\"ssml\": null,\"displayText\": \"Why hello there\"}}],\"suggestions\": null,\"linkOutSuggestion\": null}}}}",
ContentType = "application/json",
StatusCode = 200
};
Despite the HTTP header saying the charset is utf-8, that is definitely using the utf-16le character set, and then the receiving side is treating them as utf-16be. Given you're running on Azure, it sounds like there is some configuration you need to make in Azure Functions to represent the output as UTF-8 instead of using UTF-16 strings.

Programmatically provide NiFi InvokeHTTP different certificates

I have a requirement in Nifi where I have cycle through different HTTPS REST Endpoints and provide different certificates for some endpoints and different username / password for some other endpoints.
I used InvokeHTTP processor to send the requests, although URL takes an expression language, I cannot setup SSLContextService with an expression.
Alternatively, I thought on using ExecuteScript to call those Endpoints, however as listed here in StackOverflow post; I still don't know how to programmatically call an external service through a script.
Any help appreciated.
just for fun created the groovy script that calls http.
for sure you can avoid using it. and I believe InvokeHTTP processor covers almost all needs.
However.. going to call test rest service: /post at https://httpbin.org
the flow: GenerateFlowFile (generates body) -> EcecuteGroovyScript (call service)
The body generated by GenerateFlowFile : {"id":123, "txt":"aaabbbccc"}
In ExecuteGroovyScript 1.5.0 declare the CTL.ssl1 property and link it to StandardSSLContextService
and now the script:
#Grab(group='acme.groovy', module='acmehttp', version='20180301', transitive=false)
import groovyx.acme.net.AcmeHTTP
import org.apache.nifi.ssl.SSLContextService.ClientAuth
def ff=session.get()
if(!ff)return
def http
ff.write{ffIn, ffOut->
http = AcmeHTTP.post(
url: "https://httpbin.org/post", //base url
query: [aaa:"hello", bbb:"world!"], //query parameters
// send flowfile content (stream) as a body
body: ffIn,
headers:[
//assign content-type from flowfile `mime.type` attribute
"content-type":ff.'mime.type'
],
// you can declare `CTX.ssl1`, `CTX,.ssl2`,... processor properties and map them to SSLContextService
// then depending on some condition create different SSLContext
// in this case let's take `CTL.ssl1` service to create context
ssl: CTL["ssl"+1].createSSLContext(ClientAuth.WANT),
// the next commented line creates trust all ssl context:
//ssl: AcmeHTTP.getNaiveSSLContext(),
// the receiver that transfers url response stream to flowfile stream
receiver:{respStream, httpCtx-> ffOut << respStream }
)
}
//set response hesders as flow file attributes with 'http.header.' prefix
http.response.headers.each{ k,v-> ff['http.header.'+k]=v }
//status code and message
ff.'http.status.code' = http.response.code
ff.'http.status.message' = http.response.message
if( http.response.code < 400){
//transfer to success if response was ok
REL_SUCCESS << ff
}else{
//transfer to failure when response code is 400+
REL_FAILURE << ff
}

how to consume http post in elm with header and body

I am new in elm and try to consume web api using http post request with header and body using 0.17.1 version but did not get any documentation.
So any one help me to implement this functionality
The send method of the Http package gives you the possibility to create and send a custom request. For example, a post request could be something like
postRequest : Request
postRequest =
{ verb = "POST"
, headers =
[ ("Origin", "http://elm-lang.org")
, ("Access-Control-Request-Method", "POST")
, ("Access-Control-Request-Headers", "X-Custom-Header")
]
, url = "http://example.com/hats"
, body = empty
}
You can then create the Task that represent the request using the send function like
send defaultSettings postRequest

BadRequest when try Create folder via REST

I've downloaded a exampled that show the files in the "Shared with everyone" folder in my OneDrive for Bussiness. It's work fine!
But, when I try to create a Folder or File (without content) like this documentation the response became with a BadRequest .
The request goes like:
string requestUrl = String.Format(CultureInfo.InvariantCulture, "{0}/files", serviceInfo.ApiEndpoint);
// Prepare the HTTP request:
using (HttpClient client = new HttpClient())
{
Func<HttpRequestMessage> requestCreator = () =>
{
HttpRequestMessage request = new HttpRequestMessage( HttpMethod.Post, requestUrl);
request.Headers.Add("Accept", "application/json;odata.metadata=full");
request.Content = new StringContent(#"{'__metadata':{'type':'MS.FileServices.Folder'},Name:'TestFolder'}");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
return request;
};
}
And the response is a BadRequest.
I think that my problem is in the "__metadata"'s json value. It´s is correct? Where can I find a working example implementing this operations?
Thanks in advance!
EDIT: Changing the API Endpoint from "/_api/web/getfolderbyserverrelativeurl('Documents')/files" to "_api/files" the error became to: "The property '__metadata' does not exist on type 'MS.FileServices.FileSystemItem'. Make sure to only use property names that are defined by the type."
I´m think I foward in this. But, I still continue with problems.
I am not sure if this can be of any help to you, as this pertains to oneDrive and not oneDrive for business.
Also the documentations are confusing :)
according to the documentation the request should be as follow:
POST https://apis.live.net/v5.0/me/skydrive
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"name": "My example folder"
}
if you can see that in the header there is authorization access token
I don't see that you sent to the server any access token. and that is why you had a bad request.
I am trying to below way to create a folder in SP and it's working for me. Hope it will work for you as well.
Create a folder using SharePoint Web API -
POST https://<Domain>.sharepoint.com/_api/web/folders
Accept: "application/json;odata=verbose"
Content-Type: "application/json"
{
"ServerRelativeUrl": "/Shared Documents/<Folder-Name>"
}

500 error on api request. works fine when called through browser

Hello I have an api which authenticates the user login . Now when I hit this rest service in my browser it displays the result but when I try to do this using my code it gives in 500 error. Please help me with this .
My Api: http://abhinavevent2014.sched.org/api/auth/login?api_key=1309658400d57c8cfc6081f8361de52c&username=abhinavm#test.com&password=test
string url = #"http://abhinavevent2014.sched.org/api/auth/login?api_key=1309658400d57c8cfc6081f8361de52c&username=abhinavm#test.com&password=test";
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
WebRequest requestfriend = WebRequest.Create(url);
WebResponse responsefriend = requestfriend.GetResponse(); ( This is where it blows)
Stream streamResponse = responsefriend.GetResponseStream();
StreamReader streamReaderResponse = new StreamReader(streamResponse, encode);
jsonResult = streamReaderResponse.ReadToEnd();
return jsonResult.ToString();
You need to use User-Agent in the headers, as the documentation says:
You must also send requests with a User-Agent in the headers, as Sched
filters out requests with no User-Agent.
Sched API Doc
Browser automatically does that, so it can retrieve the data.