Expected type object but found type string - node.js

I am having trouble with setting up my API. The error I am getting is as follows:
[
{
"message": "Wrong data in the response. ",
"error": [
{
"code": "INVALID_TYPE",
"params": [
"object",
"string"
],
"message": "Expected type object but found type string",
"path": "#/"
}
],
"content": "{\"success\":true,\"payload\":{\"userId\":47}}"
}
]
With response headers:
connection: keep-alive
content-length: 233
content-type: application/json; charset=utf-8
date: Fri, 17 Apr 2020 08:09:38 GMT
etag: W/"e9-2OFjPp0RZp8asoi4T2vo8yXiZxE"
x-powered-by: Express
Now I expected this to work, as this very same code worked when using Swagger 2.0 instead of the oas-tools 3.0.1. This is my swagger file:
openapi: 3.0.1
info:
title: Swagger test
version: 0.0.1
servers:
- url: http://localhost:8081/
paths:
/add-user:
post:
x-router-controller: 'addUser'
description: Adds a user to the database
operationId: add
requestBody:
$ref: '#/components/requestBodies/AddUser'
responses:
201:
description: Successfully added the user to the database
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
payload:
type: object
properties:
userId:
type: integer
And this is my node script in which I send the response back:
db
.query(insert_user_query, [username, password])
.then(function(result) {
var response = {
"success": true,
"payload": {
"userId": result.rows[0].user_id
}
}
res.status(201).json(response)
})
Now I am completely lost, as I am building the JSON in the response variable, and I am setting response code 201 and sending it as json (which adds the application/json content-type), and yet Swagger interprets is as a string instead of an object.
Anyone here who could please point me in the right direction?

You have to take the string and parse it back into an object.
res.json() takes your object and converts it to a string using the json format. application/json is a string format and that's how you send javascript formatted objects over the network. They get converted to a canonical string format, sent over the network and then to use them as objects, they have to be parsed and converted back into real live objects.
You don't show your receiving code, but something on the receiving side needs to call JSON.parse() on the string response. That will return to you an actual object that you can use as it converts the json string back into an object on the receiving side.

I had the same problem and was using Express 4.x.
I could be mistaken, but I think there might be an issue with "res.json" (i.e. res.status(xxx).json({ a:b });)
I worked around the issue by using send:
res.status(201).send(response); // in your case

Related

Attempt to create simple Contact gives error: PATCH requests require components to be updated

