POST-Request doesn't get forwarded via http-proxy - javascript

I am trying to build a reverse-proxy server where the url has an id (?id=1) and the proxy server redirects to port 8000 + id!
So it works when i go to the right port directly, but when I use the proxy the browser-tab loads endlessly.
It also works with GET-Request, but POST-Request don't work!
This is my reversed-proxy:
const express = require(`express`);
const proxy = require(`http-proxy`);
const ps = proxy.createProxyServer();
const app = express();
app.listen(8000);
app.all(`*`, (req, res) => {
if (req.query.id) {
try { const id = parseInt(req.query.id);
ps.web(req, res, { target: `${req.protocol}://${req.hostname}:${8000+id}` });
} catch (err) { res.redirect(redirectUrl); }
} else { res.redirect(redirectUrl); }
});
ps.on(`error`, (err, req, res) => {
res.redirect(redirectUrl);
});
This is my website running on port 8001:
app.get(`*`, (req, res) => {
res.render(`index`, {
link: `?id=1`,
name: `name`,
value: `value`,
text: `text`,
});
});
app.post(`*`, (req, res) => {
res.render(`index`, {
link: `?id=1`,
name: `name`,
value: `value`,
text: `text`,
});
});
And this is my html:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<form action={{link}} method="POST">
<button name={{name}} value={{value}}>
<h4> {{text}} </h4>
</button>
</form>
</body>
</html>
By the way i am also using express-handlebars so the {{}} in the html is for that!
ty for any ideas :)

Related

Error: Not Found The requested URL was not found on this server

I'm trying to send some html form data to a node js file using express. However as I submit the form I keep getting this error on the browser (I've tried different browsers and restarted the server every time):
Here's the code:
import mysql from 'mysql2';
import express from 'express';
import path from 'path';
let probes = [];
let measurements = [];
let to_country;
const app = express();
const __dirname = path.resolve();
app.use(express.urlencoded( {extended: true} ));
app.use(express.static(__dirname));
const con = mysql.createConnection({
host:'localhost',
user:'root',
password:'',
database:'probes&anchors'
});
con.connect((err)=>{
if(err){
console.log("Connection not proper");
}else{
console.log("connected");
}
});
app.post('/', async function(req,res){
to_country = req.body.to_country;
let sql = 'SELECT id FROM probes WHERE country=?';
await con.promise().query(sql, [req.body.from_country], (err, rows) => {
if (err) throw err;
probes.push(rows.id);
console.log('Probe id: ', rows.id);
})
console.log(probes);
con.end();
res.send("Loaded");
});
app.get('/', (req, res) => res.send('Hello World! From Node.js'));
app.listen(8000, () => console.log('Example app listening on port 8000!'));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fetch API Demo</title>
</head>
<body>
<form action="/" method="POST">
<label for="from_country">From:</label>
<select id="from_country" name="from_country">
<option>Country1</option>
<option value="AF">Afghanistan</option>
<option value="AX">Aland Islands</option>
</select>
<label for="to_country">To:</label>
<select id="to_country" name="to_country">
<option>Country2</option>
<option value="AF">Afghanistan</option>
</select>
<input type="submit" value="Latency?">
</form>
</body>
</html>
Both files are in the same directory.
I've modified Apache httpd.conf uncommenting two lines and adding the following line as shown here:
ProxyPass / http://localhost:8000
Can someone please help out? Any help is appreciated, thanks.
As I can see you are running apache server and node.js server on same port which requires some special configurations
you have to tell apache server explicitly to send (all or in some cases request coming from specific path) requests to node.js server (this technique is called reverse proxy technique)
this blog below might help you understand that
here
or here
EDIT
app.post('/', async function(req,res){
to_country = req.body.to_country;
let sql = 'SELECT id FROM probes WHERE country=?';
await con.promise().query(sql, [req.body.from_country], (err, rows) => {
if (err) throw err;
probes.push(rows.id);
console.log('Probe id: ', rows.id);
})
console.log(probes);
con.end();
res.send("Loaded");
});
can be simplified to ...
app.post('/', (req,res)=>{
to_country = req.body.to_country;
let sql = 'SELECT id FROM probes WHERE country=?';
con.query(sql, [req.body.from_country], (err, rows) => {
if (err) throw err;
else {
probes.push(rows.id);
console.log('Probe id: ', rows.id);
console.log(probes);
con.end();
res.send("Loaded");
}
})
});

