Search code examples
javascriptfetchkoa

My webserver sends 404 when i make the request through react app, but works fine when I access it directly through chrome or postman


My web server is working fine when I call it through chrome. However when I am using fetch or axiom in my react-app to call the same url, it returns 404 Not Found. The react-app also sends a options request to same url which returns status 200. I have even set this header to allow the origin.

app.use(async (ctx, next) => {
    var origin = ctx.headers.origin;
    ctx.set({
        'Access-Control-Allow-Headers': 'authorization,Content-Type,refresh',
        'Access-Control-Allow-Methods': "GET,HEAD,POST,PUT,DELETE",
        'Access-Control-Allow-Origin': '*',
        'Connection': 'keep-alive',
        'Access-Control-Allow-Credentials': true
    });
    await next();
    console.log('______________')
  });

require('./routes')(app); //2

my ./routes.js file contain

//router.post('/signin' , signinController.signin);
router.get('/signin' , signinController.signin);

can you please tell me what I am missing here. My axios call

axios.get('http://localhost:3002/signin')
              .then(function (response) {
                console.log(response);
              })
              .catch(function (error) {
                console.log(error);
              });

Solution

  • Alright I tried your code out and it works for me if I use app.use(router.allowedMethods()) middleware to pass preflights, OR declare separate option-routes for each route; Or instead of using router.get() there is router.all('/signin', ...) which will also catch options-requests.

    This is my complete server code:

    const app = new Koa();
    
    const router = new Router();
    
    router.get('/signin' , (ctx, next) => {
      ctx.body = '{"status":"hello"}';
    });
    
    // Adding a options-route works (instead of router.allowedMethods())
    router.options('/signin' , (ctx, next) => {
      ctx.body = '';
    });
    
    app.use(async (ctx, next) => {
      var origin = ctx.headers.origin;
      ctx.set({
        'Access-Control-Allow-Headers': 'authorization,Content-Type,refresh',
        'Access-Control-Allow-Methods': "GET,HEAD,POST,PUT,DELETE",
        'Access-Control-Allow-Origin': '*',
        'Connection': 'keep-alive',
        'Access-Control-Allow-Credentials': true
      });
      await next();
      console.log('______________')
    });
    
    app.use(router.routes());
    // app.use(router.allowedMethods()); // This works instead of separate option-routes.
    app.use((ctx, next) => {
      console.log('here');
      next();
    });
    
    
    app.listen(9787);
    

    And this is my call:

    axios.defaults.headers.common['Authorization'] = "sometoken";
    axios.get('http://localhost:9787/signin').then(response =>{
      console.log(response); // {data: {…}, status: 200, ... }
    });
    

    (I had to add the header or the CORS won't trigger.)

    I've tried setting various origin and headers and it does obey your middleware. But I did notice that if you choose to use allowedMethods(), that will override your Access-Control-Allow-Methods (and make it useless).