I am currently using SDK version 3.39.0 and version 0004 of the API_MKT_CONTACT service definition to create a new Contact in Marketing Cloud with the following code:
ContactOriginData contact =
ContactOriginData.builder()
.originOfContact(origin)
.originTimestamp(ZonedDateTime.now())
.externalContactID(pii.getId().toString())
.firstName(pii.getFirstName())
.lastName(pii.getLastName())
.language(pii.getLanguage())
.countryReg(pii.getRegion())
.build();
// use low level API as a work around for https://github.com/SAP/cloud-sdk/issues/156
ODataRequestUpdate contactRequest = service
.updateContactOriginData(contact)
.withHeader("Sap-Cuan-RequestTimestamp", getFormattedTime(System.currentTimeMillis()))
.withHeader("Sap-Cuan-SequenceId", "UpdatePatch")
.withHeader("Sap-Cuan-SourceSystemType", "EXT")
.withHeader("Sap-Cuan-SourceSystemId", "sdk-test")
.toRequest();
String servicePath = "/sap/opu/odata/SAP/API_MKT_CONTACT_SRV;v=0004";
ODataRequestBatch requestBatch = new ODataRequestBatch(servicePath, ODataProtocol.V2);
requestBatch.beginChangeset().addUpdate(contactRequest).endChangeset();
HttpClient httpClient = HttpClientAccessor.getHttpClient(destination);
ODataRequestResultMultipartGeneric batchResult = requestBatch.execute(httpClient);
Running this produces the following error:
{
"error": {
"code": "/IWFND/CM_MGW/096",
"message": {
"lang": "en",
"value": "PATCH requests require components to be updated"
},
"innererror": {
"application": {
"component_id": "CEC-MKT-DM-IC",
"service_namespace": "/SAP/",
"service_id": "API_MKT_CONTACT_SRV",
"service_version": "0004"
},
"transactionid": "3B63A2A6CC920630E0060492A51E7EE7",
"timestamp": "20210310210334.4378960",
"Error_Resolution": {
"SAP_Transaction": "For backend administrators: use ADT feed reader \"SAP Gateway Error Log\" or run transaction /IWFND/ERROR_LOG on SAP Gateway hub system and search for entries with the timestamp above for more details",
"SAP_Note": "See SAP Note 1797736 for error analysis (https://service.sap.com/sap/support/notes/1797736)",
"Batch_SAP_Note": "See SAP Note 1869434 for details about working with $batch (https://service.sap.com/sap/support/notes/1869434)"
},
"errordetails": []
}
}
}
However, if I execute a similar request in postman it works without issue:
Request Payload:
--batch
Content-Type: multipart/mixed; boundary=changeset
--changeset
Content-Type: application/http
Content-Transfer-Encoding: binary
PATCH ContactOriginData(ContactOrigin='<ContactOrigin>',ContactID='24D8F7F6-440D-44F8-A24B-552435477688') HTTP/1.1
Accept: application/json
Content-Type: application/json
Content-Length: 172
Sap-Cuan-RequestTimestamp: '2021-03-10T14:07:00.000'
Sap-Cuan-SequenceId: UpdatePatch
Sap-Cuan-SourceSystemType: EXT
Sap-Cuan-SourceSystemId: postman-test
{"OriginDataLastChgUTCDateTime":"/Date(1615410479885)/","EmailAddress":"samantha.cook#theoasis.com","FirstName":"Samantha","LastName":"Cook","Country":"US","Language":"EN"}
--changeset--
--batch--
Response Payload:
--1D7E85E6BC66B34E61ACF0EF3964CBD90
Content-Type: multipart/mixed; boundary=1D7E85E6BC66B34E61ACF0EF3964CBD91
Content-Length: 430
--1D7E85E6BC66B34E61ACF0EF3964CBD91
Content-Type: application/http
Content-Length: 262
content-transfer-encoding: binary
HTTP/1.1 204 No Content
Content-Length: 0
dataserviceversion: 2.0
sap-message: {"code":"HPA_STAGING_AREA/037","message":"Payload is processed via staging area. See Import Monitor for details.","target":"","severity":"info","transition":false,"details":[]}
--1D7E85E6BC66B34E61ACF0EF3964CBD91--
--1D7E85E6BC66B34E61ACF0EF3964CBD90--
I should note that I have also tried using .replacingEntity() which doesn't work either and produces a completely different error:
Inline component is not defined or not allowed (HTTP PUT)
Is there something with the SDK that I am missing or not using correctly?
Any help would be appreciated!
Cheers!
To update an entity you should get it from the service first. That is regardless whether you are using:
PATCH which will update only changed fields
or PUT which will send the full entity object
Currently you are creating a new entity object via the builder: ContactOriginData.builder(). Instead, please use the corresponding getContactOriginDataByKey() method of your service to first retrieve the entity to update from the service. Actually many services will force you to do this to ensure you are always editing the latest version of your data. This often happens via ETags which the SDK will also handle for you automatically.
You can find more information about the update strategies from the SDK on the documentaiton.
Edit:
As you pointed out in the comments the actual goal is to create an entity and the specific service in question only allows PUT and PATCH to create objects.
In that case using replacingEntity() (which translates to PUT) should already work with your code. You can make PATCH work as well by replacing the builder approach with a constructor call + setter approach.

Cannot get generated express code (from OpenAPI) to catch error in query parameters

