每当我向服务器发送POST
请求时,{strong>总是会返回OPTIONS
。
我有一个使用React
和Apollo
的非常简单的登录应用程序。当我提交表单时,应该使用 POST 请求将mutation
发送到服务器,但是 OPTIONS 总是会拦截。
但是当我使用 Firefox 时,在OPTIONS
之后,接下来需要 POST ,如下所示:
我知道我无法禁用预检选项,因为根据我的研究,使用Content-Type: application/json
/ bodyParser.json()
会触发预检。
但是我需要Content-Type: application/json
才能使graphql
工作。但是有什么可能的方法只是 POST 请求而忽略 OPTIONS ?
我需要POST请求返回的this.props.data
所以我可以将令牌存储在客户端浏览器的localStorage中...
我的问题是:
this.props.data
,因为
OPTIONS
总是在实际的 POST (在Firefox中)我只想从POST请求中获取data
这是cors的问题吗?有人可以启发我做错了什么吗?非常感谢您。
PS: 我尝试了以下链接:https://github.com/graphql/express-graphql/issues/14,但仍然无法解决此问题...
这是我的服务器:
const express = require('express')
const morgan = require('morgan')
const bodyParser = require('body-parser')
// Grahql
const expressGraphQL = require('express-graphql')
const jwt = require('jsonwebtoken')
const cors = require('cors')
const chalk = require('chalk')
const model = require('./db/models')
const schema = require('./schema/schema')
const app = express()
app.use(cors())
app.options('*', cors())
app.use(bodyParser.json())
app.use(morgan('dev'))
// secret key
const SECRET = 'eggieandsausage'
// this method checks token authenticity from
// user attempting to login
const verifyTokenAuthenticity = async (req, res, next) => {
const token = req.headers['authentication']
try {
// verify token from headers
const { user } = await jwt.verify(token, SECRET)
// store user in req
req.user = user
} catch(err) {
console.log(err)
}
// proceed
next()
}
// Graphql
//app.use(verifyTokenAuthenticity)
app.use('/graphql', expressGraphQL(req => ({
schema,
graphiql: true,
// this context is accessible within resolve()
context: {
model,
SECRET,
user: req.user
}
})))
// Initial Route
app.get('/', (req, res) => {
res.sendFile(__dirname + '/index.html')
})
const PORT = process.env.PORT || 8080
app.listen(PORT, () => console.log(chalk.green(`MAGIC STARTS AT PORT ${PORT}`)))
这是我的变异:
const graphql = require('graphql')
const {
GraphQLObjectType,
GraphQLString,
GraphQLNonNull
} = graphql
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const UserType = require('./types/user_type')
const mutation = new GraphQLObjectType({
name: 'Mutation',
fields: {
signup: {
type: UserType,
args: {
email: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
},
resolve(parentValue, { email, password }, { model }) {
return new Promise((resolve, reject) => {
model.User.create({
email,
password
})
.then(user => {
if (!user)
return reject('Sorry. something went wrong')
resolve(user)
})
.catch(error => reject(error))
})
}
},
signin: {
type: UserType,
args: {
email: { type: new GraphQLNonNull(GraphQLString) },
password: { type: new GraphQLNonNull(GraphQLString) }
},
// params: parentValue, args, context
resolve(parentValue, { email, password }, { model, SECRET }) {
return new Promise((resolve, reject) => {
model.User.find({ where: { email } })
.then(user => {
if (!user)
return reject('Invalid Credentials')
if (!bcrypt.compareSync(password, user.password))
return reject('Invalid Credentials')
const token = jwt.sign({ user: { id: user.id, email: user.email } }, SECRET, { expiresIn: '1yr' })
user.token = token // add token property to user object which will be resolved
resolve(user)
})
.catch(error => reject(error))
})
}
}
}
})
module.exports = mutation
这是登录页面
import React from 'react'
import gql from 'graphql-tag'
import { graphql } from 'react-apollo'
class App extends React.Component {
constructor(props) {
super(props)
this.state = { email: 'edrren@gmail.com', password: 'password' }
}
onSubmit(e) {
e.preventDefault()
const { email, password } = this.state
console.log({ email, password })
this.props.mutate({
variables: { email, password }
}).then(() => console.log(this.props.data))
.catch(() => console.log("error"))
}
render() {
return (
<form onSubmit={this.onSubmit.bind(this)}>
<label>Email</label>
<input type="text" onChange={(e) => this.setState({ email: e.target.value})} value={this.state.email} />
<br/>
<label>Password</label>
<input type="password" onChange={(e) => this.setState({ password: e.target.value})} value={this.state.password} />
<button type="submit" >Login</button>
</form>
)
}
}
const mutation = gql`
mutation SignIn($email: String!, $password: String!){
signin(email: $email, password: $password) {
token
}
}
`;
export default graphql(mutation)(App)
我的提供者:
import React from 'react'
import ReactDOM from 'react-dom'
import ApolloClient, { createNetworkInterface } from 'apollo-client'
import { ApolloProvider } from 'react-apollo'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import App from './App'
import Header from './components/Header'
import Profile from './components/Profile'
const networkInterface = createNetworkInterface({
uri: 'http://localhost:8080/graphql'
});
const client = new ApolloClient({
networkInterface,
dataIdFromObject: o => o.id
})
const Root = () => {
return (
<ApolloProvider client={client}>
<Router>
<Switch>
<Route exact path="/" component={App} />
<Route path="/profile" component={Profile} />
</Switch>
</Router>
</ApolloProvider>
)
}
ReactDOM.render(<Root />, document.getElementById('root'));
答案 0 :(得分:1)
您应在create-react-app项目中使用代理。
在package.json
主对象中添加以下代理:
"/graphql": {
"target": "http://localhost:8080/",
"changeOrigin": true
}
它基本上是将您的请求从“ http://localhost:3000/graphql”代理到“ http://localhost:8080/graphql”。
还可以更改代码以使用相对的API网址。所以现在应该是:
uri: '/graphql'
这将对您的本地URL进行api调用,节点服务器会将其代理到上述目标。因此,这里没有交叉原点。