how to call expressjs endpoint from static html file in vercel - javascript

i have a very simple app with 1 /api/index.js server and 1 index.html file at the root.
index.js has a route app.get("/api/mystuff", () => {...})
index.html calls pings this route from a <script> with:
const result = await fetch("/api/mystuff")
all of this works locally, but when deployed to Vercel i get hit with a 404 from my request. the endpoint it's hitting is https://myvercelapp.vercel.app/api/mystuff and i'm getting a The page could not be found NOT_FOUND error. I don't know how to get this working, can someone steer me in the right direction?
thanks!

Based on the used tags I'm understanding you are using express with node.js.
Without seeing any of your code, I am guessing either your vercel.json isn't setup correctly (the guide explains this) or your index.js isn't setup correctly.
Vercel Guide on using Express
In that case, Vercel has a great guide on Using Express.js with Vercel.
In vercel's guide they have a section addressing using Standalone Express.
In this guide they use an index.js inside of an api folder.
The index.js file:
const app = require('express')();
const { v4 } = require('uuid');
app.get('/api', (req, res) => {
const path = `/api/item/${v4()}`;
res.setHeader('Content-Type', 'text/html');
res.setHeader('Cache-Control', 's-max-age=1, stale-while-revalidate');
res.end(`Hello! Go to item: ${path}`);
});
app.get('/api/item/:slug', (req, res) => {
const { slug } = req.params;
res.end(`Item: ${slug}`);
});
module.exports = app;
and the vercel.json which is what makes the whole project work.
{
"rewrites": [{ "source": "/api/(.*)", "destination": "/api" }]
}
And finally, Adding a Public Directory which may explain more on how you can properly use Vercel with Express.
The Problem
The reason I assume that it's the vercel.json is the problem is due it working locally and not on Vercel. A good way to test this locally is using vercel dev.
Working Example
I've created a public example which may help you. Please check https://github.com/Crispy-Cream/vercel-with-express for the source code example
and the public website https://vercel-with-express.vercel.app/api

Related

Using socket io on webserver

I used socket.io on localhost:3000 for several tests. Now i tried getting it to work online for an hour but I’m making no progress.
server.js
const http = require('http').createServer()
const io = require('socket.io')(http)
io.on('connection' (socket) => {
socket.on('start_session', (data) => {
console.log('hey there')
})
})
app.js
const socket = io('http://localhost:3000')
socket.emit('start_session', session_id)
The server.js is running on a server, it’s in the same folder as my index.html and app.js, on my own device it’s working perfectly fine
What am I missing? Can this even be archived with using localhost? I searched for alternatives but it’s always localhost.
Thanks in advance
The path to the socket.io.js file is also not working, how do I find that out? Tried the whereis command, but that didn’t help.

Heroku custom DNS API route issue in Node.js

