I am trying to do something similar to the API, using nuxtjs + express.
in server/index.js file I create
app.get ('/ test', (req, res) => {
res.send ({method: 'GET'})
})
when contacting localhost:3000/test
HTML markup is returned, why is this happening?
When trying to make a request through POSTMAN, HTML is also returned
index.js
const express = require('express')
const consola = require('consola')
const { Nuxt, Builder } = require('nuxt')
const app = express()
// Import and Set Nuxt.js options
const config = require('../nuxt.config.js')
config.dev = process.env.NODE_ENV !== 'production'
async function start() {
// Init Nuxt.js
const nuxt = new Nuxt(config)
const { host, port } = nuxt.options.server
await nuxt.ready()
// Build only in dev mode
if (config.dev) {
const builder = new Builder(nuxt)
await builder.build()
}
app.get('/test', (req, res) => {
res.send({ method: 'GET' })
})
// Give nuxt middleware to express
app.use(nuxt.render)
// Listen the server
app.listen(port, host)
consola.ready({
message: `Server has been started on port: http://${host}:${port}`,
badge: true
})
}
start()
Related
I want a server side generated page in next.js to be served as a file. So I wanted to grab the rendered content inside a custom server.js file:
const express = require('express');
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
app.prepare().then(() => {
const server = express();
server.get('/', async (req, res) => {
const nextResponse = await app.renderToHTML(req, res, '/', req.query);
console.log('nextResponse', nextResponse);
console.log('res.body', res.body);
});
server.get('*', (req, res) => {
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
Oddly enough every console.log returns null or undefined.
I thought that renderToHTML would just return the rendered HTML string. Is there any way to do this?
This one is a bit tricky but achievable.
The idea is to override res.end function in order to catch rendered HTML there. The tricky part is that Next.js gzips and streams response using the compression library that's overriding res.end somewhere in the middle of the handle function.
The compression library is initialized using the handleCompression function of the Next.js's Server object (which is accessible using the app.getServer()), so that function needs to get overridden too.
So it should be looking something like this:
const { parse } = require('url');
const next = require('next');
const express = require('express');
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const port = process.env.PORT || 3000;
const handle = app.getRequestHandler();
app.prepare()
.then(() => {
const server = express();
server.get('*', async (req, res) => {
const parsedUrl = parse(req.url, true);
const nextServer = await app.getServer();
const _handleCompression = nodeServer.handleCompression.bind(nodeServer);
nextServer.handleCompression = (req, res) => {
_handleCompression(req, res);
const _resEnd = res.end.bind(res)
res.end = function (payload) {
console.log('Rendered HTML: ', payload);
return _resEnd(payload);
}
}
return handle(req, res, parsedUrl);
});
server.listen(port, err => {
if (err) throw err;
console.log('> Ready on http://localhost:' + port);
});
});
After you get rendered HTML you don't have to use the saved _resEnd function. Feel free to manipulate, serve as a file, or whatever you want with it.
[HPM] Error occurred while trying to proxy request /api/users/ from localhost:3000 to http://localhost:5000 (ECONNRESET)
I get this error while trying to do axios.post request,
i'm running my app with concurrently (server with express and client side using react) ,
as described here I defined client/src/setupProxy.js file:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api',
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
my server.js:
const express = require('express');
const connectDB = require('./config/db');
const app = express();
//connect Database
connectDB();
//Init MiddleWare -allows to get the data from req.body
app.use(express.json());
//Define routes
app.use("/api/users", require("./routes/api/users"));
app.use("/api/auth", require("./routes/api/auth"));
app.use("/api/profile", require("./routes/api/profile"));
app.use("/api/posts", require("./routes/api/posts"));
app.get('/', (req, res) => res.send('API is running'));
//Port - first look for an environment port (when connect to heroku)
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`server listening on port: ${PORT}`);
})
and my post request in the client side:
export const register = ({ name, email, password}) => async dispatch => {
const config = {
headers: {
'Content-Type': 'application/json'
}
}
const body = JSON.stringify({name, email, password});
try {
const res = await axios.post('/api/users/', body, config);
console.log({res});
dispatch({
type: REGISTER_SUCCESS,
payload: res.data
})
console.log('passed dispatch')
} catch (e) {
const errors = e.response.data.errors;
if(errors) {
errors.forEach(e => dispatch(setAlert(e.msg, 'danger')));
}
dispatch({
type: REGISTER_FAIL
})
}
}
any idea what I miss ?
EDIT:
I've noticed that my server using type ipv6 and client on ipv4, maybe that's the problem ? how I make them run on the same ipv ?
I have a react application running on localhost:3000 and in that I am making a GET request in my code using axios to http://localhost:5000/fblogin.
const Login = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};
But I'm getting a error having status (failed)net::ERR_FAILED initiator xhr177.
How can I resolve it
You'll need to 1. implement express cors, and 2. add a proxy from react to your server
[1] https://expressjs.com/en/resources/middleware/cors.html
npm install cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
[2] https://create-react-app.dev/docs/proxying-api-requests-in-development/
In your react's package.json, add
"proxy": "http://localhost:5000",
Note that this will work in development only.
For production, you'll need to serve the client from the server.
See https://create-react-app.dev/docs/deployment
const express = require('express');
const cors = require('cors')
const path = require('path');
const app = express();
app.use(cors());
/**
* add your API routes here to avoid them getting overtaken
* by the statically served client
*/
/**
* add this as the last handler
*/
if (process.env.NODE_ENV === "production") {
const pathToClientBuild = path.join(__dirname, '..', 'path', 'to', 'client', 'build');
app.use(express.static(pathToClientBuild));
/**
* experiment with '/' and '/*' and see what works best for you
*/
app.get('/*', function (req, res) {
res.sendFile(path.join(pathToClientBuild, 'index.html'));
});
}
app.listen(5000);
(and to make it work, you'll need to build the client first, and then serve the server with NODE_ENV=production node ./server.js).
const Login 9636634272 = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};
const Login = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};
I am trying to test my app with supertest. When I run nodemon index.js, and go to the address to make a GET request, I get a working response with correct data.
Supertest is called with app.js, which it's contents are down below as well.
But when I do that, response body returns []. Why might that be? I'm new to all this, so if anything must be added, please say so.
index.js:
const app = require('./app') // the actual Express app
const http = require('http')
const config = require('./utils/config')
const server = http.createServer(app)
server.listen(config.PORT, () => {
console.log('Server running')
})
app.js:
const config = require('./utils/config')
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
const cors = require('cors')
const blogsRouter = require('./controllers/blogs')
const middleware = require('./utils/middleware')
const mongoose = require('mongoose')
console.log('connecting to', config.MONGODB_URI)
mongoose.connect(config.MONGODB_URI, { useNewUrlParser: true })
.then(() => {
console.log('connected to MongoDB')
})
.catch((error) => {
console.log('error connection to MongoDB:', error.message)
})
app.use(cors())
app.use(express.static('build'))
app.use(bodyParser.json())
app.use(middleware.requestLogger)
app.use('/api/blogs', blogsRouter)
app.use(middleware.unknownEndpoint)
app.use(middleware.errorHandler)
module.exports = app
Here is the part that I run test:
blog_api.test.js:
const mongoose = require('mongoose')
const supertest = require('supertest')
const app = require('../app')
const api = supertest(app)
test('blogs are returned as json', async () => {
await api
.get('/api/blogs')
.expect(200)
.expect('Content-Type', /application\/json/)
})
test('there are one blog', async () => {
const response = await api.get('/api/blogs')
//response doesn't return anything yet works fine in server?
expect(response.body.length).toBe(1)
})
afterAll(() => {
mongoose.connection.close()
})
first test works fine but second one fails because response.body returns [].
Just for good measure, here is the code where I actually define what the GET request should do:
in my controller:
blogsRouter.get('/', (request, response) => {
Blog.find({}).then(notes => {
let resJson = response.json(notes.map(note => note.toJSON()))
return resJson
})
})
I'm learning the MERN stack and creating the typical beginner "Todo" App. When I make an axios call such as axios.post("http://localhost:4000/todos/add", newTodo) it posts fine, but when I try axios.post("/todos/add", newTodo) it doesn't.
The call obviously only works locally - how do I fix this/what am I doing wrong?
Here is todos.js file located in /routes/api folder:
const todoRouter = require("express").Router();
let Todo = require('../../models/todo');
todoRouter.route("/").get(function (req,res){
Todo.find(function(err, todos){
if (err){
console.log (err)
} else {
res.json(todos)
}
});
});
todoRouter.route("/:id").get(function(req,res){
let id = req.params.id
Todo.findById(id, function(err,todo){
if (err) {
console.log(err)
} else {
res.json(todo)
}
});
});
todoRouter.route("/add").post(function(req,res){
let todo = new Todo(req.body)
todo.save()
.then(function (todo){
res.status(200).json({"todo": "todo added successfully"})
})
.catch(function (err){
res.status(400).json("adding new todo failed")
})
})
todoRouter.route('/update/:id').post(function(req, res) {
Todo.findById(req.params.id, function(err, todo) {
if (!todo)
res.status(404).send("data is not found");
else
todo.todo_description = req.body.todo_description;
todo.todo_responsible = req.body.todo_responsible;
todo.todo_priority = req.body.todo_priority;
todo.todo_completed = req.body.todo_completed;
todo.save().then(todo => {
res.json('Todo updated!');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
module.exports = todoRouter;
Here is my index.js located in /routes/api folder:
const router = require("express").Router();
const todoRoutes = require("./todos");
// Todo routes
router.use("/todos", todoRoutes);
module.exports = router;
Here is index.js located in the /routes folder:
const path = require("path");
const router = require("express").Router();
const todoRoutes = require("./api");
// API Routes
router.use(todoRoutes);
// If no API routes are hit, send the React app
router.use(function(req, res) {
res.sendFile(path.join(__dirname, "../client/build/index.html"));
});
module.exports = router;
Here is my server.js file:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose')
const PORT = process.env.PORT || 4000;
const routes = require('./routes')
// Define middleware here
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use(bodyParser.json());
// Serve up static assets (usually on heroku)
if (process.env.NODE_ENV === "production") {
app.use(express.static("client/build"));
}
// Define API Routes
app.use(routes)
// Send every other request to the React app
// Define any API routes before this runs
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
//Connect to mongoose
mongoose.connect(process.env.MONGODB_URI || "mongodb://127.0.0.1:27017/todos", { useNewUrlParser: true });
const connection = mongoose.connection
connection.once("open", function () {
console.log("MongoDB database connection established successfully")
})
app.listen(PORT, function () {
console.log("Server is running on Port: " + PORT);
});
Just set "proxy": "http://localhost:4000" property in your package.json and all your /something requests will be directed towars your backend without having to specify the base url
you can set the baseUrl for axios to http://localhost:4000 and then relative paths should work. https://github.com/axios/axios#creating-an-instance