Websocket disconnects immediately after handshake (guacamole) - reactjs

Forgive bad formatting as it is my first question on here, and thanks in advance for reading!
I am currently writing a remote web application that utilises Apache Guacamole to allow RDP, VNC, and SSH connections. The components I am using are:
Django for backend server - API calls (database info) and Guacamole Websocket Transmissions;
I am using Pyguacamole with Django consumers to handle Guacamole Server communication;
Reactjs for frontend and proxy;
Nginx for reverse proxy;
All this is hosted on a Centos Stream 8 vm
Basically, my websocket has trouble communicating through a proxy. When I run the application without a proxy (firefox in centos running localhost:3000 directly), the guacamole connection works! Though this is where the application communicates directly with the Django server on port 8000. What I want is for the react application to proxy websocket communications to port 8000 for me, so my nginx proxy only has to deal with port 3000 for production.
Here is the code I have tried for my react proxy (src/setupProxy.js):
const { createProxyMiddleware } = require('http-proxy-middleware');
let proxy_location = '';
module.exports = function(app) {
app.use(createProxyMiddleware('/api', { target: 'http://localhost:8000', changeOrigin: true, logLevel: "debug" } ));
app.use( createProxyMiddleware('/ws', { target: 'ws://localhost:8000' + proxy_location, ws: true, changeOrigin: true, logLebel: "debug" } ));
};
I have also already tried with http://localhost:8000 for the ws target url. Also, the api proxy works, but I am unsure if the ws proxy works. After making a websocket request, the consumer does a guacamole handshake, but disconnects the websocket before it can send anything back.
Also, the HPM output shows that it does try upgrading to websocket, but the client disconnects immediately.
Do let me know if you require more information.

I managed to find what was wrong, it was a small mistake though I felt the need to update this thread.
Basically, in consumers I used accept() instead of websocket_accept(), receive() instead of websocket_receive(), and so on. Careless mistake on my part, but hope this helps someone out!

Related

Why can I call api port from React app using ip address, but not when I use "localhost"

React or axios do not seem to understand what local host is set to.
I'm serving a react client app on port 3000, and a react api server on port 3030.
I can call curl -s localhost:3030 from command line and get a good reply. But when I call using axios or fetch within my client app, I get net::ERR_CONNECTION_REFUSED.
For example, this works:
axios.post("http://xxx.xx.xxx.xxx:3030/authentication", {
This does not work (net::ERR_CONNECTION_REFUSED):
axios.post("http://localhost:3030/authentication", {
(Where localhost is the same machine with the xxx number above)
I don't think it's a CORS issue as I've tried setting the following headers in the server and sending them in post request.
"Access-Control-Allow-Origin"
"Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"
Also, my browser seems to report CORs errors explicitly (at least, it has previously)
If you are serving your client (React app) from a different port, and in 3030 it's only your backend, then it's probably CORS. You should configure your backend server to accept petitions from your app's domain.

create-react-app proxy request fails with 404 when backend is hosted on Azure

I am having a bit of trouble setting up my create-react-app application to proxy requests to my test hosting on Microsoft azure. I have set up the proxy in my app's package.json as follows:
"proxy":{
"/api/*":{
"target":"https://mytestbackend.azurewebsites.net",
"secure":false
}
}
I have set up an axios request to be sent to the backend server on azure. It is in a stand-alone .js which I call from one of my react application's events. It looks like this:
import axios from 'axios';
const login = async (username, password) => {
console.log("Username to send is:"+username);
console.log("password to send is:"+password);
let response = await axios.post('/api/user/login', {username:username,password:password});
console.log(response);
};
export {login};
The problem can't be in my react components, because those two console.log() call show that the values entered are being recieved. If I remove the "secure":false setting from package.json, request fails with Http Error: 500. But if I use the secure setting, it fails with a 404 page. Can someone please shed a little light on what am I doing wrong? Can I only use the proxy on "localhost"? The documentation suggests otherwise. Any help is greatly appreciated.
I have verified that CORS is enabled for the domain on which the dev server is running on the Azure Management Portal. And if I do the request by using the backend's URL directly (that is, not using the create-react-app proxy), it works. The problem must be something in the way the proxy is configured.
The response text for the HTTP Errpr 500 which happens when not using secure is :
Proxy error: Could not proxy request /api/user/login from localhost:3000 to https://mytestbackend.azurewebsites.net (undefined).
Additional info: I have also tested by running my Backend locally on my development machine. The error message occurs but the "undefined" in the parenthesis says "UNABLE_TO_VERIFY_LEAF_SIGNATURE". If using "secure: false, I can call the login endpoint successfully, but calls to other endpoints which require authentication fail because the cookie is not sent by axios.
Doing:
curl -v https://mytestbackend.azurewebsites.net/api/user/login
Has this output:
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection #0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
create-react-app use WebPackDevServer which uses https://github.com/chimurai/http-proxy-middleware#options
So you can use all the options from the same
Now one key header that is import in such cases of externally hosted server is host. This at times can issues if not correct, see below example
Websocket works on EC2 url but not on ElasticBeanstalk URL
Next is the cookies might be associated with localhost, i checked and they should go without any modification. But you might want to use the cookieDomainRewrite: "" option as well
So the final config I would use is below
"proxy":{
"/api/*":{
"target":"https://mytestbackend.azurewebsites.net",
"secure":false,
"headers": {
"host": "mytestbackend.azurewebsites.net"
},
"cookieDomainRewrite": ""
}
}
Also on your client you want to use the withCredentials:true
let userinfo =await axios.get('/api/secured/userinfo',{withCredentials:true});
Create react app http-proxy-middleware, and should support the full set of options.
Some things I would try:
The path to match may be /api/** instead of /api/* if you want to nest multiple levels deep (eg. for /api/user/login)
You may need to add changeOrigin: true if you're proxying to something remotely (not on localhost)
You will likely want to keep secure: false as you aren't running localhost with https.
So in total, I would try
"proxy":{
"/api/**": {
"target": "https://mytestbackend.azurewebsites.net",
"secure": false,
"changeOrigin": true
}
}
After days of trying unsuccessfully to do this, I finally found a setup that works. Proxy is configured like this:
"proxy": {
"/api/user/login": {
"target": "https://localhost:44396",
"logLevel": "debug",
"secure": false
},
"/api/secured/userinfo": {
"target": "https://localhost:44396",
"secure": false,
"logLevel":"debug",
"secure":false
}
Request to both endpoints on the client have withCredientials:true
try {
await axios({
method:'post',
url:'/api/user/login',
withCredentials:true,
data:
{username:username,password:password}}
);
let userinfo =await axios.get('/api/secured/userinfo',{withCredentials:true});
return userinfo;
As you can see, I've moved to testing on my local dev machine. For whatever reason, this setup refuses to work on the azure-hosted backend. I would have preferred that it work as I originally intended, but at least now I can continue with my project.

Invalid Host Header when ngrok tries to connect to React dev server

I'm trying to test my React application on a mobile device. I'm using ngrok to make my local server available to other devices and have gotten this working with a variety of other applications. However, when I try to connect ngrok to the React dev server, I get the error:
Invalid Host Header
I believe that React blocks all requests from another source by default. Any thoughts?
I'm encountering a similar issue and found two solutions that work as far as viewing the application directly in a browser
ngrok http 8080 --host-header="localhost:8080"
ngrok http --host-header=rewrite 8080
obviously, replace 8080 with whatever port you're running on
this solution still raises an error when I use this in an embedded page, that pulls the bundle.js from the react app. I think since it rewrites the header to localhost when this is embedded, it's looking to localhost, which the app is no longer running on
Option 1
If you do not need to use Authentication you can add configs to ngrok commands
ngrok http 9000 --host-header=rewrite
or
ngrok http 9000 --host-header="localhost:9000"
But in this case Authentication will not work on your website because ngrok rewriting headers and session is not valid for your ngrok domain
Option 2
If you are using webpack you can add the following configuration
devServer: {
disableHostCheck: true
}
In that case Authentication header will be valid for your ngrok domain
Don't know why but tried everything and it didn't work for me.
What finally worked for me is this:
ngrok http https://localhost:4200 -host-header="localhost:4200"
it might be useful for someone
If you use webpack devServer the simplest way is to set disableHostCheck, check webpack doc like this
devServer: {
contentBase: path.join(__dirname, './dist'),
compress: true,
host: 'localhost',
// host: '0.0.0.0',
port: 8080,
disableHostCheck: true //for ngrok
},
I used this set up in a react app that works. I created a config file named configstrp.js that contains the following:
module.exports = {
ngrok: {
// use the local frontend port to connect
enabled: process.env.NODE_ENV !== 'production',
port: process.env.PORT || 3000,
subdomain: process.env.NGROK_SUBDOMAIN,
authtoken: process.env.NGROK_AUTHTOKEN
}, }
Require the file in the server.
const configstrp = require('./config/configstrp.js');
const ngrok = configstrp.ngrok.enabled ? require('ngrok') : null;
and connect as such
if (ngrok) {
console.log('If nGronk')
ngrok.connect(
{
addr: configstrp.ngrok.port,
subdomain: configstrp.ngrok.subdomain,
authtoken: configstrp.ngrok.authtoken,
host_header:3000
},
(err, url) => {
if (err) {
} else {
}
}
);
}
Do not pass a subdomain if you do not have a custom domain
Windows, ngrok v3
ngrok http <url> --host-header=<host>:<port>

Bluemix Spring - Application must be listening on the right port

I'm trying to deploy a Jhipster application (Spring Boot + AngularJS) to Bluemix Tomcat. However I always get this error:
Error restarting application: Start app timeout
TIP: The application must be listening on the right port. Instead of hard coding the port, use the $PORT environment variable.
The complete error on Bluemix console is:
App instance exited with guid 1c76324f-57fb-4a00-b203-499519b4367c payload:
{
"cc_partition"=>"default",
"droplet"=>"1c76324f-57fb-4a00-b203-499519b4367c",
"version"=>"0103e173-b6d3-4daa-a291-b5792c16b69b",
"instance"=>"0c09506c30764b6c921cabb9a55d9e45",
"index"=>0,
"reason"=>"CRASHED",
"exit_status"=>255,
"exit_description"=>"failed to accept connections within health check timeout",
"crash_timestamp"=>1479341938
}
Instance (index 0) failed to start accepting connections
I've already tried to change the application-dev.yml config to
server:
port: ${VCAP_APP_PORT}
Or
server:
port: 80
However, I have not had any success. How can I pass the port variable to the Jhipster configuration?

Trying to connect to laravel backend with grunt-connect-proxy

I am finding myself pretty stuck using grunt-connect-proxy to make calls from my yeoman generated angular app running on port 9000 to my laravel backend which is running on port 8000. After following the instructions on the grunt-connect-proxy github I see the following message upon running grunt serve:
Running "configureProxies:server" (configureProxies) task
Proxy created for: /api to localhost:8000
I have my proxies set up here in connect.proxies directly following connect.options:
proxies: [{
context: '/api', // the context of the data service
host: 'localhost', // wherever the data service is running
port: 8000 // the port that the data service is running on
}],
In my controller then attempt to make a call to the api to test my proxy:
var Proxy = $resource('/api/v1/purchase');
Proxy.get(function(test){
console.log(test);
});
In the result of this in my console is a 500 error indicating that the call was still made to port 9000 rather than 8000:
http://localhost:9000/api/v1/purchase 500 (Internal Server Error)
Here is a link to a gist containing my full gruntfile: https://gist.github.com/JohnBueno/7d48027f739cc91e0b79
I have seen quite a few posts on this but so far none of them have been of much help to me.

Resources