simpletut / Universal-React-Apollo-Registration

Open Source Universal User Registration System – NodeJS React Apollo GraphQL JWT MongoDB

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is it possible to reverse proxy this application?

marksmithonline opened this issue · comments

Hello,

I'm not sure if this is something you can help with as I don't know if this is a webconfig issue or more nginx orientated - but I am trying to dockerise this application and reverse proxy it using nginx.

Do you know if this application can be reversed proxied?

When I try to set a location in my nginx config as an entry point for the applciation, none of the assets are loaded on the relative path I set and the links on the page all point to the root of my nginx server and not the location I set in my nginx.conf file...

I have reversed proxied another node application (express based) and this seems to work without issue so I am not sure if there is something in the architecture of this app that will prevent me from reverse proxying it...

I am trying to make this app available on the following url

http://domain-name/memberdemo

I am reverse proxying an express base site to http://domain-name and that works fine...

The entries in my nginx.conf file are as follows:

    location / {
    proxy_pass http://192.168.1.104:3000/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;                       
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;  
    }

below is the location block I am trying to host your app on

    location /memberdemo/ {
    proxy_pass http://192.168.1.66:3000/;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;                       
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 

    }

The first location block reverse proxies to a host on my lan running an express based application and works fine as all assets are loaded and the links work as needed...

The second location block reverse proxies to the universal react app running on another machine on my lan - if I enter http://192.168.1.66:3000 in my browser the app loads as expected with all assets loaded and the links work as needed from my client machine...

If I try to access it through the reverse proxy no assets are loaded and all the links point to the location of the first 'location' block as shown above so I get page not found when I click on them...

e.g.

When I go to http://domain-name/memberdemo

I see the universal app load its default page but no assets are loaded and I see 'not found' errors in the browser console - if I hover or click on a link on the un-styled page the links point to the root of my nginx server so I get a not found error if clicked...

I know this may not be an issues with your application but I have been trying for days to find a way to make this work so I thought I might ask you if you know of any issues that may be effecting this... or reasons why this application can not be reverse proxyed...

My webconfig looks like this:

{
"siteURL": "http://192.168.1.66:3000",
"environment": "production"
}

Thanks for any help or pointers you can give...

As I understand it, your problem appears to be around relative file paths. A simpler solution maybe to change the way images are handled in the application.

Presently we are using relative file paths. Your solution would be to configure webpack to handle images and the file paths.

To do this, follow the instructions below.

Please note: I have not tested this code, so it may need tweaking.

  1. Firstly, we need to update webpack to use the 'file-loader' module.

In 'webpack.server.js'

{
test: /\.(png|jpg|gif)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: '[name].[ext]',
                publicPath: '/assets/webpack-images/',
                emitFile: false
            }
        }
    ]
}

In 'webpack.client.js'

{
    test: /\.(png|jpg|gif)$/,
    use: [
        {
            loader: 'file-loader',
            options: {
                name: 'assets/webpack-images/[name].[ext]',
            }
        }
    ]
}
  1. Update your components wherever images are being used.

Import the graphic/image

import MyImage from './path/to/image';

Render the image

<img src={MyImage} />

Thank you for the above info, I'm going to try this out and will let you know how I get on.

I do really appreciate your help with this!

Cheers

Thanks for pointing me in the right direction - I looked into the Webpack.server and webpack.client files and can see that they contain the following entries in relation to js/css which are assets that aren't being loaded as well as the images:

Webpack.server

    module: {
        rules: [
            {
                test: /\.js?$/,
                loader: 'babel-loader',
                exclude: '/node_modules/',
                options: {
                    presets: [
                        'react', 'stage-0', ['env', {
                            target: { browsers: ['last 2 versions']}
                        }]
                    ]
                } 
            }
        ]
    },

Webpack.client

    module: {
        rules: [
            {
                test: /\.js?$/,
                loader: 'babel-loader',
                exclude: '/node_modules/',
                options: {
                    presets: [
                        'react', 'stage-0', ['env', {
                            target: { browsers: ['last 2 versions']}
                        }]
                    ]
                } 
            },
            {
                test: /\.scss$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name].min.css',
                            outputPath: 'assets/css/'
                        }
                    },
                    {
                        loader: 'extract-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            minimize: true,
                            url: true,
                            root: webConfig.siteURL
                        }
                    },
                    {
                        loader: 'sass-loader'
                    }
                ]
            }
        ]
    },

I have not had a lot of time to investigate this as yet but I think I will need to apply the same 'file-loader' module to the js/css assets in order to make this work - e.g. replace the babel module with 'file-loader'?

Also, do I need to add the entries you suggested with regard to images to these files as I can't see any existing entries in relation to images in these files?

Sorry for the newbie question - your reply really helped me understand that it wasn't a nginx problem and that I need to learn more about Webpack and how it loads files, so thank you...

Please can you confirm if I need to both add the 'file-loader' code for the images you supplied above to these two files and also change the js/css entries to 'file-loader' from 'babel'?

Thanks

No, you should not change any of the existing code.

The rules array .contains two objects, however they are configured to handle different file types (JS and SCSS).

You need to add the code I previously forwarded to handle image file types (.png/.jpg/.gif)

test: /\.(png|jpg|gif)$/,

Note: The code I previously sent for the server and client bundles are different. On the server bundle we need to handle the image file types to prevent our build throwing errors. However we only emit the files within our client webpack configuration for the obvious reasons.

I've done some digging and think I may have found an additional issue or at least something I will also need to look into...

It seems that part of the problem is also displayed when I try to run the app using ssl through nginx - e.g if I reverse proxy the app at the root of the nginx server using just http it works fine - but if I then try and use https - I get the issue where no js/css is loaded and I see the below error...

(node:3109) UnhandledPromiseRejectionWarning: Error: Network error: request to https://192.168.1.66:3000/graphql failed, reason: socket hang up
    at new ApolloError (/home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:124:32)
    at /home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:1248:45
    at /home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:1680:21
    at Array.forEach (<anonymous>)
    at /home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:1679:22
    at Map.forEach (<anonymous>)
    at QueryManager.broadcastQueries (/home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:1672:26)
    at /home/ec2-user/Universal-React-Apollo-Registration/node_modules/apollo-client/bundle.umd.js:1175:35
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:189:7)
(node:3109) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:3109) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

If I then remove ssl from the nginx config it works fine...

If I then try to do a secondary reverse proxy e.g to http://192.168.1.66/memberdemo just using http - the front page loads showing the menu bar with all its assets but the main page to the right of the screen shows 404 Not Found... and if I click on a link on the menu bar, it initially loads the page but if I try to refresh the page I get a full page 404 error...

So it seems that I will need to do what you have suggested above and also add in a https module for apollo - I found the below link on the apollo website which talks about adding ssl support so I think I will have to learn how to do both what you have suggested in terms of overcoming the secondary reverse proxy issue and also adding the ability for the apollo server to work over ssl...

I'm not sure if you will want to close this issue as strictly speaking its not an issue with your code as such.

And it will also be a good learning experience for me to work out how to over come this... I'd be happy to update this issue with what I do to resolve this - but alternatively, if you want to close the issue, I'm fine with that... and if you have any comments, suggestions or pointers I'd be keen to hear them...

https://www.apollographql.com/docs/apollo-server/essentials/server.html#ssl

Thanks!

Before I close this issue, I would like to explain the process of Dockerizing this application.

I recommend users have some prior experience with Docker before attempting to proceed.

Although I will not be providing the exact code to complete this process, I will attempt to summarise the steps involved to run our app within a Docker Container.

Webpack

Firstly you will need to follow my instructions above to update Webpack and the way we handle images within the project.

Link

Docker & Docker Compose

You will need to manually configure Docker & Docker Compose in the root of this project.

Whilst I will not provide the exact code for doing this, each user case will likely be different.

I suggest you create the following files:

  • Dockerfile
  • docker-compose.yml
  • .dockerignore

You should configuring MongoDB in your 'docker-compose' file using the official MongoDB image.

Please note: If you proceed with MongoDB, don't forget to enable authentication. You can easily do so by adding the following environment variables to your 'docker-compose' file.

environment:
      - MONGO_INITDB_ROOT_USERNAME=<user>
      - MONGO_INITDB_ROOT_PASSWORD=<pass>

Connecting to MongoDB running within your Docker Container

Assuming you have configured Docker to run MongoDB. You will need to update 'server.js' to connect to your database.

Your connection string should look something like this:

mongodb://dbUser:mypass@mongo:27017/someDB

Please note: you will need to login to your mongo shell and create a database/assign a user to that database (referenced on the connection string ^).

CSS/JS files

We are referencing some CSS and JS files in the initial html thrown down by the server.

For localhost env, please update the paths to important files

Open: src/helpers/renderer.js and change:

<link href="${webConfig.siteURL}/assets/css/styles.min.css"...

To:

<link href="http://localhost/assets/css/styles.min.css"...

Please note: You may need to update these references upon deployment.

Most important files:

  • styles.min.css
  • client_bundle.js
  • favicon

Please note: I have not tested any of the above snippets, some please be aware that they may require some tweaking.

Good luck!