Silind-Software / direflow

🧩 Use the best of two worlds. Create fast, performant, native Web Components using React.
https://direflow.io
MIT License
501 stars 78 forks source link

webpack devServer proxy not working #218

Open tstankevicius opened 3 years ago

tstankevicius commented 3 years ago

Hello,

I am trying to overwrite webpack config in direflow-webpack.js file to add proxy setup:

function addCustomConfig(config) { config.devServer = { proxy: { '/rest/**': { target: 'http://localhost:1880', bypass: function (req, res, proxyOptions) { console.log('proxy...', req); } } }, } return config; }

module.exports = (config, env) => ({ ...addCustomConfig(webpackConfig(config, env)), // Add your own webpack config here (optional) });

However, it does not work.

If I setup same webpack config in another project (not direflow) it works fine!

What could be an issue?

Thank you.

yaya-bhavik commented 3 years ago

Hi @tstankevicius ,

In your config-overrides.js you can try using:

module.exports = {
  devServer: (configFunction) => {
      return (proxy, allowedHost) => {
          const config = configFunction(proxy, allowedHost);
      config.proxy = {
              context: ["/PATH_YOU_WANT_TO_PROXY"],
              target: "PROXY_TARGET",
              secure: false,
          };
          return config;
     }
  }
  ...
}
FrankKai commented 2 years ago

I can config devServer successfully by this way.

const { webpackConfig } = require("direflow-scripts");

module.exports = {
  webpack: (config, env) => {
    return {
      ...webpackConfig(config, env),
    };
  },
  devServer: function (configFunction) {
    return function (proxy, allowedHost) {
      // config here to overrides the deverServer's proxy config by react-app-rewired
      proxy = {
        "/api": {
          target: "https://foo.bar.com/",
          secure: false,
          changeOrigin: true,
        },
      };

      const config = configFunction(proxy, allowedHost);
      return config;
    };
  },
};

@tstankevicius Maybe you can have a try.

MaksimLavrenyuk commented 2 years ago

@tstankevicius

Since a cra configuration is used under the hood, you can do the following:

according to this article https://create-react-app.dev/docs/proxying-api-requests-in-development#configuring-the-proxy-manually

create a file: src/setupProxy.js

with roughly the following contents:

const { createProxyMiddleware } = require('http-proxy-middleware');
const path = require('path');
const ip = require('ip');
const fs = require('fs');
const paths = require('react-scripts/config/paths');

const sockPath = process.env.WDS_SOCKET_PATH || '/sockjs-node';
const isDefaultSockHost = !process.env.WDS_SOCKET_HOST;

function filter(pathname) {
    return pathname.match('^/ajax')
    || pathname.match('^/download');
}

function mayProxy(pathname) {
    const maybePublicPath = path.resolve(paths.appPublic, pathname.replace(new RegExp(`^${paths.publicUrlOrPath}`), ''));
    const isPublicFileRequest = fs.existsSync(maybePublicPath);
    const isWdsEndpointRequest = isDefaultSockHost && pathname.startsWith(sockPath);

    return !(isPublicFileRequest || isWdsEndpointRequest);
}

function onProxyError(proxy) {
    return (err, req, res) => {
        const host = req.headers && req.headers.host;
        console.log(
            `${'Proxy error:'
            } Could not proxy request ${
                req.url
            } from ${
                host
            } to ${
                proxy
            }.`,
        );

        console.log(
            `See https://nodejs.org/api/errors.html#errors_common_system_errors for more information (${
                err.code
            }).`,
        );

        if (res.writeHead && !res.headersSent) {
            res.writeHead(500);
        }
        res.end(
            `Proxy error: Could not proxy request ${
                req.url
            } from ${
                host
            } to ${
                proxy
            } (${
                err.code
            }).`,
        );
    };
}

module.exports = function (app) {
    const target = `http://${ip}`; // TODO: Specify where to proxy requests

    app.use(
        createProxyMiddleware(filter, {
            target,
            logLevel: 'silent',
            context(pathname, req) {
                return (
                    req.method !== 'GET'
                    || (mayProxy(pathname)
                        && req.headers.accept
                        && req.headers.accept.indexOf('text/html') === -1)
                );
            },
            onProxyReq: (proxyReq) => {
                if (proxyReq.getHeader('origin')) {
                    proxyReq.setHeader('origin', target);
                }
            },
            onError: onProxyError(target),
            secure: false,
            changeOrigin: true,
            ws: true,
            xfwd: true,
        }),
    );
};

In this way all POST requests from the /ajax, /download part will go to the proxy, and GET requests for static files, like pictures, will go to the /public folder of your dev server.