How to properly send a GraphQL update request using Axios? - node.js

I created an application using AWS Amplify, and I want to create an endpoint in an API function that will mutate a field in GraphQL. Since its a nodejs API function, I cannot use the recommended libraries from the AWS documentation which use ES6, since the functions can only use ES5. Therefore I need to use Axios.
I created a graphql query:
const query = /* GraphQL */ `mutation updatePublication($id: ID!, $keywords: String) {
updatePublication(id: $id, keywords: $keywords){
id
keywords
}
}`
Next, I created the Axios request based on this StackOverflow question.
const data = await axios.post(
process.env.API_APPNAME_GRAPHQLAPIENDPOINTOUTPUT,
{
query: query,
variables: {
id: variableWithID,
keywords: "updated keywords!"
}
},
{
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.API_APPNAME_GRAPHQLAPIKEYOUTPUT
}
}
)
When I run the query, I get a status 200 from the server with the following errors:
data: null,
errors: [
{
path: null,
locations: [Array],
message: "Validation error of type MissingFieldArgument: Missing field argument input # 'updatePublication'"
},
{
path: null,
locations: [Array],
message: "Validation error of type UnknownArgument: Unknown field argument id # 'updatePublication'"
},
{
path: null,
locations: [Array],
message: "Validation error of type UnknownArgument: Unknown field argument keywords # 'updatePublication'"
}
]
}
Can anyone advise on what this means?

Related

Google Secret Manager INVALID_ARGUMENT Error

I'm using Google Secret Manager to access/store some secret parameters in an API. I have no problem saving secrets and accessing versions.
But when I send a request to list these secrets, I keep getting this error.
Error: 3 INVALID_ARGUMENT: Invalid resource field value in the request.
code: 3,
details: 'Invalid resource field value in the request.',
metadata: Metadata {
internalRepr: Map(3) {
'grpc-server-stats-bin' => [Array],
'google.rpc.errorinfo-bin' => [Array],
'grpc-status-details-bin' => [Array]
},
options: {}
},
statusDetails: [
ErrorInfo {
metadata: [Object],
reason: 'RESOURCE_PROJECT_INVALID',
domain: 'googleapis.com'
}
],
reason: 'RESOURCE_PROJECT_INVALID',
domain: 'googleapis.com',
errorInfoMetadata: {
method: 'google.cloud.secretmanager.v1.SecretManagerService.ListSecrets',
service: 'secretmanager.googleapis.com'
}
}
I've also checked the docs and tried different queries like in here but no dice...
This is the part of the code I'm running:
import { SecretManagerServiceClient } from "#google-cloud/secret-manager";
const secretClient = new SecretManagerServiceClient({
keyFile: "foo/bar/google_credentials.json"
});
const [secrets] = await secretClient.listSecrets({
filter: `labels.environment=development`
});
Version of the "#google-cloud/secret-manager": "^4.1.2",
Okay, I found the issue. I had to add the parent param to the request body.
So it should look like this:
const [secrets] = await SecretManager.secretClient.listSecrets({
parent: "projects/**", <=========== This is the key
filter: `
labels.environment:development AND
labels.scope:some-scope AND
labels.customer_id:*`
});

Elastic Search Node.js client - Routing Error