I’m trying to get the generated code (express.js) from isa-group/oas-tools to check the input url, but I’m having no luck. (Or am I abusing the tool?!) It seems to ignore errors in the query parameters. For example, I don’t get an error sending this url:
http://localhost:8080/acQyreXchange/acQyr-sample/1.0.0/gamer/123?limit=-3&xyz=a
I would expect it to complain about ‘limit’ being out of range (-3 < 0), and ‘xyz’ being an unknown parameter. I get an error message about wrong data in the response (which I’m expecting), but nothing about the inputs. Here's the response:
[
• {
o message: "Wrong data in the response. ",
o error:
[
 {
 code: "INVALID_TYPE",
 params:
[
 "array",
 "object"
],
 message: "Expected type array but found type object",
 path: "#/"
}
],
o content:
{
 message: "This is the mockup controller for getGamer"
}
• }
]
The debug log shows:
2020-09-01T14:49:11.670Z info: Requested method-url pair: get - /acQyreXchange/acQyr-sample/1.0.0/gamer/123?limit=-3&xyz=a
2020-09-01T14:49:11.671Z debug: OASValidator -res.locals.requestedSpecPath: /gamer/{gamerId}
2020-09-01T14:49:11.673Z info: Valid parameter on request
2020-09-01T14:49:11.675Z debug: Processing at checkResponse:
...
The api doc shows:
'/gamer/{gamerId}':
get:
tags:
- admins
summary: 'given a gamerId, returns a gamer'
operationId: getGamer
description: Returns a gamer
parameters:
- in: path
name: gamerId
description: pass the gamerId for looking up the gamer
required: true
schema:
type: string
- in: query
name: skip
description: number of records to skip for pagination
schema:
type: integer
format: int32
minimum: 0
- in: query
name: limit
description: maximum number of records to return
schema:
type: integer
format: int32
minimum: 0
maximum: 50
responses:
'200':
description: search results matching criteria
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Gamer'
'400':
description: bad input parameter
I’ve tried option:
strict: true (also tried false)
validator: true (also tried false)
customErrorHandling: true (also tried false)
The owner of the code said he's put this fix in asap.

Swagger produces key behaving differently in Openapi 3

I'm currently converting my swagger file to openapi3 and I have an endpoint thats returning a json response and I am using produces to output it as text/plain. I know the produces key for responses has been replaced in openapi3 by content: text/plain: etc.. but this is no longer converting my response. So previously if I called response.text after calling the endpoint I would get "This is a test." but now I get '"This is a test."\n'
Swagger 2 file:
/api/logs:
get:
description: Retrieve logs .
operationId: controller.get_logs
responses:
"200":
description: Job logs found
schema:
type: string
produces:
- text/plain
Openapi 3 file:
/api/logs:
get:
description: Retrieve logs .
operationId: controller.get_logs
responses:
"200":
description: Job logs found
content:
text/plain:
schema:
type: string
Below is a snippet of the application code, we call an external API and just return the response from that call. I don't have a snippet of the Api code to share but I have added some logs to display the response content:
resp = job.get_output() # Api call
try:
json_resp = resp.json()
LOGGER.info(f"Response: {resp}")
LOGGER.info(f"JSON: {json_resp}")
LOGGER.info(f"Text: {repr(resp.text)}")
LOGGER.info(f"Headers: {dict(resp.headers)}")
except Exception as error:
return (
{
"message": f"Failed to get job output for job: {job_id}"
},
HTTPStatus.NOT_FOUND,
)
return json_resp, HTTPStatus.OK, dict(resp.headers)
Log output:
LOGGER - Response: <Response [200]>
LOGGER - JSON: This is a test.
LOGGER - Text: '"This is a test."\n'
LOGGER - Headers: {'Date': 'Tue, 28 Jul 2020 15:23:31 GMT', 'Content-Type': 'application/json', 'Content-Length': '18', 'Connection': 'keep-alive'}
What am I doing wrong or am I missing something?

