Socket.io - socket.io.js not available - javascript

I need to get a socket.io server running using python.
I followed this example:
https://tutorialedge.net/python/python-socket-io-tutorial/
With the final files looking as follows:
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<button onClick="sendMsg()">Hit Me</button>
<!--WORKS:-->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>-->
<!-- DOESNT WORK:-->
<script src="http://localhost:8080/socket.io/socket.io.js"></script>
<script>
const socket = io("http://localhost:8080");
function sendMsg() {
socket.emit("message", "HELLO WORLD");
}
socket.on("message", function(data) {
console.log(data);
});
</script>
</body>
</html>
server.py
from aiohttp import web
import socketio
sio = socketio.AsyncServer()
app = web.Application()
sio.attach(app)
async def index(request):
with open('index.html') as f:
return web.Response(text=f.read(), content_type='text/html')
#sio.on('message')
async def print_message(sid, message):
print("Socket ID-: " , sid)
print(message)
await sio.emit('message', message[::-1])
app.router.add_get('/', index)
if __name__ == '__main__':
web.run_app(app)
So much this is only copy paste and thus works fine, but I dont want to use the script from some online source. So I tried to modify the src of the script by commenting out the running version and replacing it by a version using a local socket.io.js.
As I did not find the script on my machine I found the following questions, that both did not help me solve my issue:
node-js-socket-io-socket-io-js-not-found
socket-io-not-being-served-by-node-js-server
No matter what I do I get the following error in my browser:
GET http://localhost:8080/node_modules/socket.io/socket.io.js net::ERR_ABORTED 404 (Not Found)
(index):18 Uncaught ReferenceError: io is not defined
at (index):18
(anonymous) # (index):18
From what I understood from the 2 linked threads, my server should provide the socket.io/socket.io.js when listen is called on the server.
Unfortunately this is not happening in my case.
I had socket.io installed via pip, I also tried npm install socket.io --save as suggested, this gives me a new folder 'node_modules', but modifying the src for my script to:
<script src="http://localhost:8080/node_modules/socket.io/socket.io.js"></script>
doesnt help either.
For some reason using the fie from cdnjs works just fine (see my index.html).
I would be very glad if someone could help me out with this.
Cheers
Chris

I've never worked with AIOHTTP (always worked with flask-socketio) so I did some research using the documentation. It turns out that like a lot of http server, AIOHTTP doesn't serve static files out of the box.
You will thus need to take care of it using the add_static method (doc here).
(Note that if you want to deploy this app for production it would be better practice to use an HTTP server like Apache or Nginx).
Just add this line under your routes declarations.
app.router.add_static('/static/', path='static/')
Now you need to create a static folder in the root of your project and put your socket.io.js file inside of it.
Make sure that the socket.io.js in the version 2.2 (same as the CDN version). You can get this file by downloading it directly from the CDN URL you were using or using npm -i -s socket.io-client#2.2. You can then find the socket.io.js file in node_modules/socket.io-client/dist.
You now just need to use <script src="/static/socket.io.js"></script> in your HTML to import socket.io.

Related

App works fine on 127.0.0.1, but not when accessed from another device