We have elastic hosted on GCP. I'm getting an error when I try to simply post a document. I'm using their node.js package, and I'm stuck with the following error:
PS C:\Projects\foo> node --experimental-modules --unhandled-rejections=strict app.js
(node:19356) ExperimentalWarning: The ESM module loader is experimental.
(node:19356) ExperimentalWarning: Conditional exports is an experimental feature. This feature could change at any time
Posting to Elastic => 5f91dfb0c64004000aab6c9b
C:\Projects\foo\node_modules\#elastic\elasticsearch\lib\Transport.js:257
const error = new ResponseError(result)
^
ResponseError: Response Error
at IncomingMessage.<anonymous> (C:\Projects\foo\node_modules\#elastic\elasticsearch\lib\Transport.js:257:25)
at IncomingMessage.emit (events.js:323:22)
at endReadableNT (_stream_readable.js:1204:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21) {
name: 'ResponseError',
meta: {
body: { error: 'Routing Error. The path you have requested is invalid.' },
statusCode: 404,
headers: {
'content-type': 'application/json;charset=utf-8',
server: 'Jetty(9.4.30.v20200611)',
'x-cloud-request-id': 'srCq9DMFQVWuGsdXxgWhjA',
'x-content-type-options': 'nosniff',
'x-found-handling-cluster': '[Removed]',
'x-found-handling-instance': 'instance-0000000001',
'x-frame-options': 'SAMEORIGIN',
'x-request-id': 'a2696b33-e4dc-4dfc-a8b1-f7ec17906ff7',
'x-runtime': '0.010689',
'x-xss-protection': '1; mode=block',
date: 'Mon, 09 Nov 2020 21:28:28 GMT',
'content-length': '66'
},
meta: {
context: null,
request: [Object],
name: 'elasticsearch-js',
connection: [Object],
attempts: 0,
aborted: false
}
}
}
I have the client set up as follows
const client = new Client({
node: 'https://[REMOVED].ent-search.us-central1.gcp.cloud.es.io',
auth: {
apiKey: 'Bearer private-[REMOVED]'
}
});
Then I attempt to send a json file as an array to Elastic.
client.helpers.bulk({
datasource: posts,
onDocument(doc) {
return {
create: {_index: 'my-index', _id: elasticPost.id}
};
}
});
Update:
The JSON names MUST be lowercase. For example:
Doesn't Work:
{
"Id": 123456
}
Works:
{
"id": 123456
}
Another thing may have to do with needing the cloud ID from Elastic, I'm not sure if this is required as well, but the lowercase allowed me to upload our document directly into Elastic.
I think you have one too many create in the command you return from onDocument. The command you can return is described here:
So, by removing one create layer, it should work:
client.helpers.bulk({
datasource: posts,
onDocument(doc) {
return {
create: {_index: 'my-index', _id: elasticPost.id}
};
}
});
UPDATE:
Looking at the host name *.ent-search.*, it looks like you're using the elasticsearch client to try to connect to the Enterprise search backend, that cannot work as the latter doesn't support the _bulk API.
If you connect to an AppSearch backend, you can't use the the _bulk endpoint (i.e. client.helpers.bulk()). Instead, you need to add documents through the AppSearch Documents API. Feel free to share more info on what you're trying to achieve.
The JSON names MUST be lowercase. For example:
Doesn't Work:
{
"Id": 123456,
"userName": "Dave2118"
}
Works:
{
"id": 123456,
"username": "Dave2118"
}

GraphQL Error Handling with ApolloClient and Apollo-Server-Express

The onError function from apollo-link-error has a populated graphQLErrors Object, but when ApolloClient throws an error object, the graphQLErrors property contains an empty array. Further inspection reveals the graphql error message in error.networkError.result.errors.
How can one properly configure Apollo Client to return a populated graphQLErrors object?
Apollo Client Setup:
const {ApolloClient} = require('apollo-client')
const { ApolloLink } = require('apollo-link')
const {HttpLink} = require('apollo-link-http')
const {onError} = require('apollo-link-error')
const {InMemoryCache} = require('apollo-cache-inmemory')
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
)
}
if (networkError) console.log(`[Network error]: ${networkError}`)
})
const middleware = (req, ignored_res, next) => {
const client = new ApolloClient({
link: ApolloLink.from([errorLink, new HttpLink({ uri:'http://somegraphqlserver.com', fetch: require('node-fetch') })]),
cache: new InMemoryCache(),
})
req.GQLClient = client
return next()
}
module.exports = middleware
Calling apollo-server-express:
req.GQLClient
.query({
query: SOME_MALFORMED_QUERY,
})
.then((data) => {...})
.catch((error) => {
console.log('rawError', error)
console.log('error.networkError.result.errors', error.networkError.result.errors)
return next(error)
})
Console Results:
[GraphQL error]: Message: Cannot query field "blah" on type "CustomerList"., Location: [object Object], Path: undefined
[Network error]: Error: Response not successful: Received status code 400
rawError { Error: Network error: Response not successful: Received status code 400
at new ApolloError (/.../node_modules/apollo-client/bundle.umd.js:121:28)
at /.../node_modules/apollo-client/bundle.umd.js:1187:41
at /.../node_modules/apollo-client/bundle.umd.js:1620:17
at Array.forEach (<anonymous>)
at /.../node_modules/apollo-client/bundle.umd.js:1619:18
at Map.forEach (<anonymous>)
at QueryManager.broadcastQueries (/.../node_modules/apollo-client/bundle.umd.js:1614:22)
at /.../node_modules/apollo-client/bundle.umd.js:1114:31
at process._tickCallback (internal/process/next_tick.js:178:7)
graphQLErrors: [],
networkError:
{ Error: Response not successful: Received status code 400
at throwServerError (/.../node_modules/apollo-link-http-common/lib/bundle.umd.js:33:21)
at /.../node_modules/apollo-link-http-common/lib/bundle.umd.js:58:17
at process._tickCallback (internal/process/next_tick.js:178:7)
response:
Response {
size: 0,
timeout: 0,
[Symbol(Body internals)]: [Object],
[Symbol(Response internals)]: [Object] },
statusCode: 400,
result: { errors: [Array] } },
message: 'Network error: Response not successful: Received status code 400',
extraInfo: undefined }
error.networkError.result.errors [ { message: 'Cannot query field "blah" on type "CustomerList".',
locations: [ [Object] ] } ]
library versions:
Server:
"apollo-server-express": "^1.3.2"
Client:
"apollo-cache-inmemory": "^1.1.12"
"apollo-client": "^2.2.8"
"apollo-link-error": "^1.0.9"
"apollo-link-http": "^1.5.4"
This is by design. From the docs:
graphQLErrors: An array of errors from the GraphQL endpoint
networkError: Any error during the link execution or server response,
that wasn't delivered as part of the errors field in the GraphQL result
In other words, if your query is malformed, you request a field that isn't valid (like in your example), or hit any other issue that results in status other than 200, the error will appear as part of the networkError property. On the other hand, if the request returns a 200, but the errors array inside the response is populated, those same errors will be returned as part of graphQLErrors.
If you want to see an example of graphQLErrors being populated, format your query correctly but have one of your resolvers throw an error as soon as it's called. As long as the query doesn't hit any other issues, you should see the same error pop up inside graphQLErrors.