Failed to parse Dialogflow response into AppResponse because of invalid platform response (with Youtube API)

I am trying to build a YouTube entertainment app using Google Assistant, following this tutorial: here. I have followed every step precisely, copying code verbatim, but when I run the test, I get this error:
MalformedResponse Failed to parse Dialogflow response into AppResponse because of invalid platform response: Could not find a RichResponse or SystemIntent in the platform response for agentId: ~~ and intentId: ~~. WebhookStatus: code: 2 message: "Webhook call failed. Error: UNKNOWN." ..
I'm not really well versed in DialogFlow, so I'm not sure what's happening. If anyone has any advice, I'd really appreciate it!
Edit: So, here's what happens that triggers the error. I follow the tutorial all the way to the end. I run the test and type in their test request 'rahman'. The response I get back from the test is the above error. I'm not sure what other details I can add, but if there's anything else I can provide, please let me know!
Edit 2: Following the next comment I received, I opened the cloud functions up in the GCP console and found that a new function was made called dialogflowFirebaseFulfillment. I checked the logs for the 'youtube' function I made, and found this notification:
{
insertId: "..."
labels: {
execution_id: ""
}
logName: "projects/<name of project>/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
receiveTimestamp: "<time>"
resource: {
labels: {…}
type: "cloud_function"
}
severity: "ERROR"
textPayload: "Warning, estimating Firebase Config based on GCLOUD_PROJECT. Intializing firebase-admin may fail"
timestamp: "<time>"
}
I then checked out the new function that was made without me knowing and saw it didn't deploy, having an error: "Function failed on loading user code. Error message: Node.js module defined by file index.js is expected to export function named dialogflowFirebaseFulfillment". I checked the logs and found this:
{
insertId: "<id>"
logName: "projects/<project name>/logs/cloudaudit.googleapis.com%2Factivity"
operation: {
id: "operations/<id>"
last: true
producer: "cloudfunctions.googleapis.com"
}
protoPayload: {
#type: "type.googleapis.com/google.cloud.audit.AuditLog"
authenticationInfo: {
principalEmail: "<email>"
}
methodName: "google.cloud.functions.v1.CloudFunctionsService.UpdateFunction"
requestMetadata: {
destinationAttributes: {
}
requestAttributes: {
}
}
resourceName: "projects/<project name>/locations/us-central1/functions/dialogflowFirebaseFulfillment"
serviceName: "cloudfunctions.googleapis.com"
status: {
code: 3
message: "INVALID_ARGUMENT"
}
}
receiveTimestamp: "<time>"
resource: {
labels: {…}
type: "cloud_function"
}
severity: "ERROR"
timestamp: "<time>"
I know this isn't a good sign, but I also don't know how to really interpret where I should go fix the error. Any ideas would be appreciated, thanks!

swagger: requestBody not allowed

I'm trying to define a post endpoint using swagger, but it isn't allowing the requestBody parameter:
/names/{roster}:
get:
#...
post:
x-swagger-router-controller: names
description: Adds or removes name(s)
operationId: manageNames
parameters:
- name: roster
in: path
description: the roster to use
type: string
required: true
requestBody:
content:
'application/json':
schema:
$ref: '#/definitions/ManageNamesRequest'
when I run npm start, I get this:
API Errors:
#/paths/~1names~1{roster}/post: Additional properties not allowed: requestBody
1 error and 0 warnings
What's wrong with my spec?
You are probably mixing OpenAPI/Swagger 2.0 and OpenAPI 3.0 syntax. Your spec seems to be 2.0, but the requestBody keyword is a 3.0 feature. In 2.0, the request body is defined as a body parameter:
paths:
/names/{roster}:
post:
produces:
- application/json
...
parameters:
- ...
- in: body
name: body
required: true
schema:
$ref: '#/definitions/ManageNamesRequest'
More info: Describing Request Body

Resources