Send 1 request, Receive 2 Responses GraphQL - javascript

I want to trigger a request from an Apollo Server during (and dependent on the data returned from) a request that originated from the client. I want to return the data that was originally requested by the client, and later return the data from the request originating from the server to the client.
SERVER:
async function getPlaylistItems(playlistId) {
const url = '... external api endpoint with query parameter playlistId=playlistId'
const response = await axios(url, { method: 'GET' });
// response.data = ['title1','title2',...]'
const secondUrl = '...another external endpoint with response.data as query parameters'
// create a new request (but don't wait for it to resolve) and return response.data to client
const secondRequest = axios(secondUrl, { method: 'GET' });
return response.data
}
CLIENT:
const playlist = getPlaylistItems('playlistId');
const secondRequestData = ...?
I want to receive the response from getPlaylistItems first, and send the response from secondRequest (on the server) back to the client once it resolves.
Here is a diagram of the desired data flow:

The features you are looking for is #defer directive. But right now it is under development and not possible to use it using apollo-server.
As far I know you there is no support available for returning partial response right now.
Or else you can use GraphQL Subscriptions if you really want to return the partial response.
More info about #defer

Related

How to catch an error when using S3.getsignedurlpromise() in node.js

I have a node.js server that downloads images from my s3 bucket and serves the images to my React client. I want to manage the case when the wrong file key is sent to the S3 client.
In order to do so, I am intentionally sending a wrong key from React. I am expecting to receive an error that I could catch and render my view accordingly.
Unfortunately, the s3 API is not returning an error, so all the points in my code where I intend to catch the error are being passed and I cant render a view when I get the image and another view when I get an error.
My code looks like so:
//s3Connect.js
download: async (fileKey)=>{
const downloadParams={
Key:fileKey, //this is a wrong key like 123 or anything
Bucket:bucketName
}
const data = s3.getSignedUrlPromise('getObject', downloadParams);
return data
}
//adminPanel.js
//I call the above function below
getBackgroundCheck:async (req,res)=>{
const readStream = await s3.download(req.params.key).then(url=> {
console.log(url)
res.send({url})
})
.catch(error=>{
console.log(error)
res.send('the error is',error) //since I sent a wrong key I expect to catch an error here
} )
}
Now in the client side. I use React and the fetch method to retrieve the image
const getBackgroundFile = async (e) => {
try {
e.preventDefault()
const response = await fetch(`http://localhost:3003/adminPanel/getbackgroundcheck/${id}`)
console.log('this is the response ',response)
const parseResponse = await response.json()
console.log('this is the parseResponse', parseResponse)
setImage(parseResponse)
setShowBackImage(true)
}
catch (error) {
console.log('this is the error',error) //again I expect to see this in console
}
}
Finally:
What do I get with the console.logs from the above function
this is the response Response {type: 'cors', url: 'http://localhost:3003/adminPanel/getbackgroundcheck/nll%C3%B1', redirected: false, status: 200, ok: true, …}
So as you can see I get a 200 status. So how can I manage an error if I get a 200 ok status when I know that the response is failed because my server could not find the image in the s3 bucket and serve it to my client.
Creating a pre-signed URL is an operation that cannot fail, in normal operation. There's no actual API call behind the creation of a pre-signed URL - it's a simple local signing exercise in the SDK. It will happily generate pre-signed URLs for objects that don't exist, for example.
If you wan't to detect vending URLs for non-existent S3 objects, you'll have to do that some other way. For example, by proxying the downloads or pushing responsibility to the client.

Problem to call an API inside a Webhook - Javascript