Display express.js res.send() without overwriting current html

I am trying to create a calculator app using express.js to get request for an html file and a post request that takes the user's input and responds with the answer. However, I want to display my answer inside a html container without the page redirecting. Is there a way to achieve this with vanilla javascript?
index.html
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="stylesheet" href="styles.css" />
<link rel="shortcut icon" href="#" />
<title>Calculator</title>
</head>
<body>
<h1>Calculator App</h1>
<form action="/" method="post" class="ajax">
<label for="userInput">Enter Equation</label>
<input type="text" id="equation" name="equation" />
<button type="submit" id="btn_submit">Calculate</button>
</form>
<div class="container"></div>
</body>
</html>
app.js
const express = require('express');
const app = express();
port = 3000;
app.use(express.urlencoded({ extended : false }));
app.use(express.static('public'));
app.get('/', (req, res) => {
res.sendFile(__dirname + public);
});
app.post('/', (req, res) => {
let equation = req.body.equation;
console.log(equation);
let result = eval(equation);
res.status(200).send('Result is ' + result);
});
app.listen(port, ()=> {
console.log('Hosted on port: ' + port);
});
CalculatorApp
Evaluated Expression
You will need to write front end JavaScript code to make the ajax request instead of having the form action submit the request. The JavaScript will receive the response and can update the value on the HTML.
app.post('/', (req, res) => {
let equation = req.body.equation;
console.log(equation);
let result = eval(equation);
res.status(200).json({ value: `Result is ${result}` });
});
<script>
document.querySelector('form').addEventListener('submit',submitEquation);
function submitEquation(event){
event.preventDefault();
const input = document.querySelector('#equation');
const equation = input.value;
const clearInput = true;
if(clearInput){
input.textContent = '';
}
fetch(window.location.origin, {
method: 'post',
body: JSON.stringify({ equation })
})
.then(response => response.json())
.then(json => {
document.querySelector('.container').textContent = json.value;
})
}
</script>

How do I link a js file to index.html in a Node.js web server?

