如何将Cookie添加到vue-apollo请求?

时间:2019-10-25 21:50:51

标签: django cookies vuejs2 apollo vue-apollo

我使用vue-cli-plugin-apollo,并且我想通过Cookie将用户选择的language从前端发送到后端。

作为vue-apollo.js,我使用下一个模板

import Vue from 'vue'
import VueApollo from 'vue-apollo'
import { createApolloClient, restartWebsockets } from 'vue-cli-plugin-apollo/graphql-client'

// Install the vue plugin
Vue.use(VueApollo)

// Name of the localStorage item
const AUTH_TOKEN = 'apollo-token'

// Http endpoint
const httpEndpoint = process.env.VUE_APP_GRAPHQL_HTTP || 'http://localhost:4000/graphql'

// Files URL root
export const filesRoot = process.env.VUE_APP_FILES_ROOT || httpEndpoint.substr(0, httpEndpoint.indexOf('/graphql'))

Vue.prototype.$filesRoot = filesRoot

// Config
const defaultOptions = {
  // You can use `https` for secure connection (recommended in production)
  httpEndpoint,
  // You can use `wss` for secure connection (recommended in production)
  // Use `null` to disable subscriptions
  wsEndpoint: process.env.VUE_APP_GRAPHQL_WS || 'ws://localhost:4000/graphql',
  // LocalStorage token
  tokenName: AUTH_TOKEN,
  // Enable Automatic Query persisting with Apollo Engine
  persisting: false,
  // Use websockets for everything (no HTTP)
  // You need to pass a `wsEndpoint` for this to work
  websocketsOnly: false,
  // Is being rendered on the server?
  ssr: false,

  // Override default apollo link
  // note: don't override httpLink here, specify httpLink options in the
  // httpLinkOptions property of defaultOptions.
  // link: myLink

  // Override default cache
  // cache: myCache

  // Override the way the Authorization header is set
  // getAuth: (tokenName) => ...

  // Additional ApolloClient options
  // apollo: { ... }

  // Client local data (see apollo-link-state)
  // clientState: { resolvers: { ... }, defaults: { ... } }
}

// Call this in the Vue app file
export function createProvider (options = {}) {
  // Create apollo client
  const { apolloClient, wsClient } = createApolloClient({
    ...defaultOptions,
    ...options,
  })
  apolloClient.wsClient = wsClient

  // Create vue apollo provider
  const apolloProvider = new VueApollo({
    defaultClient: apolloClient,
    defaultOptions: {
      $query: {
        // fetchPolicy: 'cache-and-network',
      },
    },
    errorHandler (error) {
      // eslint-disable-next-line no-console
      console.log('%cError', 'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;', error.message)
    },
  })

  return apolloProvider
}

取自here。所有选项均显示为here

我在不同的github讨论中看到cookies必须放在headers内,例如here。然后我发现apollo-link-httpheaders选项,所以最后我尝试了...的不同变体:

httpLinkOptions: {
  headers: {

    // Tried something like:
    cookie[s]: 'language=en; path=/;'

    // and something like:
    cookie[s]: {
      language: 'en'
    }
  }
}

但没有运气。

如果使用cookie S ,我会收到Error: Network error: Failed to fetch

对于cookie,发送请求时不会出现问题,但后端看不到language cookie。

我使用Postman仔细检查了后端,在这种情况下,后端接收到带有手动添加的language cookie的请求。

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

找到解决方案。

前端设置

  1. 创建cookie:
export function languageCookieSet (lang) {
  document.cookie = `language=${lang}; path=/;`
}
  1. httpLinkOptions的{​​{1}}中添加defaultOptions
vue-apollo.js

后端设置

作为后端,我使用const defaultOptions = { ... httpLinkOptions: { credentials: 'include' }, ... (当前为v2.2.7)。

  1. 对于开发,我们需要使用django-cors-headers
  2. 我的Django现在看起来像:
development.py
  1. 添加到from .production import * CORS_ORIGIN_WHITELIST = ( 'http://localhost:8080', ) CORS_ALLOW_CREDENTIALS = True INSTALLED_APPS += ['corsheaders'] MIDDLEWARE.insert(0, 'corsheaders.middleware.CorsMiddleware')
production.py

LANGUAGE_COOKIE_NAME = 'language' 的默认值为LANGUAGE_COOKIE_NAME,因此,如果适合您,请更改

django_language

document.cookie = `language=${lang}; path=/;`
  1. 现在在后端,我们可以获取前端语言:
document.cookie = `django_language=${lang}; path=/;`

注意:我尚未测试生产环境中的这些更改,但是在生产环境中,我仅使用一台服务器,前端和后端位于import graphene from django.contrib.auth import get_user_model from django.utils.translation import gettext as _ from .views import user_activation__create_email_confirmation User = get_user_model() class UserRegister(graphene.Mutation): """ mutation { userRegister(email: "test@domain.com", password: "TestPass") { msg } } """ msg = graphene.String() class Arguments: email = graphene.String(required=True) password = graphene.String(required=True) def mutate(self, info, email, password): request = info.context # Here we get either language from our cookie or from # header's "Accept-Language" added by Browser (taken # from its settings) lang = request.LANGUAGE_CODE print('lang:', lang) if User.objects.filter(email=email).exists(): # In our case Django translates this string based # on the cookie's value (the same as "request.LANGUAGE_CODE") # Details: https://docs.djangoproject.com/en/2.2/topics/i18n/translation/ msg = _('Email is already taken') else: msg = _('Activation link has been sent to your email.') user = User(email=email) user.set_password(password) user.save() user_activation__create_email_confirmation(info.context, user) return UserRegister(msg=msg) 之后,这就是CORS设置有效的原因在nGinx中而不是development.py中。同样在生产中,production.py可能会更改为credentials: 'include'(即更严格)。