Auth POST 请求与 Axios 定向到错误的 http 地址并返回 404

时间:2021-05-25 18:06:18

标签: javascript reactjs api post axios

我在验证我的应用程序时遇到问题。当使用注册组件中表单中的信息向客户端发送 POST 请求时,我在控制台中收到以下错误:

POST http://localhost:3000/api/auth/signup 404 (Not Found)

我知道将我的 POST 请求定向到的正确地址是“localhost:5005”,这是我的服务器运行的地方。但是,当我不在客户端的“services/auth.js”中对此进行硬编码时,它默认为“localhost:3000”并引发错误。但是我无法在定义的地方/需要更改它的地方锻炼。

如果我将 POST 请求的目标硬编码为“http://localhost:5005/api/auth/signup”,则代码会运行并且新用户条目会在数据库中生成。

仅供参考 下面的代码抛出 404 错误,如上。

提前致谢!如果我遗漏了任何重要信息,请告诉我。

client/src/services/auth.js

```
import axios from 'axios';

const signup = (email, password, firstname, lastname) => {
  return axios
    .post('/api/auth/signup', { email, password, firstname, lastname})
    .then(response => {
      // console.log(response)
      return response.data;
    })
    .catch(err => {
      // console.log(err)
      return err.response.data;
    });
};

const login = (email, password) => {
  return axios
    .post('/api/auth/login', { email, password })
    .then(response => {
      return response.data;
    })
    .catch(err => {
      return err.response.data;
    });
};

const logout = () => {
  return axios
    .delete('/api/auth/logout')
    .then(response => {
      return response.data;
    })
    .catch(err => {
      return err.response.data;
    });
};

export { signup, login, logout };
```

client/src/components/Signup.js

```
    import { React, useState } from 'react'
import { signup } from '../services/auth'

function useInput(initialValue){
  const [value, setValue] = useState(initialValue);
  
  function handleChange(event){
    setValue(event.target.value);
  }

  return [value,handleChange]
}

export default function Signup(props) {

  const [email, setEmail] = useInput('');
  const [password, setPassword] = useInput('');
  const [firstname, setFirstname] = useInput('');
  const [lastname, setLastname] = useInput('');
  const [message, setMessage] = useState('');
  const [user, setUser] = useState('')

  const handleSubmit = event => {
    event.preventDefault();
    console.log('email:', email, 'password:', password, 'firstname:', firstname, 'lastname:', lastname)
    signup(email, password, firstname, lastname).then(data => {
      if (data.message) {
        // console.log(data.message);
        setMessage(data.message);
        // setEmail('');
        // setPassword('');
        // setFirstname('');
        // setLastname('')
      } else {
        setUser(data)
        console.log(user)
        props.history.push('/dashboard');
      }
    });
  };

  return (
    <div>
    <h1>User signup</h1>
    <div class='signupForm'>
    <form onSubmit={handleSubmit}>

        <label>Email</label>
        <input 
          type='text'
          name='email'
          value={email}
          onChange={setEmail}
          id='email'
        />

        <label>Password</label>
        <input 
          type='password'
          name='password'
          value={password}
          onChange={setPassword}
          id='password'
        />

        <label>Firstname</label>
        <input 
          type='text'
          name='firstname'
          value={firstname}
          onChange={setFirstname}
          id='firstname'
        />

        <label>Lastname</label>
        <input 
          type='text'
          name='lastname'
          value={lastname}
          onChange={setLastname}
          id='lastname'
        />
        
{message && (
<alert variant='danger'>{message}</alert>
)}

<button type='submit'>Signup</button>
</form>
    </div>
    </div>
  )
}

```

(服务器)路由/auth-routes.js

```
const express = require('express');
const passport = require('passport');
const bcrypt = require('bcrypt');
const User = require('../models/User.model');

const router = express.Router();

// Signup route
router.post('/signup', (req, res) => {
  const {
    email, password, firstname, lastname,
  } = req.body;

  if (!password || password.length < 8) {
    return res
      .status(400)
      .json({ message: 'Your password must be 8 char. min.' });
  }
  if (!email) {
    return res.status(400).json({ message: 'Your email cannot be empty' });
  }

  // check if username exists in database -> show message
  User.findOne({ email })
    .then((found) => {
      if (found) {
        return res
          .status(400)
          .json({ message: 'This email is already taken' });
      }

      // hash the password, create the user and send the user to the client
      const salt = bcrypt.genSaltSync();
      const hash = bcrypt.hashSync(password, salt);

      return User.create({
        email, password: hash, firstname, lastname,
      }).then(
        (dbUser) => {
          // login with passport:
          req.login(dbUser, (err) => {
            if (err) {
              return res
                .status(500)
                .json({ message: 'Error while attempting to login' });
            }
            return res.status(200).json(dbUser);
          });
        },
      );
    })
    .catch((err) => {
      res.json(err);
    });
});

// Login route
router.post('/login', (req, res) => {
  passport.authenticate('local', (err, user) => {
    if (err) {
      return res.status(500).json({ message: 'Error while authenticating' });
    }
    if (!user) {
      return res.status(400).json({ message: 'Wrong credentials' });
    }
    req.login(user, (error) => {
      if (error) {
        return res
          .status(500)
          .json({ message: 'Error while attempting to login' });
      }
      return res.json(user);
    });
  })(req, res);
});

// Delete user route
router.delete('/logout', (req, res) => {
  req.logout();
  res.json({ message: 'Successful logout' });
});

// returns the logged in user
router.get('/loggedin', (req, res) => {
  res.json(req.user);
});

// when login is successful, retrieve user info
router.get('/login/success', (req, res) => {
  if (req.user) {
    res.json({
      success: true,
      message: 'user has successfully authenticated',
      user: req.user,
      cookies: req.cookies,
    });
  }
});

// auth with google
router.get(
  '/google',
  passport.authenticate('google', {
    scope: [
      'https://www.googleapis.com/auth/userinfo.profile',
      'https://www.googleapis.com/auth/userinfo.email',
    ],
  }),
);
router.get(
  '/google/callback',
  passport.authenticate('google', {
    successRedirect: '/private-page',
    // eslint-disable-next-line max-len
    failureRedirect: '/login', // here you would redirect to the login page using traditional login approach
  }),
);

module.exports = router;
```