I'm creating a chatbot using a Webhook in Javascript and in a moment I need to connect to my API(using a POST) to get some data and send the information received inside a message to the user. The problem here is the API is not been called and the flow just bypass my connection(I don't even see the connection in the API server).
I've run some testes with the API out of the Webhook and it worked.
I've tried to use async function and await but the application continues to "ignore" my API call.
Below is my code with my tests. I've made some changes with the URL just fo security purpose, but the logic is the same.
var price = 0
var payload = {'product_id': 'n/a'} **//Creating this global variable just for testing**
//CREATING THE FUNCTION TO CONNECT TO MY API USING AXIOS
function my_api(payload){
app.get("/", async(request, response) => {
const {data} = await axios.post('https://www.test.com/my_api', payload)
price = data.price
});
}
//FILLING MY TEST PAYLOAD
payload = {'product_id':10}
//CALLING THE API OUT OF THE WEBHOOK AND PRINTING THE RETURN ON MY WEBSITE CONSOLE
my_api(payload) **//If I call the API here, the application is accessed by the function. I confirmed that writing a response.send(price) command in the API function and check my API Server log**
//STARTING MY WEBHOOK
app.post("/webhook", async function (request, response) {
const agent = new WebhookClient({ request: request, response: response });
//THE FUNCTION WHERE THE API IS CALLED AFTER THE USER'S INPUT IN THE LAST INTENT AND I NEED TO WAIT IT RETURN WITH THE RESULT TO SEND THE MESSAGE
async function product_price(agent){
user_input = agent.query
var payload = {'product_id': user_input}
await my_api(payload) **//When I call the API function here it don't connect to my application**
agent.add('The price for this product is '+price)
}
}
Do you have any idea how can I connect to the API in the Webhook?
I've tried to create a function outside the Webhook and call the my_api(payload) function inside it but it didn't work.
Thank you for your attention.
You have a rest endpoint /webhook and in it's handler you create a function product_price but never execute it. To fix it you just have to call it like product_price() but in your code there is no need to create this function at all
//STARTING MY WEBHOOK
app.post("/webhook", async function (request, response) {
const agent = new WebhookClient({ request: request, response: response });
const user_input = agent.query
const payload = {'product_id': user_input}
await my_api(payload)
agent.add('The price for this product is '+price)
}
Your code has some weird stuff, that should also be improved: in my_api you create a rest endpoint for / but why? I guess you just want to make a request to get the price?
async function my_api(payload){
const {data} = await axios.post('https://www.test.com/my_api', payload)
price = data.price
}

How can I use re-fetch data in Next.js when an endpoint is hit?

I am using a webhook which triggers a request to an URL when a message is POST in the channel. I am using getServerSideProps to fetch data from the server,
export async function getServerSideProps({ req }) {
console.log("\x1b[36m%s\x1b[0m", "get req to serverside");
let messages = {};
if (req.method === "GET") {
messages = await getMessages(process.env.NEXT_PUBLIC_ROCKET_CHAT_CONF_RID,req.cookies)
}
if (req.method === "POST") {
// does a re-fetch but it is not sending me the data back
messages = await getMessages(process.env.NEXT_PUBLIC_ROCKET_CHAT_CONF_RID,req.cookies)
}
return {
props: {
messages,
cookies: req.cookies,
},
};
}
As quoted here in the doc,
Server-side Rendering: The HTML is generated on each request. To make a page use Server-side Rendering, export getServerSideProps. Because Server-side Rendering results in slower performance than Static Generation, use this only if absolutely necessary.
How can I re-fetch data and make the message sending part realtime?

GET/POST methods on Express

I am configuring a server using express.
My question has nothing to do with the project itself because it is running great.
I just have a minor doubt about why I have to use GET when for me it makes more sense to use POST.
So, for short I am configuring an API key on the server side and fetching it on the client side so I can use it.
This is the snippet on the server side:
const apiKey = process.env.API_KEY;
console.log(`Your API key is ${apiKey}`);
const dataObject ={};
app.get('/api', (req,res) => {
res.send({key: apiKey})
})
app.get('/all', sendData = (req,res) => {
res.send(dataObject)
})
app.post('/addText', (req,res) => {
let newEntry = {
agreement = req.body.agreement,
subjectivity = req.body.subjectivity
}
dataObject = newEntry;
res.send(dataObject);
} )
And then on the client side I fetch on the '/api' path:
const getApiKey = async () => {
// Getting API key from server
const request = await fetch('/api');
try {
const data = await request.json();
console.log(data);
return data;
}catch(error) {
console.log('ERROR', error);
}
}
Ok, that's working and everything, but my question is:
On the first GET on the server side, I understand that I am sending the API key to the '/api' path so that I can retrieve this key with fetch on the client side. But if I am sending the api key to this path, why am I using GET and not POST?
Sorry if it seems a stupid question but I am having a hard time understanding the GET method.
Thanks!
You are not sending any API key to the server. The server is sending the API key to the client as a response. The client uses a GET request to get the API key from /api. The names of the methods (GET, POST, PUT, DELETE, ...) are from the perspective of the client.
"And then on the client side I fetch on the '/api' path:" No. First the client sends the request with
const request = await fetch('/api');
try {
const data = await request.json();
console.log(data);
return data;
}catch(error) {
console.log('ERROR', error);
}
This triggers the callback in
app.get('/api', (req,res) => {
res.send({key: apiKey})
})
and the server sends the response.
This code returns the API key from the server. It does not send it from the client to the server.
app.get('/api', (req,res) => {
res.send({key: apiKey})
}
The
res.send()
Function is constructing the response returned by the server to the client.
Usually, you use the GET method when the client has to read some data from the server, in this case, you want to read the API_KEY defined in the server. GET has no body, but every request may be parametric by passing parameters in the query string.
On the other hand, when you have to update or create an entity on the server, that's when POST (or PUT) enters into action. Here you pass your data in the body of the request.

Parse raw body on cloudflare-worker service(Non NODE)

I've created an api server'ish environment on cloudflare using cloudflare-worker and there is no node server running(cloudflare-worker is pretty much serverless event handler service). It does provide the configurations to handle any subdomain calls much like how api works. I've used a package called cf-worker-router to do so.
My cloud service looks like this:
import { ApiError, ApiRedirect, DomainRouter, FetchRouter } from 'cf-worker-router';
const router = new FetchRouter();
// add the cloudflare event listener
addEventListener('fetch', (event) => {
router.onFetch(event);
});
router.route('/users', 'POST', async (event) => {
// automatically converts anything not of Response type to ApiResponse
return await event.request.text();
});
And what I did was create a POST request to the url and supplied some body to the request. I was able to get the request text successfully but now I can't figure out how to parse the text I received.
When using the request as multipart/form-data request and the received body text is as follows:
"----------------------------093590450792211419875705\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nJon Doe\r\n----------------------------093590450792211419875705--\r\n"
I tried sending application/x-www-form-urlencoded and I the response text as such:
"name=Jon%20Doe"
And Similar for application/json request:
"{\n\t\"name\": \"Jon Doe\"\n}"
Since cloudflare is not using nodejs server, body-parser can't be applied here. This service is pretty much an open api so it needs to take care of all sorts of request content types. Is there any way to identify and decode the strignified contents from any of these content types to a valid object in javascript?
To handle form data uploads, you can use the request.formData() method which will return a promise of a FormData object.
For example:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
async function handleRequest(request) {
const formData = await request.formData();
const name = formData.get('name');
return new Response(`Hello ${name}`);
}

Categories

Resources