Node.js as a custom (streaming) upload handler for Django - python

I want to build an upload-centric app using Django. One way to do this is with nginx's upload module (nonblocking) but it has its problems. Node.js is supposed to be a good candidate for this type of application. But how can I make node.js act as an upload_handler() for Django? I'm not sure where to look for examples?

Okay I'm not like an expert on the subject or anything, but the way I think I understand it, nginx is a proxy that runs in front of the webserver that serves your django app, right?
You could build a simple node.js server that does the same - listen on port 80, wait until the request is completely sent to the server, and then forward it to the webserver that serves the Django app. If your problem is that the webservers threads are being used up by long running uploads, then I think this would solve that problem.
Here's some code - just off the top of my head
var http = require('http');
var server = http.createServer(function (req, res) {
var headers = req.headers;
var url = req.url;
var method = req.method;
var body = '';
req.addListener('data', function(chunk) {
body += chunk;
});
req.addListener('end', function() {
// at this point the request is completely uploaded (including files)
// so it can be forwarded to the django webserver
var dj_client = http.createClient(8000, 'localhost');
var dj_req = dj_client.request(method, url, headers);
dj_req.addListener('response', function (dj_res) {
// here the response have been received from the django server
// so we can return that to the waiting client
res.writeHead(dj_res.status, dj_res.headers);
dj_res.addListener('data', res.write);
dj_res.addListener('end', res.close);
});
// send the request to the django webserver
dj_req.write(body);
dj_req.close();
});
});
server.listen(80);

Make node.js write the file to disk and proxy the upload POST to Django along with a '_node_file' value so your Django view knows where to get the file.

Related

Using a single websocket for a multiple clients

I've never used before websockets neither web workers and everything around that. Obviously, I'm lost and I don't know how to make it properly.
I've learned how to make a websocket and leave it working in a server port successfully. As well, load a web worker (but this one can't refresh the website straight).
When a user is connected, everything is working fine. Websocket is sending messages to the user and the user is refreshing their website.
The problem is when I want to use it with many other users (different tabs or browsers to simulate different users). Only works with next user is connected with websocket, is not working anymore with the other users.
I share a diagram just to make it simple to understand what I want to do.
Another point is. Which language do I have to use to get this, both for the server and for the users? Python, NodeJs, Php (those are the only I know how to use).
SOLVED!
Just I generate a number assigned to each client (can be different device between each other) and I send the random number generated by server to each connection!
Before "connection" you shoul add:
const WS = require('ws');
const WS_PORT = 8081
const express = require('express');
const app = express();
const PORT = 3000;
app.listen(PORT, () => console.log(`Server listening , go to http://localhost:${PORT}`));
app.use(express.static('public'));
const wss = new WS.Server({ port: WS_PORT })
const wsSelected = new Set();
// Creating connection using websocket
const interval = setInterval(() => {
const randomNumber = Math.floor(Math.random() * 100);
//Sending same number to each client
wsSelected.forEach(ws =>
ws.send(randomNumber)
)
}, 2000);
After "connection" you should add:
wss.on("connection", ws => {
console.log("New client!");
//This line you should add
wsSelected.add(ws);
...

Create Api for MySQL database and connect to mobile App using Python

I developed a simple app using React Native and I am trying to connect to a database. I looked online and I found out that many companies like Facebook, Instagram, YouTube and many more are using MySQL + Python.
I want to use Python to manipulate (insert/delete and update) the database but in order to do that I need to create an API. Using NodeJS + Express I would do something like this:
import express from 'express';
import mysql from 'mysql';
const app = express();
app.listen(port, ()=> {
console.log('server started');
// do stuff
});
//database
const database = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'password12345',
database : 'database_app'
});
//create
app.get('/create', (req, res)=> {
// check error
// create query
});
//delete
app.get('/delete', (req, res)=> {
// check error
// delete query
});
//update
app.get('/update', (req, res)=> {
// check error
// update query
});
How do I do the same with Python? and how do I connect it to my app?
You'll need something like Django or Flask to serve up the data for it to be consumed by the front end.
In Flask, you make a blueprint, then use that blueprint to serve routes, which is analogous to what you were doing in your Node.js code.
app.get('/update', (req, res)=> {
// check error
// update query
});
The Flask version would look like:
users_blueprint = Blueprint('users', __name__, template_folder='./templates')
#users_blueprint.route('/users/', methods={'GET'})
def getUsers():
return jsonify({
'status': 'success',
'message': 'test response msg',
'data' : mydata
})
You could use code like this after registering the Users Blueprint and creating a Model.
First of all I don't have a strong python background but I know that people use flask for building REST APIs and the way you can connect the API to your app is via URL, you just need to start your server and in the client side of your RN App fetch the data from the URL (in dev mode, probably through localhost:$PORT) where your REST API is mounted.

Can I generate a REST service from a GraphQL schema?