app.js

const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
const GoogleStrategy = require('passport-google-oauth20').Strategy;
const bcrypt = require('bcrypt');

const cors = require('cors');

// ℹ️ Gets access to environment variables/settings
// https://www.npmjs.com/package/dotenv
require('dotenv/config');

// ℹ️ Connects to the database
require('./db');

// Handles http requests (express is node js framework)
// https://www.npmjs.com/package/express

const express = require('express');

const app = express();

// ℹ️ This function is getting exported from the config folder. It runs most middlewares
require('./config')(app);

app.use(
  cors({
    // this could be multiple domains/origins, but we will allow just our React app
    origin: ['http://localhost:3000'],
  }),
);

// session configuration

const session = require('express-session');

// session store using mongo
const MongoStore = require('connect-mongo')(session);

const mongoose = require('./db/index');

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    cookie: { maxAge: 1000 * 60 * 60 * 24 },
    saveUninitialized: false,
    // Forces the session to be saved back to the session store,
    // even if the session was never modified during the request.
    resave: true,
    store: new MongoStore({
      // mongooseConnection: mongoose.connection,
      url: 'mongodb://localhost:27017',
    }),
  }),
);
// end of session configuration

// passport configuration

const User = require('./models/User.model');

// we serialize only the `_id` field of the user to keep the information stored minimum
passport.serializeUser((user, done) => {
  // eslint-disable-next-line no-underscore-dangle
  done(null, user._id);
});

// when we need the information for the user, the deserializeUser function is called with
// the id that we previously serialized to fetch the user from the database
passport.deserializeUser((id, done) => {
  User.findById(id)
    .then((dbUser) => {
      done(null, dbUser);
    })
    .catch((err) => {
      done(err);
    });
});

passport.use(
  new GoogleStrategy(
    {
      clientID: process.env.GOOGLE_CLIENTID,
      clientSecret: process.env.GOOGLE_CLIENTSECRET,
      callbackURL: '/auth/google/callback',
    },
    (accessToken, refreshToken, profile, done) => {
      // to see the structure of the data in received response:
      console.log('Google account details:', profile);

      User.findOne({ googleID: profile.id })
        .then((user) => {
          if (user) {
            done(null, user);
            return;
          }

          User.create({ googleID: profile.id })
            .then((newUser) => {
              done(null, newUser);
            })
            .catch((err) => done(err)); // closes User.create()
        })
        .catch((err) => done(err)); // closes User.findOne()
    },
  ),
  new LocalStrategy((username, password, done) => {
    // login
    User.findOne({ username })
      .then((userFromDB) => {
        if (userFromDB === null) {
          // there is no user with this username
          done(null, false, { message: 'Wrong Credentials' });
        } else if (!bcrypt.compareSync(password, userFromDB.password)) {
          // the password is not matching
          done(null, false, { message: 'Wrong Credentials' });
        } else {
          // the userFromDB should now be logged in
          done(null, userFromDB);
        }
      })
      .catch((err) => {
        console.log(err);
      });
  }),

);

app.use(passport.initialize());
app.use(passport.session());

// end of passport

// ? Start handling routes here
// Contrary to the views version, all routes are controled from the routes/index.js
const index = require('./routes');

app.use('/api', index);

const auth = require('./routes/auth-routes');

app.use('/api/auth', auth);

// Allows access to the API from different domains/origins BEFORE session
app.use(
  cors({
    // this could be multiple domains/origins, but we will allow just our React app
    origin: ['http://localhost:3000'],
  }),
);

// ? Start handling routes here
// Contrary to the views version, all routes are controled from the routes/index.js

// This could be a conflict with line 104, so I commented it out. We can reinstate
// const allRoutes = require('./routes');
// app.use('/api', allRoutes);

const admin = require('./routes/admin');

app.use('/api', admin);

// ❗ To handle errors. Routes that don't exist or errors that you handle in specific routes
require('./error-handling')(app);

module.exports = app;

2 个答案:

答案 0 :(得分:1)

<块引用>

但我无法在定义的地方/需要更改的地方锻炼。

那是您的前端运行的地方,并且您正在使用相对网址。你可能只想做:

axios.defaults.baseURL = 'http://localhost:5005';

答案 1 :(得分:0)

写作时

return axios
    .post('/api/auth/signup'

这意味着您的端点与前端运行在同一台服务器上,即 localhost:3000 在您的情况下,但在您的情况下,您在前端服务器上没有端点。