I'm new to Node.js and I'm just trying to create simple web server that can serve HTML, JS, and CSS files.
The server works and I can view index.html in localhost. But I can't seem to link the request.js to index.html. Here's my project structure:
--public
----js
------request.js
----index.html
--app.js
app.js
const http = require("http");
const fs = require('fs').promises;
const host = 'localhost';
const port = 8000;
const requestListener = function (req, res) {
fs.readFile(__dirname + "/public/index.html")
.then(contents => {
res.setHeader("Content-Type", "text/html");
res.writeHead(200); // success status code
res.end(contents);
})
.catch(err => {
res.writeHead(500);
res.end(err);
return;
});
};
const server = http.createServer(requestListener);
server.listen(port, host, function(error) {
if (error) {
console.log('Something went wrong', error)
}
else {
console.log(`Server is running on http://${host}:${port}`);
}
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="/js/request.js" defer></script>
<title>Water Web Dev</title>
<body>
</body>
</html>
</head>
request.js
const axios = require('axios');
const getBtn = document.getElementById('get-btn');
const getData = () => {
axios.get('https://reqres.in/api/unknown')
.then(function (response) {
// success
console.log(response);
})
.catch(function (error) {
// error
console.log(error);
})
.then(function () {
// always executed
});
}
getBtn.addEventListener('click', getData)
You should server your css & js files as static files.

Intercepting a real data response

I have a problem with data stubbing in Cypress 6. I am trying to implement the exchange of real data from the server to custom data. I read the docs and came to the conclusion that
describe("test", () => {
it("intercept", () => {
cy.intercept("http://localhost:3000/spoons", (req) => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log(res.body);
return body;
});
});
});
});
will be the solution, however... body in networking for request http://localhost:3000/spoons returns to me
{
"sizes": [
"huge",
"small"
],
"colors": [
"yello",
"brown"
],
"build": {
"back": true,
"front": true
}
}
but in the console.log as it shows what res.body has, it gets an empty console.log as if it had nothing res.body in it.
Edit #1
About internal "server" I made just simple express server with a website which make fetch request to have easy another request in "Networking". It was made just as a battlefield to train intercept and other stuff. There is the only endpoint to this /spoons
server.js
const express = require("express");
const app = express();
const port = 3000;
const path = require("path");
const obj = {
sizes: ["huge", "small"],
colors: ["yello", "brown"],
build: {
back: true,
front: true,
},
};
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
app.get("/spoons", (req, res) => {
res.json(obj);
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body></body>
<script>
console.log(fetch("http://localhost:3000/spoons"));
</script>
</html>
It works for intercepting external network requests,
/// <reference types="#cypress/fiddle" />
const test = {
html: `
<script>
fetch('https://jsonplaceholder.typicode.com/todos/1')
</script>
`,
test: `
cy.intercept('https://jsonplaceholder.typicode.com/todos/1', req => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log(res.body);
return body;
});
})
`
}
it('test', () => {
cy.runExample(test)
})
This logs
{
completed: false,
id: 1,
newProperty: "new", // added by intercept
title: "delectus aut autem",
userId: 1
}
Can you explain the api server and client ports in more detail?
I set up your server, and found it works ok.
The only thing I changed was to add a no-store header to the server response (stops browser seeing status code '304').
Without it every second refresh of the Cypress test cy.intercept() did not trigger. That may actually be fixable in the test by adding a full route matcher to cy.intercept() instead of just the url.
app.use((req, res, next) => {
res.set('Cache-Control', 'no-store')
next()
})
app.get("/", (req, res) => {...
I also modified the script in the app to console.log in .then(), otherwise you just get the promise object.
<script>
fetch('http://localhost:3000/spoons')
.then(res => res.json())
.then(res => console.log('app', res))
</script>
This is the spec I used.
it('test', () => {
cy.intercept('http://localhost:3000/spoons', req => {
req.reply((res) => {
let { body } = res;
body.newProperty = "new";
console.log('intercept', res.body);
return body;
});
})
cy.visit('../app/intercept-mod-response-local-server-2.html')
})

Posting data from a html form to SQL does not post

I have a node.js web app, an SQL server, and I am working locally in visual studio code then syncing to azure.
I have a simple form on my home page which when I click post, should send the data to a table in my SQL database. However nothing is happening at all. I am redirected to the user page, and I get no errors, but I also get nothing in the console log, or anything posted to the table.
Here is what I have:
app.js
var express = require('express');
var app = express();
var mysql = require("mysql");
var bodyParser = require('body-parser');
var config = {
host: '',
user: '',
password: '',
database: '',
port: 3306,
ssl: true
};
var connection = new mysql.createConnection(config);
app.use('/node_modules', express.static(__dirname + '/node_modules'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.get('/Template/views/home.html',function(req,res){
res.sendFile('home.html',{'root': __dirname + '/views'});
})
app.get('/Template/views/about.html',function(req,res){
res.sendFile('about.html',{'root': __dirname + '/views'});
})
app.get('/Template/views/user.html',function(req,res){
res.sendFile('user.html',{'root':__dirname + '/views'})
})
app.post('/Template/views/user.html', function(req, res){
var fName = req.body.first_name;
connection.query("INSERT INTO `Persons` (name) SET ?", fName.toString(), function(err, result) { function(err, result) {
if(err) throw err;
console.log("1 record inserted");
});
res.send('user.html',{'root':__dirname + '/views'})
});
app.listen(process.env.PORT);
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>Template</title>
<link href="../node_modules/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
</head>
<body>
<form action="/Template/views/user.html" name="formA">
First Name: <input type="text" name="first_name"> <br>
Last Name: <input type="text" name="last_name"> <br>
<input type="submit" value="submit">
</form>
</body>
</html>
Can anyone see what I am doing wrong here?
Try connection to the connection after defining it:
connection.connect();
then execute the query and finally close the connection with:
connection.end();
Add method='post' on your form.
<form action="/Template/views/user.html" method='post' name="formA">
And change the serverside code
app.get('/Template/views/user.html',function(req,res){
res.sendFile('user.html',{'root':__dirname + '/views'})
})
To:
app.post('/Template/views/user.html',function(req,res){
res.sendFile('user.html',{'root':__dirname + '/views'})
})
and start db connection like below.
var connection = new mysql.createConnection(config);
connection.connect();

Categories

Resources