I'd like to build a Django app with both a GraphQL endpoint and a REST API. Maintaining both separately would be too much of a pain; I'm looking for a good way to only maintain the GraphQL service and have the REST endpoints generated automagically.
Does anyone know about a good way to do this?
I know there are ways to build a GraphQL server on top of REST endpoints, but I'd rather have it the other way around, as the REST API requirement might go away in the future.
If you don't mind using Node.js, there is a library that does that (graphql2rest): https://github.com/sisense/graphql2rest
You can use it to automatically generate a REST API from your existing GraphQL schema.
"GraphQL2REST is a Node.js library that reads your GraphQL schema and a user-provided manifest file and automatically generates an Express router with fully RESTful HTTP routes — a full-fledged REST API."
If your only problem is not having a dedicated client on the client side and you can live with long urls your graphql endpoint is your RESTlike API. Disclaimer: Untested code for educational purposes only ;)
Read all posts:
GET /api/posts
=>
GET /graphql?query={posts{id title body}}
Create a post
POST /api/posts
{ "title": "Hello", "body": "world" }
=>
POST /graphql?query=mutation m($title:String!,$body:String!){createPost(title:$title,body:$body){id title body}
{ "variables": { "title": "Hello", "body": "world" } }
Your code can then work in a REST like manner (imagine redux actions calling REST APIs).
If you want something more in terms of a server, you can easily reverse what you discribed here:
I know there are ways to build a GraphQL server on top of REST endpoints,
You can build a proxy that rewrites your REST queries to GraphQL queries. This might be much easier than mapping a REST endpoint to GraphQL since your GraphQL API is much more powerful.
Some node.js express code since I don't know any python :(
const Lokka = require('lokka').Lokka;
const Transport = require('lokka-transport-http').Transport;
const express = require('express');
const client = new Lokka({
transport: new Transport('...')
});
const app = express();
app.get('/api/posts', (req, res) => {
client.query('{posts{id title body}}').then(result => {
res.status(200).send(result);
}).catch(error => {
res.status(500).end(); // Or other error handling
});
});

write a reverse proxy in node js to call the api in django

My frontend code is running in angular at node httpserver port 127.0.0.1:8081
My backend services runnning in python django framework at port 127.0.0.1:9000
While calling my backend servies from angular http methods throws cors exception
so i wrote a proxy controller in my node js
var http = require('http'),
httpProxy = require('http-proxy');
var proxy = httpProxy.createProxyServer();
http.createServer(function (req, res) {
// This simulates an operation that takes 500ms to execute
setTimeout(function () {
proxy.web(req, res, {
target: 'http://127.0.0.1:9000/dummy/'
});
}, 500);
}).listen(8080, "127.0.0.1");
to listen and bind at angular. i run as the node proxycontroller.js, results a another port no 127.0.0.1:8080
from proxy controller it calls my backend service and result json but from the angular js calling the proxy controller from the http.get() method results cors problem
please help to solve this problem.
Enable CORS in Django
Uses this third-party lib django-cors to do it.
You are getting CORS because you are making the call from your AngularJS app and its host is 127.0.0.1:8081, different from your Django app host 127.0.0.1:9000
The error said CORS is supported only for specific protocals like http:// etc. So you have to add http to that url. When you say, 127.0.0.1, the browser is unable to understand which protocol to use to access that url, should it be using http:// or data:// or chrome:// etc. So you've to explicitly say http://
You have to configure cors in the backend. The backend (the API server) much explcitly say a site is allowed using the http header I specified earlier. Otherwise, I can open your website, edit the frontend using chrome console and remove all the security stuff. It has the be in the backend.
as http://127.0.0.1:9000 from the front end angular app, dosent need to create proxy server to transfer the calls to backend service.

Is there a way to broadcast a message to all (or filtered) WebSocket clients connected to a WebSocket server? [duplicate]

I'm assuming this isn't possible, but wanted to ask in case it is. If I want to provide a status information web page, I want to use WebSockets to push the data from the server to the browser. But my concerns are the effect a large number of browsers will have on the server. Can I broadcast to all clients rather than send discrete messages to each client?
WebSockets uses TCP, which is point to point, and provides no broadcast support.
Not sure how is your client/server setup, but you can always just keep in the server a collection of all connected clients - and then iterate over each one and send the message.
A simple example using Node's Websocket library:
Server code
var WebSocketServer = require('websocket').server;
var clients = [];
var socket = new WebSocketServer({
httpServer: server,
autoAcceptConnections: false
});
socket.on('request', function(request) {
var connection = request.accept('any-protocol', request.origin);
clients.push(connection);
connection.on('message', function(message) {
//broadcast the message to all the clients
clients.forEach(function(client) {
client.send(message.utf8Data);
});
});
});
As noted in other answers, WebSockets don't support multicast, but it looks like the 'ws' module maintains a list of connected clients for you, so it's pretty easy to iterate through them. From the docs:
const WebSocketServer = require('ws').Server;
const wss = new WebSocketServer({ port: 8080 });
wss.broadcast = function(data) {
wss.clients.forEach(client => client.send(data));
};
Yes, it is possible to broadcast messages to multiple clients.
In Java,
#OnMessage
public void onMessage(String m, Session s) throws IOException {
for (Session session : s.getOpenSessions()) {
session.getBasicRemote().sendText(m);
}
}
and here it is explained.
https://blogs.oracle.com/PavelBucek/entry/optimized_websocket_broadcast.
It depends on the server-side really. Here's an example of how it's done using Tomcat7:
Tomcat 7 Chat Websockets Servlet Example
and an explanation of the how it's constructed here.
Yes you can and there are many socket servers out there written in various scripting languages that are doing it.
The Microsoft.Web.WebSockets namespace has a WebSocketCollection with Broadcast capability. Look for the assembly in Nuget. The name is Microsoft.WebSockets.

Categories

Resources