Unhandled rejection Error: Content-Type header [] is not supported

I had a elastic query in my Node.js app as follows. I am using elastic search version 6.2.2. But when I execute the API from postman it shows the following error:
Unhandled rejection Error: Content-Type header [] is not supported
exports.radix = function (req, res) {
var elasticsearch = require('elasticsearch'),
client = new elasticsearch.Client({
host: 'localhost:9200'
});
client.search({
index: 'xpertradix',
type: 'search',
size: 20,
body: {
query: {
match: {
name: req.param('term')
}
}
}
}).then(function (resp) {
var data = helper.prepareRadix(resp.hits.hits);
res.json(data);
});
};
I have been struggling for 2 days to fix this. Can someone please help me in resolving the issue?
The problem is from Elastic search 6 onwards,we must send headers in the query.So I added headers as follows,
var client = elasticsearch.Client({
hosts: [{
host: 'loalhost,
port: 9200,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}]
})
From the following docs,
Link1
LINK2

Azure Insert failed in database but query works

I am trying to do an Insert/replace :
insertOrReplaceEntity('myusertables', task, function(error)
it always goes to error code indicating that insertion did not happen.
How to debug this in Azure?
I am using the Azure emulator and have in the code:
var account = azure.ServiceClient.DEVSTORE_STORAGE_ACCOUNT;
var accountKey = azure.ServiceClient.DEVSTORE_STORAGE_ACCESS_KEY;
I get PUT failed with 403.
{ error:
{ [Error: Server failed to authenticate the request. Make sure the value of Authorization header is formed correctl
including the signature.]
code: 'AuthenticationFailed',
message: 'Server failed to authenticate the request. Make sure the value of Authorization header is formed correc
y including the signature.' },
response:
{ isSuccessful: false,
statusCode: 403,
body:
{ '#': [Object],
code: 'AuthenticationFailed',
message: [Object] },
headers:
{ 'content-length': '356',
'content-type': 'application/xml',
server: 'Microsoft-HTTPAPI/2.0',
date: 'Mon, 12 Nov 2012 20:57:10 GMT' },
md5: undefined } }
As Described here the storage emulator does not support Insert-Or-Replace Entity or Insert-Or-Merge Entity, known as upsert features. That's why when you use insertOrReplaceEntity in your code it return an error. If you have to verify the code, you may need to check it with the real Azure Table Storage.

Resources