How can I call a graphql lambda from another lambda in nodejs? - node.js

I created graphql lambda by following this instruction: https://www.apollographql.com/docs/apollo-server/deployment/lambda/
It works fine with API gateway. However, I need to call this lambda function from another lambda. I think I need to put ApolloClient in the other lambda function in order to send a graphql request. However, it doesn't work because I can't choose a right link for calling lambda.
So I am looking for how to build the graphql request programatically. I can send the request as an event to trigger the graphql lambda.
Is there a way to do that?
For example, if I have a mutation request like:
mutation sendMessage {
sendMessage(text: "hello"){
text
}
I need to find a way to convert the request to below payload:
{"id":"1","type":"start","payload":{"variables":{},"extensions":{},"operationName":"sendMessage","query":"mutation sendMessage {\\n sendMessage(text: \\"hello\\") {\\n text\\n __typename\\n }\\n}\\n"}}
then I send this payload to the graphql lambda function

You can use graphQL client to perform graphQL request via API Gateway endpoint using HTTP.
Given that you have an API Gateway endpoint pointing to the graphQL server, you can perform a graphQL request to that endpoint from another lambda.
GraphQL queries to the server is simply a regular POST request formatted in a certain way. So if you wanted, you could use any server-side HTTP client to perform that request. However, using a library like graphql-request makes it much simpler.
You can use graphql-request package to perform server-side graphQL requests.
import { request } from 'graphql-request'
const endpoint="https://your-api-gateway-endpoint";
const headers = {
"x-api-key": 'api-gateway-key' // if your endpoint requires API key
};
const client = new GraphQLClient(endpoint, { headers });
const query = `{
mutation sendMessage {
sendMessage(text: "hello"){
text
}
}`;
const data = await client.request(query);
console.log(JSON.stringify(data, undefined, 2));

Related

Verifying Stripe webhook in SvelteKit endpoint: how to get the raw body of a RequestEvent?

Similar to this question, using a more recent version of SvelteKit.
Context: SvelteKit PR #3384 started passing standard Request objects to endpoints and removed rawBody.
The question linked above has a good answer for how to use rawBody to call Stripe's constructEvent to verify the signature of an incoming webhook request, but now that the unmodified body is no longer exposed (as far as I can tell), I'm left wondering how to update my webhook handler.
I've tried calling constructEvent with the results of request.text(), request.json(), request.arrayBuffer() (converted to a string), request.blob().text(), and the plain request.body converted to a string, yet none of them worked. It always throws the same error:
No signatures found matching the expected signature for payload.
Are you passing the raw request body you received from Stripe?
https://github.com/stripe/stripe-node#webhook-signing
So I've looked into the node-fetch source code because that's what svelte-kit uses to shim the dev server with and all environments that don't support Fetch and there is a method that the standard Request class doesn't have and that's Request.buffer(). With this method I was able to solve that issue. This will only be available in node or serverless environments that don't support fetch natively (nearly every environment except cloudflare).
export async function post({ request }: RequestEvent) {
try {
const body = await request.buffer();
const sig = request.headers.get('stripe-signature') as string;
const e = stripe.webhooks.constructEvent(body, sig, secret);
console.log(e.type);
} catch (_e) {
console.error(_e);
}
}
Result:
charge.succeeded
payment_intent.succeeded
payment_intent.created

nodejs supertest express test prior to invoking external API

Not sure if this is possible but Id like to run a test without invoking an external API POST request.
Whats currently happening is ive got a test confirming the post data sent to my server API is processed correctly, as it needs to add some basic additional information to the BODY before sending it to the external API, and then the server makes another POST request to an external API with this modified BODY.
This is all done in the below function.
createUser(req,res){
...
// schema validation,
// adding fields
// external server post request
}
Is it possible to have my test ignore the external API call?
the test looks like
it('POST users --> 200 Successful Post', () => {
return request(app).post('/api/users').send(........ my json .......)
.expect('Content-Type', /json/)
.expect(200)
.then((response) => {
expect(response.body).toEqual(
......
)
})
});
You can use nock to intercept and mock requests for testings.
On your test, you can setup your mocking object like this:
const nock = require("nock");
const scope = nock("https://api.github.com")
.get("/repos/atom/atom/license")
.reply(200);
It will intercept an HTTPS GET requests to /repos/atom/atom/license.
How to Test Node.js Apps That Interact With External APIs

NodeJs Express how to handle items(params) that sent from frontend?

Im new in backend development (using NodeJs Express).
Its very basic question (I didn't find any good tutorial about it)
Question is:
I have this line of code:
app.get('/test', function (req ,res){
res.send('test');
});
What I wanna do is: BackEnd only sends res to FrontEnd, if FrontEnd send some JSON first.
Like Backend will show Something to FrontEnd, only if FrontEnd send JSON first;
How to handle it? What code to write?
Or what to type in google search to find this kind of tutorial
You are building a REST API with node. In REST we don't keep states. When we receive a request we process and respond. In the Front end, you can do wait until the response is received. use promises, async-await or callbacks to wait until the response in the Front end. Use these methods to connect with back end from front-end axios, fetch. To process the incoming JSON body use body-parser. Based on the request body you can process and send the response. PS: Every request should be given a response. That's how REST behaves.
In Query
yourbackend.com/test?message=welcomeToStackOverflow
This is how you can access with in query:
const {message} = req.query;
console.log(message);
// welcomeToStackOverflow
In Params
yourbackend.com/test/:message
This is how you can access with in params :
const {message} = req.params;
console.log(message);
// welcomeToStackOverflow
Here you have working example : https://codesandbox.io/s/trusting-rosalind-37brf?file=/routes/test.js

ReactJS - NodeJS - Issue Connecting to Graphql On AWS Lambda

I have a nodejs lambda function deployed on aws which exposes a lambda endpoint via API Gateway.
The endpoint is here and allows you to access the graphiql endpoint.
I have been trying to call this from my react code but I am getting the following error response
{"message":"Missing Authentication Token"}
And the following console warning
Failed to load https://z8zch5bp3m.execute-api.us-east-1.amazonaws.com/test: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:3000' is therefore not allowed access. The response had HTTP status code 403. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
I have enabled cors in the API gateway but still getting this error.
My simple react code is as follows
import React, { Component } from 'react';
import { gql } from 'apollo-boost';
import { Query } from 'react-apollo';
const ADD_NUMBERS = gql`
query {
addNumbers(number1:1, number2:55) {
add
}
}
`
const App = () => (
<Query query={ADD_NUMBERS}>
{({ loading, error, data }) => {
if (loading) return <div>Loading...</div>;
if (error) return <div>Error :(</div>;
return (
<div>Data: {data}</div>
)
}}
</Query>
)
export default App;
The nodejs code for my lambda function is located here
Please let me know if I need to do anything to get this lambda call working.
Looking into your code did not tell me much. I would advise you to take a look into those topics:
Missing Authentication Token is also returned when you make an HTTP call with the wrong method (say you want to POST, but you PUT);
Look into Lambda Proxy Integration. When using Lambda Proxy Integration you can specify headers in your response. There you can make sure to allow Cross-Origin-Resource-Sharing.
Hope this helps.
Got this working by recreating my api gateway endpoints with cors enabled from the start and it worked as expected

$resource.query() parameters fail to arrive at server

Trying to implement a RESTful API using Node.js and Angular.
On the client side, I define a resource called songResource with the $resource function in Angular.
I then call the API with this method:
$scope.displayArray = songResource.query(
parameters, // an object containing various settings
function(value, responseHeaders) { // success callback
console.log('Success!',parameters);
...
},
function(httpResponse) { // error callback
console.log('Error!');
...
}
);
On the server side, the route resolves, but the parameters do not come over. (In other words, req.params is an
empty object.) The rest of the service retrieves and sends zero records. My client receives the zero records and
hits the success callback, where I can tell that the API call succeeded.
Why aren't the parameters coming over to the API, and how do I fix this?
Found out what I was doing wrong. My parameters come in through the query string. Therefore, I need to use req.query rather than req.params to get the parameters.

Resources