Vue使用GraphQL Apollo动态修改URI

商运锋
2023-12-01

前言

继上次完成在Ant Design Pro Vue中集成GraphQL使用后,为了配合后端做日志记录,需要进行语义化接口地址,即:

对于单个查询操作,需要加参数:/graphql?query:goods

对于单个变更操作,需要加参数:/graphql?mutation:updateGood

对此,需要在每次进行graphql提交操作时,根据提交的参数进行动态修改Uri。

具体实现

引入createHttpLink…,直接看代码吧:

import storage from 'store'
import {ApolloClient} from 'apollo-client'
// 下面这句目前用不到了
// import {HttpLink} from 'apollo-link-http'
import { createHttpLink } from "apollo-link-http"
import {InMemoryCache} from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
import {ApolloLink} from 'apollo-link'

// 下面注释的是原先固定的uri
/* var apiLink = new HttpLink({
  // uri: Vue.prototype.$graphql_url
  uri: process.env.VUE_APP_API_GRAPHQL_URL    //请求路径
}) */

// 动态修改uri地址
const customFetch = (uri, options) => {

  var { operationName } = JSON.parse(options.body)
  var type = 'query'
  // 以下是由于我自定义了operationName,所以需要去掉前缀
  if (operationName.indexOf('q') == 0) {
    type = 'query'
    operationName = operationName.replace('q_', '')
  } else if (operationName.indexOf('c') == 0) {
    type = 'mutation'
    operationName = operationName.replace('c_', '')
  } else if (operationName.indexOf('u') == 0) {
    type = 'mutation'
    operationName = operationName.replace('u_', '')
  } else if (operationName.indexOf('d') == 0) {
    type = 'mutation'
    operationName = operationName.replace('d_', '')
  }

  return fetch(process.env.VUE_APP_API_GRAPHQL_URL + `?${type}:${operationName}`, options)
}

完整代码:

import storage from 'store'
import {ApolloClient} from 'apollo-client'
import { createHttpLink } from "apollo-link-http"
import {InMemoryCache} from 'apollo-cache-inmemory'
import VueApollo from 'vue-apollo'
import {ApolloLink} from 'apollo-link'

// 动态修改uri地址
const customFetch = (uri, options) => {
  var { operationName } = JSON.parse(options.body)
  var type = 'query'
  if (operationName.indexOf('q') == 0) {
    type = 'query'
    operationName = operationName.replace('q_', '')
  } else if (operationName.indexOf('c') == 0) {
    type = 'mutation'
    operationName = operationName.replace('c_', '')
  } else if (operationName.indexOf('u') == 0) {
    type = 'mutation'
    operationName = operationName.replace('u_', '')
  } else if (operationName.indexOf('d') == 0) {
    type = 'mutation'
    operationName = operationName.replace('d_', '')
  }
  return fetch(process.env.VUE_APP_API_GRAPHQL_URL + `?${type}:${operationName}`, options)
}

const apiLink = createHttpLink({ fetch: customFetch });

const middlewareLink = new ApolloLink((operation, forward) => {
  const token = storage.get('Access-Token')
  const user_info = storage.get('user_info')
  var role = user_info ? user_info.type : ''
  operation.setContext({
    headers: {
      'api-token': token || null,
      'api-source': role
    }
  })
  return forward(operation)
})
const apiClient = new ApolloClient({
  // 如果不添加请求头直接放路径
  link: middlewareLink.concat(apiLink),
  cache: new InMemoryCache()
})
const apolloProvider = new VueApollo({
  // 默认请求路径,如果只有一个请求就使用这个就行
  defaultClient: apiClient
})
Vue.use(VueApollo)

header也可以动态修改,具体实现可以参考链接:https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-http#upgrading-from-apollo-fetch–apollo-client
这里贴下示例代码:

const customFetch = (uri, options) => {
  const { header } = Hawk.client.header(
    "http://example.com:8000/resource/1?b=1&a=2",
    "POST",
    { credentials: credentials, ext: "some-app-data" }
  );
  options.headers.Authorization = header;
  return fetch(uri, options);
};

const link = createHttpLink({ fetch: customFetch });
 类似资料: