Hey all. I’m building a small, stupid react app and trying to deploy it on Netlify. I wrote a small Express proxy server to help keep some github API access tokens private during production. I have found some examples of using serverless-http
to wrap my express app so that it will work on Netlify. There are only 2 routes on the express server so it’s not that hard to re-write but dammit I am committed to getting this to work now.
I’m using React and Webpack. I will post relevant code:
[build]
command = "npm install && npm run build-for-netlify"
functions = "functions"
publish = "dist"
// package.json
"scripts": {
"build": "NODE_ENV='production' webpack",
"build-for-windows": "SET NODE_ENV='production' && webpack",
"build-for-netlify": "NODE_ENV='production' webpack && npm run build:lambda",
"start": "concurrently \"webpack-dev-server\" \"npm run start:lambda\"",
"server": "nodemon server/index.js",
"start:lambda": "NODE_ENV='production' netlify-lambda serve ./server",
"build:lambda": "netlify-lambda build ./server"
},
"proxy": "http://localhost:3000"
The code related to the proxy server I had:
//webpack.config.js
mode: process.env.NODE_ENV === 'production'
? 'production'
: 'development',
devServer: {
proxy: {
'/api': {
target: 'http://localhost:3000',
pathRewrite: { '^/api': '.netlify/functions/index' }
}
},
historyApiFallback: true
},
The code that the UI is using to trigger the post requests which go through the proxy server:
function getProfile(username) {
return fetch('/api/profile', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ 'username': username })
})
.then(res => {
return res.json()
})
.then(profile => {
if (profile.message) {
throw new Error(getErrorMsg(profile.message, username))
}
return profile
})
}
function getRepos(username) {
return fetch('/api/repos', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ 'username': username })
})
.then(res => {
return res.json()
})
.then(repos => {
if (repos.message) {
throw new Error(getErrorMsg(repos.message, username))
}
return repos
})
}
And finally, the Express API:
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const serverless = require('serverless-http');
require('dotenv').config();
// Initialize app
const app = express();
const router = express.Router();
const port = process.env.PORT || 3000;
// Configuration
app.use(bodyParser.json({ type: 'application/json' }));
const routerBasePath = (process.env.NODE_ENV === 'development')
? `/index`
: `/.netlify/functions/index`
app.use(routerBasePath, router);
console.warn('Node environment: ', process.env.NODE_ENV)
// Constants
const id = process.env.GITHUB_CLIENT_ID;
const secret = process.env.GITHUB_CLIENT_SECRET;
const params = `?client_id=${id}&client_secret=${secret}`
// Route(s)
router.post('/profile', (req, res) => {
const { username } = req.body;
const endpoint = `https://api.github.com/users/${username}${params}`;
axios({
method: 'get',
url: endpoint,
})
.then(response => {
res.status(200)
res.send(response.data)
})
.catch(error => {
console.log('Error with Axios profile res: ', error)
res.send({ error })
})
return
})
router.post('/repos', (req, res) => {
const { username } = req.body;
const endpoint = `https://api.github.com/users/${username}/repos${params}&per_page=100`;
axios({
method: 'get',
url: endpoint,
})
.then(response => {
res.status(200)
res.send(response.data)
})
.catch(error => {
console.log('Error with Axios repos res: ', error)
res.send({ error })
})
return
})
// DJ, spin that sh*t:
app.listen(port, () => console.log(`App is running on port ${port}`));
process.on('SIGINT', () => {
console.log(`Process on port ${port} successfully terminated.`);
process.exit();
})
// Serverless
// app.use('/.netlify/functions/index', router);
module.exports.handler = serverless(app);
To be clear: When I run the npm start
command (which fires up the React frontend and lambda server OR the node server in another branch…) and manually set the environment to either production
or development
the app works locally. The pathRewrite
in the webpack.config
can be observed working taking calls to api/route
and rewriting to correct path. I can also hit the routes from Postman in either configuration and see that my request makes it to the github API. I have a feeling that this has something to do with my configuration.
I apologize if this is a somewhat naive question. I’ve read through the documentation, including perusing some of the docs on github regarding proxy setups being used for local development. I’ve been staring at this for a few days, deploying sh*t and just hoping that something sticks. Also, the project is at: