Need help with creating a generic function which can be used to call Graphql API from react-apollo.
Learn about the following ways
using componenet
graphql(gqlquery{...}) method
using axios lib
any suggestion how can I create a generic function or common function that can be used.
using axios library.
const graphqlfetchhandler = async (query, variables) => {
try {
const response = await axios.post(
endpointURL,
{
query: gitQuery,
variables: variables
},
{
headers: {
Authorization: "token YOUR_TOKEN_HERE"
}
}
);
console.log(response.data);
} catch (error) {
console.log(error);
}
};
Related
I am using next js as a front-end and laravel as a back-end. and i want to call back-end (laravel) api from getServerSideProps() method. as shown below
export async function getServerSideProps(context) {
const response = await Axios.request({
url: 'http://localhost:8000/api/event',
method: 'get',
headers: {
Cookie: context.req.headers.cookie,
},
})
const events = response.events
console.log(response)
return {
props: { events },
}
}
so i have also set the cookie but i am getting response with message unauthenticated like below
I just wanted to say a huge THANK YOU to Riaz Kahn for his answer. After a lot of banging my face against a wall this was the answer. I'm going to post a working example of my getServerSideProps function for anyone arriving here in the future. The getUser({[configObject]}) function is just returning a promise from an axios.get('my-user/route', config) call. This is working properly in a Next 13 app using standard pages functionality (not using experimental app directory).
export const getServerSideProps = async (context: any) => {
const {req, res} = context;
try {
const {data: user} = await getUser({
headers: {...req.headers}
});
return {
props: {
fallback: {user}
}
}
} catch (e) {
res.writeHead(302, {Location: '/login'});
res.end();
}
}
I am trying to unit test a function which makes an async call using an Axios helper instance. I have attempted multiple ways of trying to unit test this but I can not seem to find any material online which has helped. I've been stuck on this problem for a few days which is frustrating so any help would be appreciated! Below are the Axios Helper file (api.js)
api.js
import axios from 'axios'
const API = (token = null) => {
let headers = {
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-key': process.env.NEXT_PUBLIC_API_HEADER_SUBSCRIPTION_KEY
}
if (token) {
const tokenHeader = { Authorization: 'Bearer ' + token }
headers = { ...headers, ...tokenHeader }
}
const url = process.env.NEXT_PUBLIC_API_BASE_URL
const API = axios.create({
baseURL: url,
headers
})
return API
}
export default API
mocked API
export default {
post: jest.fn(() =>
Promise.resolve({
data: {}
})
),
get: jest.fn(() =>
Promise.resolve({
data: {}
})
)
}
action file
export const initiate2FA = (destinationValue) => async () => {
const twoFactorAuth = destinationValue
const res = await API().post('/foo', {
Destination: twoFactorAuth
})
return res
}
Action.test.js
import API from 'api/api'
import { initiate2FA } from 'actions/userActions'
jest.mock('api/api')
const mockedAxios = API
const dispatch = jest.fn()
describe('Initiate2FA function', () => {
it('bar', async () => {
mockedAxios.get.mockImplementationOnce(() => Promise.resolve({ status: 200 }))
const t = await dispatch(initiate2FA('test#test.com'))
console.log(t)
})
})
My issue with the above test file is that it returns an anonymous function and I do not know how to handle this to pass the unit test. The goal of the test is to make sure the function is called. I am not sure if I am approaching this the correct way or should change my approach.
Again, any suggestions would be great!
Mocking an API call is something you can mock on your own React component, instead of a function, and the best option would be to not mock anything on your component. Here you can read all about why you should not mock your API functions. At the end of the article, you're going to find a library called Mock Service Worker which you can use for your purpose.
The way you declare you have an actual HTTP called that needs to be mocked would be something like this:
rest.get('/foo', async (req, res, ctx) => {
const mockedResponse = {bar: ''};
return res(ctx.json(mockedResponse))
}),
If you just need to unit test a function, you can still use Mock Service Worker to resolve the HTTP request, and then test what happens after that. This would still be your first choice. And the test would look like:
// this could be in another file or on top of your tests.
rest.get('/foo', async (req, res, ctx) => {
const mockedResponse = {bar: ''};
return res(ctx.json(mockedResponse))
}),
// and this would be your test
describe('Initiate2FA function', () => {
it('bar', async () => {
const res = await initiate2FA('test#test.com');
expect(res).toBe({bar: '');
})
})
I am using Vue.js with Vue-Apollo and trying to fetch shared member list using query. I am using the graphQL service in backend.
I am using apollo 'error' function to handle GraphQL error. When the request is made with invalid input, I can see the errors in the network tab, I can see the JSON for the custom errors messages. But I can't console the errors in 'error' function.
Here is the apollo query that is used to fetch shared member list -
apollo: {
sharedMembers: {
query: gql`
query item($uuid: ID) {
item(uuid: $uuid) {
...itemTemplate
members {
...member
permission
}
}
}
${ITEM_TEMPLATE}
${MEMBER}
`,
variables() {
return {
uuid: this.$route.params.uuid,
}
},
update(data) {
return data.item.members
},
error(error) {
console.log('errors', error)
}
},
},
The network response I got -
network_error
Using graphQLErrors
You could get the errors by looking in the error object for graphQLErrors:
error(error) {
console.log('errors', error.graphQLErrors)
}
or
error({ graphQlErrors }) {
console.log('errors', graphQLErrors)
}
Using apollo-error-link
You can use apollo-error-link to help solve your problem if the above doesn't work, docs here.
Here's an example from the docs and I added to it in the networkErrors section to show what you can do to edit the error message you see in your error block, or catch block if its a mutation.
import { onError } from "apollo-link-error";
const link = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.map(({ message, locations, path }) =>
console.log(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
),
);
if (networkError) {
// Add something like this to set the error message to the one from the server response
networkError.message = networkError.result.errors[0].debugMessage
console.log(`[Network error]: ${networkError}`)
};
});
And then in your code:
error(error) {
console.log('error-message', error.message)
}
The console should then log your debugMessage from the server.
unfortunately i couldn't find out how i'd handle errors in such of graphql method call, but as an option you could provide onError method to ApolloClient constructor options. first argument is the error object. hopefully it may help. like so..
const apolloClient = new ApolloClient({
uri: 'http://localhost:4000',
onError(err) {
console.log(err)
},
})
I can access the request header in a get or post call
fastify.get('/route1',(req,res,next)=>{
console.log(req.headers.Authorization)
...
}
I am looking for a way to pass it to a plugin register call, specifically fastify-graphql
const { graphqlFastify } = require("fastify-graphql");
fastify.register(graphqlFastify,
{
prefix: "/graphql",
graphql: {
schema: schema,
rootValue: resolvers,
context:{auth:req.headers.Authorization} <-----
}
},
err => {
if (err) {
console.log(err);
throw err;
}
}
);
Is there a way to write a wrapper or any ideas?
I think you can't do that.
If read the code you will find that:
fastify-graphql is calling runHttpQuery
runHttpQuery is calling context without passing the request
So I think that you should check the auth-client with a standard JWT and then use another token server-side.
The final solution could be to check Apollo 2.0 and open the issue on fastify-graphql.
Here a little snippet that explain the idea:
const fastify = require('fastify')({ logger: true })
const { makeExecutableSchema } = require('graphql-tools')
const { graphiqlFastify, graphqlFastify } = require('fastify-graphql');
const typeDefs = `
type Query {
demo: String,
hello: String
}
`
const resolvers = {
Query: {
demo: (parent, args, context) => {
console.log({ args, context });
return 'demo'
},
hello: () => 'world'
}
}
const schema = makeExecutableSchema({ typeDefs, resolvers })
fastify.register(graphqlFastify, {
prefix: '/gr',
graphql: {
schema,
context: function () {
return { serverAuth: 'TOKEN' }
},
},
});
fastify.listen(3000)
// curl -X POST 'http://localhost:3000/gr' -H 'Content-Type: application/json' -d '{"query": "{ demo }"}'
For anyone who need to access request headers in graphql context, try
graphql-fastify
Usage
Create /graphql endpoint like following
const graphqlFastify = require("graphql-fastify");
fastify.register(graphqlFastify, {
prefix: "/graphql",
graphQLOptions
});
graphQLOptions
graphQLOptions can be provided as an object or a function that returns graphql options
graphQLOptions: {
schema: schema,
rootValue: resolver
contextValue?: context
}
If it is a function, you have access to http request and response. This allows you to do authentication and pass authentication scopes to graphql context. See the following pseudo-code
const graphQLOptions = function (request,reply) {
const auth = decodeBearerToken(request.headers.Authorization);
// auth may contain userId, scope permissions
return {
schema: schema,
rootValue: resolver,
contextValue: {auth}
}
});
This way, context.auth is accessible to resolver functions allowing you to check user's scope/permissions before proceeding.
I am using axios to create a restful api in my project.Based on the server response I am trying to dispatch an action.
restful api code
handleSubmit(e) {
console.log("form submit");
e.preventDefault();
const forms=new FormData(e.target);
axios.post("http://localhost:8080/reactLogin",forms).then(res=> {
console.log(res.data);
this.props.loginSubmit(res.data);
}).catch(err=>console.log(err))
}
code to dispatch action in react-redux
const mapStateProps=(state) => {
return {
userLogin:state.loginDetails
}
}
const mapDispatchProps=(dispatch) => {
return {
loginSubmit:(data) => {
console.log(data);
if(data.status==1) {
dispatch(loginSuccess(data.data[0]));
}
else {
dispatch(loginFail(data))
}
},
emailInputBorder:(data) => {
dispatch(emailBorder(data));
},
passwordInputBorder:(data) => {
dispatch(passwordBorder(data));
}
}
}
export default connect(mapStateProps,mapDispatchProps)(Login)
when i trying to dispatch an action in my restful api response it shows following error
TypeError: Cannot read property 'props' of undefined
what the issue here is?
If you are using a functional component, you can access the props directly without using the this keyword.
Access the method with something like props.loginSubmit directly.
Since I am not able to view your entire file, this is just a pre-assumption. It would be helpful if you could share the entire code.