I have a custom domain set up in Heroku which works fine.
I can access my site using both my app name and custom domain.
I can access a route using my standard Heroku URL, but not using the custom domain.
For example:
Works:
https://{myappname}.herokuapp.com
https://{myappname}.herokuapp.com/callback
https://{customdomain}.com
Does not work:
https://{customdomain}.com/callback
Server config:
const express = require("express");
const path = require("path");;
const callback = require("./callback");
const app = express();
// Body parser middleware
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// Serve static assets if in production
if (process.env.NODE_ENV === "production") {
app.use("/callback", callback);
// Set static folder
app.use(express.static("client/build"));
app.get("*", (req, res) => {
res.sendFile(path.resolve(__dirname, "client", "build", "index.html"));
});
}
// Init server/port
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server running on port ${port}`));
I know its too late but I am writing for those who face this issue in the future.
I was also facing this issue and solved through this.
Was Not Working
https://{customdomain}.com/callback
This Worked for me.
https://www.{customdomain}.com/callback
I figured this out, it was pretty simple and I feel stupid, however I will answer this here in case anyone ever has the same issue.
Problem:
I had a React route/component called Callback. This React component was calling a Node.js route also called Callback, which processes information then redirects to a new React route/component.
Simple fix was to change my React route/component to callbackPage, leaving my Node.js route as Callback.
So in summary, I had a webpage URL with the same name as a server API route. when I visited this page, instead of the page being rendered, the API route was run and basically did nothing and timed out. I'm still confused as to why it worked with my app URL but not my custom domain.

Issues connecting to my Node.js and MongoDB backend using a React and axios front end

I am struggling currently when making a call using Axios to my backend, I currently have a user register page and I want to send the user data to the backend, everything seems to be set up correctly but I get these errors inside of my google chrome.
Here is the code from my React Register.js that breaks my program and causes this error.
onSubmit(e) {
e.preventDefault();
const newUser = {
name: this.state.name,
email: this.state.email,
password: this.state.password,
password2: this.state.password2
};
axios.post('api/users/register', newUser) //EDIT : Line 35, where the error is
.then(res => console.log(res.data))
.catch(err => console.log(err));
}
The onSubmit is connected to a button at the bottom of the website and all the code there is %100 fine. One issue that might be hurting me here is that my server is on localhost5000 while my front end is running on localhost3000 on my computer. I don't know how to fix this or what to do next, I've looked everywhere and this small issue is incredibyly frustrating.
Any help , pointers or general advice would be greatly appreciated as this seems like an extremely trivial error. Thanks in advance for any help.
Also look into the create-react-app docs to setup a proxy. CRA Proxy Docs
I like to setup my proxies in package.json (for the react client). I usually add the following, and all my routes start with api, to save on typing.
// somewhere in package.json
"proxy": {
"/api/*": {
"target": "http://localhost:5000"
}
}
If I was still getting a CORS error I would install the npm package cors (on the express app) and set that up as a middleware before my route handlers. Cors Docs
const app = express()
app.use(cors())
That is the most basic config, but you can specifically whitelist your front end if you want to.
app.use(cors({ origin: 'http://localhost:3000' }))
You can also add cors to any one route if you want to, in the usual express manner.
app.post('/api/user/register', cors(), (req,res) => {
// route handler
})
This is how I setup my apps using CRA and Express for development. Then when things go to production I don't have to change the api routes on the front end. That is the inherent problem with writing out the whole path ei: 'http://localhost:5000/api/users/register' - that is not going to work when the app goes to production say on Heroku, or wherever, and localhost:5000 is no longer the backend url. You would have to go back to all api routes and adjust them or insert ternaries for process.env.NODE_ENV, which is more work.
In this case all you need on the front end is axios.post('/api/users/register', newUser)
The proxy will take care of the rest in development.
Now when you publish site, if you chose to make it one single express app that serves your build statically, you just put the api route handlers above a catch all for serving the index.html. Anyways, this is a little beyond your question, just trying to give you an idea of one approach that will work down the line a little easier.
The issue is that when you run axios.post('api/users/register', newUser) it is running simply against http://localhost. You stated that the backend is running at http://localhost:5000 so you would want to run an absolute address to hit the backend properly. The code would turn into axios.post('http://localhost:5000/api/users/register', newUser) to hit the backend APIs.
Make sure you have "proxy": "http://localhost:5000" in your Client/React Package.json

Nuxt application using Express won't allow POST routes to be hit externally of application

Background
I have a NUXT application that renders vue templates as you would expect. I have a need to hit some Express routes in the application from external applications client side.
I can hit GET routes from external applications but POST requests fail with a error 404.
Example
Express
This works
router.get('/test/get', (req, res, next) => {
res.json({ message: "Global PDF Generator is configured correctly", status: "operational" })
});
This fails with 404
router.post('/test/post', (req, res, next) => {
res.json({ message: "Global PDF Generator is configured correctly", status: "operational" })
});
Inside of the Nuxt application and within any of the vue components I can hit the POST routes like this,
fetch('api/v1/pdf', { method: 'POST' }
But if we try to do something like this it fails,
fetch('localhost:3000/api/v1/pdf', { method: 'POST' }
The second example is important because obvioulsy that is how I would have to hit an end point in this application from an outside application.
What I can not figure out is why the GET requests work and do not get a 404 while the POST requests continue to get a 404 from external applications.
Question
How can I create an externally accessible Express POST end point in my NUXT application so that it will be directly accessible from an external source?
Not as an answer but just so I can format things and demonstrate that something else must be going on. This minimal example works fine for me.
vue init nuxt-community/express-template sample_post
cd sample_post
npm install
Modify api/routes/users.js adding a post route:
router.post('/test', function(req, res, next) {
res.json(message: 'hello');
});
Start up the service:
npm run dev
Verify it returns a post from an external request successfully:
curl -X POST http://localhost:3000/api/test
{"message":"hello"}
So something else must be going on somewhere.
This is because when the NuxtJs app on production it sees only page routes not server route. You should use NuxtJs serverMiddleware. You can find it here from NuxtJs API

Using a node.js app with HTML

My goal is this: JS but server-side. My solution, the obvious, node.js. I've used node.js quiet a bit. Mainly for an application, not a web server. The only reason I need to do server-side JS is that I need to use a library that connects to the Discord API. So I have a little test .js file with my node.js in it. It just prints text if it works. Basic. What I need it to do is whenever someone goes to https://example.com/something, it runs the node.js script and if the script ends up with printing "hello", then https://example.com/something will say "hello".
I've done some research on this, I've found ways to deploy a node.js app, which I know how to do. I can't really find anything that I'm looking for though.
You can use express to run a webserver on nodejs
Install express by running "npm install express" in your project folder through command prompt
Create a app.js file with the following code
var express = require('express'); // load the express library
var app = express(); // create an instance of express
var child_process = require('child_process'); //load the child_process module
app.get("/something", function(req, res) { // Setup a router which listens to the site http://localhost/something
child_process.fork("./yourCodeFile.js"); // Launch your code file
});
app.listen(80);
Run node app.js to listen to web connections
Then you put your code into the yourCodeFile.js which has to be be in the same folder as the app.js file, even better you could just write all your code in the app.js code as long as you keep it inside the function inside app.get
You should take a look at cloud-based lambda functions and platforms like AWS Lambda, which run a script in response to an HTTP request. They are relatively new and the architecture used to support this is being called "serverless", which is a simple term, albeit a bit of a misnomer. There are various tools out there to help you build these systems, such as the similarly named Serverless framework, though you can typically still use more traditional server frameworks that you are probably more comfortable with. Either way, you are not responsible for managing any server, including starting it or stopping it.
In terms of constructing a response that you are happy with, you can of course respond with any arbitrary string you want. See the AWS example of a Node.js handler.
exports.myHandler = function(event, context, callback) {
callback(null, "Hello, world!");
}
Lambda functions can also return binary data and work well with static storage systems like Amazon S3. For example, the function can be run in response to the creation of static assets.
Your code should look like this:
const http = require('http');
const url = require('url');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
const pathName =url.parse(req.url).pathname;
if (pathName == '/something') {
res.end('Hello World\n');
} else {
res.end('Please visit /something \n');
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
You should run your file with node youfile.js And when you do curl http://127.0.0.1:3000 you will see
Please visit /something
But when you do curl http://127.0.0.1:3000/something you will see
Hello World

Categories

Resources