I want to disable caching or restrict the cache to 24 hours. My ApolloClient runs exclusively on the Server side.
My environment:
apollo-boost 0.4.3
graphql 14.1.1
apollo-link-batch-http - 1.2.12
Right now, that's how I configure my ApolloClient.
new ApolloClient({
ssrMode: true,
cache: new InMemoryCache(),
link: WithApollo.BatchLink(),
credentials: 'same-origin',
});
The closest thing I saw in docs is FetchOptions ... But it doesn't specify what options i can actually pass to achieve my need for disabling or restricting the cache.
This is not possible with Apollo Boost. You need to migrate to migrate to using Apollo Client. This will allow you to provide a defaultOptions option to your ApolloClient constructor as shown in the docs:
const defaultOptions = {
watchQuery: {
fetchPolicy: 'no-cache',
},
query: {
fetchPolicy: 'no-cache',
},
}
The fetchPolicy option can actually be set on each individual query call or Query component -- by providing a defaultOptions object, you avoid having to specify no-cache as the fetch policy on each individual Query component you use. That also means if you're bent on keeping Boost, you could just do this on each of your components. However, the above is how to effectively "turn off" caching for the whole client.
Maybe someone want to know how to disable caching of apollo-boost ApolloClient exactly, so let's talk about it.
#Daniel said is truth, we cannot disable the caching when we do new ApolloClient of apollo-boost directly, but we can set fetchPolicy when we send out the request. The code as below:
// create client first
import ApolloClient from "apollo-boost";
const client = new ApolloClient({ uri: GRAPHQL_URL })
// Set the fetchPolicy when we send request
import { gql } from 'apollo-boost';
client.query({
query: gql`
query someInfo($id: ID!) {
info(id: $id) {
id
name
}
}`,
variables:{id: '123'},
fetchPolicy: 'no-cache'
})
The valid value for fetchPolicy you can find from there.
Related
In my react app, I created an api.js file which creates an api object with axios.create and exports it as default. So, I use that template to make the API requests. The problem is that, one of the headers in created axios api object must be dynamic.
For example, see the locale header below:
At first it may be something like this:
export default api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
headers: {
post: {
"Content-Type": "application/json;charset=utf-8",
"Access-Control-Allow-Origin": "*",
locale: "en",
},
get: {
locale: "en",
},
},
});
But after some time it can be updated to some other locale, like "en" should be changed with "fr" for example. How can I update it, and make sure when it gets updated it changes in every place api is imported.
I can't use ContextApi etc, because I need to use that api in index.js file too, which, because of not being a react component, doesn't support use of hooks.
Sounds like a job for Axios interceptors...
import axios from "axios"
// some kind of storage for your locale
let locale = "en"
// some way of changing it
export const setLocale = (newLocale) => {
locale = newLocale
}
const api = axios.create({
baseURL: process.env.REACT_APP_API_URL,
})
// register a synchronous request interceptor
api.interceptors.request.use(config => ({
...config,
headers: {
...config.headers,
locale // merge the "locale" into the request config headers
}
}), null, { synchronous: true })
export default api
Also, Access-Control-Allow-Origin is a response header that comes from the server. It does not belong in your request and in general will more than likely cause CORS errors.
Also, the default content-type when posting JS objects in Axios is application/json so you typically don't need to set it.
I currently have a Nestjs server setup and am attempting to perform an Axios request when one of the endpoints is hit with a GET request. Here is the controller.ts code:
#Controller()
export class TestController {
constructor(private readonly testService: TestService) {}
#Get('testData')
testData() {
return this.testService.testData();
}
}
Service.ts:
#Injectable()
export class TestService {
status(): string {
return 'OK'
}
testData(): Promise<any> {
return helper.getTestData();
}
}
Where helper.getTestData() is just a call to a helper file with the following function:
export async function getTestData(): Promise<any> {
const result = await axios({
url: tempURL,
method: 'GET',
timeout: 3000,
httpsAgent: new https.Agent({
rejectUnauthorized: false,
}),
});
I am able to hit this endpoint tempURL but encounter the following error message: Cannot read property 'Agent' of undefined. I know that the endpoint I am attempting to hit requires a cert, which is why I must include the httpsAgent argument inside the Axios request. If I don't include the httpsAgent argument, I receive the following message Error: unable to verify the first certificate in nodejs.
Is there a way to configure Nestjs to work with https? Or is there another way to handle this authorization issue inside of Nestjs? Using Postman everything works fine so I'm assuming it is a Nestjs issue. Any help is appreciated.
instead of import https from 'https'; you should use the namespace import: import * as https from 'https'; or set the esModuleInterop to true in your tsconfig file (under compilerOptions)
I want to call an API in asyncData()
async asyncData({ $axios, params, store }) {
let itemUUID = params.item;
let item = await $axios.get("/item/" + itemUUID);
return {item};
}
Problem: Axios is still making the request on http://localhost:3000
if I do a console.log($axios.defaults.baseURL) the correct baseURL of my API is printed.
This also works if I use my store action & make the call by using this.$axios
I am using #nuxtjs/axios 5.13.1 with Nuxt 2.15.6 in SSR mode and configured it with the correct baseURL in the nuxt.config.js
Interestingly, if I edit my page content and a hot module reload is triggered, the correct URL is used. Maybe the question should be if Axios is triggered in the right time, on the server?
Edit: I checked the request that was made on HMR and this was triggered in the client.js.
If I call my store inside the created() hook the request gets executed successfully.
My nuxt.config.js:
publicRuntimeConfig: {
axios: {
baseURL: process.env.EXPRESS_SERVER_URL
}
},
privateRuntimeConfig: {
axios: {
baseURL: process.env.EXPRESS_SERVER_URL,
}
},
I'm not sure what is the NODE_TLS_REJECT_UNAUTHORIZED=0 thing doing but your frontend configuration (Nuxt) is working well so far.
Sorry if I cannot help on the Express part.
Maybe try to setup HTTPS locally on Nuxt: How to run NUXT (npm run dev) with HTTPS in localhost?
TLDR; This was not related at all - I forgot to set the auth token for my backend. At the time of axios init it's not present. $axios object doesn't have auth - backend fails.
On page load the nuxt function nuxtServerInit() is used to get the auth token out of the acces_token cookie.
I am using a plugin to initialize Axios - with the token from the store.
But of couse the token is not present at the time axios is initialized as nuxtServerInit is called after plugin init.
In my axios.js plugin I changed:
export default function({ app, error: nuxtError, store }) {
const token = const token = store.state.user.token;
app.$axios.setToken(token, "Bearer");
}
to;
export default function({ app, error: nuxtError, store }) {
const token = app.$cookies.get("access_token");
app.$axios.setToken(token, "Bearer");
}
Now the token is present & used for every request happening server-side.
I just realize and noticing that my vue app doesn't work well on some older browsers (ios 9 for example). I used the vue-apollo to get data from graphql api using django graphene , but it doesn't event get called on the first load when i debug it.
Previously i get error like "fetch is not found globally", but then i already fix it by adding "unfetch" to the ApolloClient config. But i still can't see on xhr network the api get called. I haven't try with isomorphic-fetch
Here's my code for the apollo client config:
// src/utils/graphql.js
import { ApolloClient } from 'apollo-client';
import { HttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import fetch from 'unfetch'
export default new ApolloClient({
// Provide the URL to the API server.
link: new HttpLink({ uri: '/api/', fetch: fetch }),
// Using a cache for blazingly
// fast subsequent queries.
cache: new InMemoryCache(),
connectToDevTools: true
});
and i specify it like so in the main.js
import apolloClient from '../utils/graphql'
import VueApollo from 'vue-apollo'
Vue.use(VueApollo);
Vue.config.silent = true
const apolloProvider = new VueApollo({
defaultClient: apolloClient,
defaultOptions: {
$loadingKey: "loading"
}
})
This is example of the apollo that i use inside the main.js as well using the smart query:
apollo: {
currentUser: {
query: GET_LOGGED_USER,
skipQuery() {
return this.skipUser
}
}
}
How can i make it work on ios 9 / any older browser?
Ok, after debugging it for two days, I finally found out the issue. So it turns out that i need to add and configure babel/polyfill as well in order to make it works, and add it to the entry point of my app.
Hope everyone who has the same issue can learn from my mistake lol
I'm just start using graphql with apollo client, I have graphql server setup and is running localhost:4000, and here is my client
index.js
const client = new ApolloClient({
uri: "http://localhost:4000/graphql",
cache: new InMemoryCache()
});
blog.js
const GET_BLOG = gql`
{
post(id:"5ab2b46d941953bf614e2617") {
title
body
user {
name
email
}
}
}
<Query query={GET_BLOG}>...</Query>
I got everything working, my question is there way I can change the graphql endpoint url name, so instead of graphql, can I have something like /graphql/post, /graphql/user, I have the scheme in graphql server, but if I do two call, it will just return two /graphql in network tab
SERVER.applyMiddleware({
app: APP,
path: '/newEndPoint'
});
Set path attribute within applyMiddleWare Options object. Now visit
localhost:<port>/newEndPoint for the grap
As far as I know, graphql only use one endpoint url name, in your case is http://localhost:4000/graphql , if you want separated endpoint, it is just like REST routing