Can I create a method that will call on demand from the strapi project to get the data from external services?
Basically, I need to call a method when I route to some collection. This method will call the external source using Axios to get data from it.
Hi Sunnyson,
I didn’t understand your solution much.
But I have a requirement where I will use my local version link to call some route path, which will make call to external source which is being passed as a parameter in the link.
Basically, I want the steps that needs to be followed to accomplish my goal.
Oh, Got it. I got a bit confusing. My bad. So actually you want to make a route like this and pass a parameter with url?
http://localhost:1337/api/example?link=https://externalsource.com/api
And it should retrieve data from that url and add it to your collection type?
Create the controller (/controllers/controllerName.js)
const axios = require('axios');
module.exports = {
async index(ctx) {
let { link } = ctx.query;
let { data } = await axios.get(link);
//process data here and map it.
await strapi.query('someCollection').create(data);
return data;
}
}
Create the route (/config/routes.json) and add the created controller function to handler
[
{
"method": "GET",
"path": "/example",
"handler": "controllerName.index",
"config": {
"policies": []
}
}
]
Now when you will send a request to http://localhost:1337/api/example?link=https://externalsource.com/api it will get the data from that source and store it in db.
Hi Sunnyson,
Thanks for the response. I understand everything in this code.
But I have to create a api path like http://localhost:1337?collection={collectionName}&extsrc={externalSourceLink/Name}.
So, Is it possible to create a query like this and get the collection data using {collectionName} and {externalSourceLink/Name}.
For your example, the code will look like this:
Create the controller (/controllers/controllerName .js)
const axios = require('axios');
module.exports = {
async index(ctx) {
let { collection, extsrc } = ctx.query;
//hard-coding collection types, to avoid calls to inexistent collection,
//also you can write a function to retrieve the collectionTypes dynamically.
let allowedCollectionTypes = ['collectionType1','collectionType2','collectionType3'];
if (!allowedCollectionTypes .includes(collection)) {
return {
status: 'error',
message: `<${collection}> type is not Pre-configured in the API. Please add it to allowedCollectionTypes. `,
};
}
//fetching data from external source
let { data } = await axios.get(extsrc);
//you can add a service with multiple functions in it for each collectionType.
//example:
await strapi.services.storeDataFromExtSrc[collection](data);
return {
status:'ok',
message: `Data stored successfully in ${collection}`
};
}
}
In the service file (/services/storeDataFromExtSrc.js) create functions for each collectionType
module.exports = {
collectionType1: async (data) => {
//some mapping/validations here for collectionType1, maybe it has different fields and etc.
await strapi.query(collectionType1).create(data);
},
collectionType2: async (data) => {
//some mapping/validations here for collectionType2, maybe it has different fields and etc.
await strapi.query(collectionType2).create(data);
},
collectionType3: async (data) => {
//some mapping/validations here for collectionType3, maybe it has different fields and etc.
await strapi.query(collectionType3).create(data);
}
}
Hi Sunnyson,
Thanks for the response.
Can we create a global routing. And can we also create global controller for the global routing handler?
Basically, I don’t want to navigate to any controller written inside ./api/{collectionName}/controller.
I just want to navigate based on custom routing that will call the collections to get the data.
Of course you can make a global route, just generate a new API using CLI:
strapi generate:api extsrc
Now navigate inside it to /extsrc/config/routes.json
and change the default to “/”.
{
"method": "GET",
"path": "/",
"handler": "extsrc.process",
"config": {
"policies": []
}
}
Now it will be accessible on http://localhost:1337?collection={collectionName}&extsrc={externalSourceLink/Name}. But make sure that you don’t have other routes that also have root path “/”.
In controller: /extsrc/controller/extsrc.js
and /extsrc/services/extsrc.js
: Write the logic I described in previous response.