I managed to publish my app with nodejs and I am able to access it from devices in my network (mind you its going to be a local app only). It is an app that is used to control other hardware connected to my network.
The problem I am having right now is that, the app is working fine when I open it from 127.0.0.1:8081 from my local PC on which it is hosted, but if I attempt to open it from another device (or even from the hosting PC itself) by using the IP of the hosting PC 192.168.z.z:8081, the javascript files dont work and here is what I mean.
I have a config.js file which holds configuration data that my app needs to work, like IP of the device that I am controlling.
var config = {
URL: '192.168.0.2',
}
Then I have a Model.js file that has SetData and GetData which are both dependent on config.URL to execute their AJAX requests, however config.URL stays null, its hardcoded and still a null!
When I run the app and do config.URL in the console, I get null, even if I manually set it in the console config.URL = '192.168.0.2', and then try to invoke Model.SetData..... or Model.GetData... they still dont see it, they still are attempting to send a request to http://null/......
Here is my node code:
const express = require("express");
const app = express();
const port = 8081
app.use(express.static('public'))
app.use('/css', express.static(__dirname + '/public/css'));
app.use('/js', express.static(__dirname + '/public/js'));
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
I have tried with and without the app.use(/css and /js lines of code, no change
Here is how my JS is added to my html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Robot Stuff</title>
<script type="text/javascript" src="./js/jquery-3.5.0.js"></script>
<script type="text/javascript" src="./assets/scripts/main.js"></script>
<script type="text/javascript" src="./js/easy-numpad.js"></script>
<script type="text/javascript" src="./js/jquery-modal.js"></script>
<script type="text/javascript" src="./js/Model.js"></script>
<script type="text/javascript" src="./js/UI.js"></script>
<script type="text/javascript" src="./js/config.js"></script>
<link href="./css/main.css" rel="stylesheet" type="text/css" >
<link href="./css/easy-numpad.css" rel="stylesheet" type="text/css" >
Again, if I open that app from http://127.0.0.1:8081, or if I directly go and double-click on my index.html file, it all works just fine, but when I use the actual IP of the PC to access it remotely, then it breaks.
I dont want to overcomplicate it more than necessary, I am simply trying to use node explicitly to make the app available on my network, nothing more.
You need to allow cross origin policy in your server script.
That will enable you to accept request headers from your other devices also.
npm i cors --save
or alternatively you can follow this guide
Enable CORS in nodejs
Check with netstat -nlp if your server is working on 0.0.0.0 or 127.0.0.1. This could possibly be one of the issue for non-accessibility outside localhost.

Python Flask - Error: "Failed to load module script. Strict MIME type checking is enforced". Works on production, not on the local server

I have this html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link
rel="stylesheet"
href="../../../static/css/style.css"
type="text/css" />
<link
rel="stylesheet"
href="../../../static/css/user_header.css"
type="text/css" />
<!--suppress HtmlUnknownTarget -->
<link rel="shortcut icon" href="/favicon.png">
<script type="module" src="../../../static/js/node_connect.js" ></script> <-- Error
<script src="../../../static/lib/jquery.min.js"></script>
<script src="../../../static/lib/selfserve.js"></script>
</head>
The problematic bit is the node_connect.js file. When starting the Flask web tool locally (Python 3.7.2), the following error is given in the console when opening the page:
Failed to load module script: The server responded with a non-JavaScript MIME type of "text/plain".
Strict MIME type checking is enforced for module scripts per HTML spec.
Checking the headers:
Content-Type: text/plain; charset=utf-8
However, on production (when started through Gunicorn) it gives this:
Content-Type: application/javascript; charset=utf-8
I am guessing the web-server (Apache) serves them in the production case, but another thing is when testing other pages of this web tool, they all work all and load
the javascript files correctly (even if their content-type is text/plain). However the difference is, I noticed,
in the type.
This works in my case:
<script src="../../static/js/translator/library/materialize.js"></script>
Or this:
<script type="application/javascript" src="../../static/js/translator/library/materialize.js"></script>
Of course, I tried this for the problematic javascript file and received the following error (which means it now loaded):
Uncaught SyntaxError: Cannot use import statement outside a module
This, as far as I researched, basically means I need to set the type to module (however this makes the browser decline the .js file).
Could anyone please help me with this?
Problem is caused by how flask is guessing content type of each static file.
To do that flask imports mimetypes and calls mimetype, encoding = mimetypes.guess_type(download_name)
This module creates a database of known mime types from several sources and uses it to return mime type.
Under Linux and MacOS mimetypes.py looks inside files:
knownfiles = [
"/etc/mime.types",
"/etc/httpd/mime.types", # Mac OS X
"/etc/httpd/conf/mime.types", # Apache
"/etc/apache/mime.types", # Apache 1
"/etc/apache2/mime.types", # Apache 2
"/usr/local/etc/httpd/conf/mime.types",
"/usr/local/lib/netscape/mime.types",
"/usr/local/etc/httpd/conf/mime.types", # Apache 1.2
"/usr/local/etc/mime.types", # Apache 1.3
]
But under Windows it looks inside the registry:
with _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT, '') as hkcr:
for subkeyname in enum_types(hkcr):
try:
with _winreg.OpenKey(hkcr, subkeyname) as subkey:
# Only check file extensions
if not subkeyname.startswith("."):
continue
# raises OSError if no 'Content Type' value
mimetype, datatype = _winreg.QueryValueEx(
subkey, 'Content Type')
if datatype != _winreg.REG_SZ:
continue
self.add_type(mimetype, subkeyname, strict)
So to fix the problem of flask thinking that .js file was actually text/plain all that's necessary is to open regedit and adjust this registry key to application/javascript:
LK"I
Here's another trick without needing to change anything in registry:
put this before importing flask:
# fix windows registry stuff
import mimetypes
mimetypes.add_type('application/javascript', '.js')
mimetypes.add_type('text/css', '.css')
I'm having similar trouble around a .js export class which contains a vanilla js web component with an integrated template, itself having jinja2 escape sequences.
So, you may not get the same error with the first script statement using url_for as I did.
This appears to load as no error is raised by the templating engine...
<script type="module" src="{{ url_for('static', filename='interval_table.js') }}"></script>
... but Firefox console reports error: Loading module from “http://127.0.0.1:8000/static/interval_table.js” was blocked because of a disallowed MIME type (“application/json”).
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
I thought to get around the json error with the following, but it results in a jinja2 error, could not create endpoint:
<script type="module" src="{{ url_for('auth/interval_table.js') }}"></script>
This doesn't look like a CORS issue, and lots of digging has yielded no results. A new question may be necessary.
Instead of using type="module" you are able to use the defer attribute to achieve the same effect. Ie: The script will not be executed until the page finishes loading.
<script defer src="flong.js"></script>
I'm unsure if it helps, but I had a similar problem and it was solved by changing the module js extension from .js to .mjs. I don't think Flask can see the difference, unlike Node.js, without the different extensions.
I know this is an old thread, but I had a similar problem that was solved using the method I mentioned.
I didn't see this before I posted, but my thread is here:
Flask Server Not Sending JS Module Script
Harel Ashwal, Thank you so much. I was unable to load the external CSS file on flask because of a mimetype error, and this bit you shared fixed it for me:
# fix windows registry stuff
import mimetypes
mimetypes.add_type('application/javascript', '.js')
mimetypes.add_type('text/css', '.css')

nodejs config on subdirectory

I have a sub-domain and I publish my server.js on this directory. everything work fine. but I want to running my server.js inside a directory(because I want to run my react.js project on sub directory). for example:
web.example.com/sr
web is my subdomain and sr is my directory.
but my routes not worked at all:
web.example.com/sr/user/1
I got this error message:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /sr/user/1</pre>
</body>
</html>
Should I make any changes or is there any config to do this?
You can't do deployment-level configs to serve your react app to the subdir /sr. Every call to your.domain.com/sr/* will end up in your server and pass /sr/* to it (and not simply /*.
You'll have to code your server to serve your React app. If you bundle your react app to index.html and bundle.js, you'll have to write something like this (if you're using express, which you probably do):
app.get(/\/sr\/\.js/, (req, res) => res.sendFile(`${__dirname}/bundle.js`));
app.get(/\/sr\/*/, (req, res) => res.sendFile(`${__dirname}/index.html`));
If you're using react-router, you'll have to set it up too so as to take into account the leading /sr in your URL.

Python - flask server with angularjs front end, can't locate javascript or css files in index.html

I'm building a basic website that works with a python backend in Flask and an Angularjs frontend. I'm currently running into 404 issues when the index template is loading js files and css files
My directory structure is as follows:
-console/
---lib/
---css/
---bootstrap.css
---app.module.js
---index.html
-src/
---_init_.py
---api.py
My code for server api.py is as follows:
from flask import (Flask, jsonify, request, abort, render_template)
app = Flask(__name__, template_folder='../console')
#app.route('/', methods=['GET'])
def index():
return render_template('index.html')
This locates the index file with no issues, but when the index file tries to load the necessary css and js files, it fails to locate them. My current code for the basic index page is as follows:
<!DOCTYPE html>
<html ng-app="championsLeague" lang="en-US">
<head>
<title>Champions League</title>
<link rel="stylesheet" href="lib/css/bootstrap.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script src="app.module.js"></script>
</head>
<body>
<div ng-view>
<p>test</p>
</div>
</body>
</html>
When I start my server and navigate to my localhost, these errors appear in the console:
127.0.0.1/:7 GET http://127.0.0.1:5000/lib/css/bootstrap.css net::ERR_ABORTED 404 (NOT FOUND)
2127.0.0.1/:9 GET http://127.0.0.1:5000/app.module.js net::ERR_ABORTED 404 (NOT FOUND)
angular.js:88 Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.6.9/$injector/modulerr?p0=championsLeague&p1=Error%3A%20%5B%24injector%3Anomod%5D%20http%3A%2F%2Ferrors.angularjs.org%2F1.6.9%2F%24injector%2Fnomod%3Fp0%3DchampionsLeague%0A%20%20%20%20at%20https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A7%3A76%0A%20%20%20%20at%20https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A26%3A408%0A%20%20%20%20at%20b%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A25%3A439)%0A%20%20%20%20at%20https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A26%3A182%0A%20%20%20%20at%20https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A42%3A332%0A%20%20%20%20at%20r%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A8%3A7)%0A%20%20%20%20at%20g%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A42%3A180)%0A%20%20%20%20at%20gb%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A46%3A250)%0A%20%20%20%20at%20c%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A22%3A19)%0A%20%20%20%20at%20Uc%20(https%3A%2F%2Fajax.googleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.9%2Fangular.min.js%3A22%3A332)
at angular.js:88
at angular.js:5023
at r (angular.js:408)
at g (angular.js:4983)
at gb (angular.js:4900)
at c (angular.js:1955)
at Uc (angular.js:1976)
at we (angular.js:1861)
at angular.js:34354
at HTMLDocument.b (angular.js:3488)
I'm assuming the angular error is being caused by the app.module.js file not being found. Any ideas on what the issue could be? It's a requirement that I use flask as my server for this task, so other servers aren't an option.
Your js files are not templates, but static resources. Try this:
app = Flask(__name__,
template_folder='../console',
static_url_path='../console')
Another problem could be that your Flask app is in a subdirectory. It should be a the root of your application files.
More info: How to serve static files in Flask
Side note: personally I would use a slightly different structure. There are some conventions on how to structure a Flask app, as explained here:
http://flask.pocoo.org/docs/1.0/tutorial/layout/
http://flask.pocoo.org/docs/1.0/patterns/packages/
This was really helpful to me.

Using s3, node js

i'm trying to make a http request using 'request' for nodeJS. But it doesn't work.
It keeps writing 'require is not defined'. I have uploaded my index.html file to my s3 bucket, as well as my node_modules folder and my package.json file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.20/browser.min.js"></script>
<script data-main="js.config" src="js/r.js"></script>
</head>
<body>
<div id="app"></div>
<script type="text/babel">
const request = require('request');
</script>
This is how the index.html file looks like. It's not the whole file. But it's only the 'require' part is making trouble..
Let me know if you need any more info.
Hope someone can help.
You cannot use the request package on a client side script in that way, pointed out by many of the comments posted. That being said, if you want to have an App with a Node JS Backend for the serverside, you probably shouldn't be using AWS S3 anyways. There are many options for you if you plan to make a Backend App with Node JS:
AWS EC2 with Node JS
AWS Lambda
AWS Elastic Beanstalk
Some of these options, notably the EC2 and Lambda, have free tier options. Hopefully this helps you.

Categories

Resources