Arhn - архитектура программирования

Как использовать привязку сервера к приложению flask, запущенному на открытом локальном хосте

Прямо сейчас у меня есть чат, который использует socket.io и mongoDB для связи с сервером, который позволяет отправлять текст в чат. При необходимости я могу отказаться от mongoDB, если он не мешает отображению текста. Все это работает на локальном порту 5000, который я открыл с помощью ngrok, который позволяет мне получить к нему доступ через домен. Проблема в том, что когда я получаю доступ к приложению из домена, все функции моего сервера не работают так, как предполагалось (у меня есть server.js, index.html и flask-app.py), index.html и приложение flask-app работают. Я включу домен для справки.

https://143bd63a.ngrok.io

Я думаю, что может быть что-то, связанное с тем фактом, что server.js не запускается вместе с индексом и приложением flask, которое фактически возвращает render_template. Я запускаю сервер с помощью npm start.

Я знаю, я знаю, что index.html - это беспорядок, и уровень новичков, пожалуйста, помилуй

Вот сервер:

const mongo = require('mongodb').MongoClient;
const client = require('socket.io').listen(4000).sockets;
// Connect to mongo
mongo.connect('mongodb://127.0.0.1/mongochat', function(err, db){
    if(err){
        throw err;
}

console.log('MongoDB connected...');


// Connect to Socket.io
client.on('connection', function(socket){
    let chat = db.collection('chats');

    // Create function to send status
    sendStatus = function(s){
        socket.emit('status', s);
    }

    // Get chats from mongo collection
    chat.find().limit(100).sort({_id:1}).toArray(function(err, res){
        if(err){
            throw err;
        }
        // Emit the messages
        socket.emit('output', res);

    });
  // Handle input events
    socket.on('input', function(data){
        let name = data.name;
        let message = data.message;
            // Insert message
            chat.insert({name: name, message: message}, function(){
                client.emit('output', [data]);
                // Send status object
                sendStatus({
                    message: '',
                    clear: true
                });
            });
    });

    // Handle clear
    socket.on('clear', function(data){
        // Remove all chats from collection
        chat.remove({}, function(){
            // Emit cleared
            socket.emit('cleared');
        });
    });
});// end of server
});

Это index.html (извините за беспорядок)

 <!DOCTYPE html>

<html lang="en">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>

<script type = "text/javascript">
//==============================================

//=
 </script>
<script src = "bundle.js"></script>
<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">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
    <title>QuickORDR</title>
    <style>
        #messages{height:300px;}
    </style>

    <style>
        {#.chat-message {#}
        {#    width: 100px;#}
        {#    word-break: break-word;#}
        {#    margin-bottom: 20px;#}
        {#}#}
        .break-all{
            word-break: break-all;
        }
        preBot{
            color:#317df7;
            text-align:left;
            display: block;
            font-family: Helvetica;
            white-space: pre;
            margin: 1em 0;


        }
        preUser{
            color:#09c64c;
            display: block;
            font-family: Helvetica;
            white-space: pre;
            margin: 1em 0;
            text-align: right;

        }
    </style>

</head>
<body style ="background-color: #eee;">

    <div class="container">
        <div class="row">
            <div class="col-md-6 offset-md-3 col-sm-12">
                <br>
                <h1 class="text-center">
                    Quik Ordr
                    <button id="clear" class="btn btn-warning">Clear</button>
                </h1>
                <div id="status"></div>
                <div id="chat">
                    <input type="text" id="username" name = "username" class="form-control" placeholder="Enter name..." style="display:none;" wrap="soft">
                    <br>
                    <div class="card">
                        <div id="messages" class="card-block", style="overflow:auto" >

                        </div>
                    </div>
                    <br>
                    <textarea id="textarea" name = "message" class="form-control" placeholder="Enter message..."></textarea>
                    <br />
                  <div class="yes" style="display:none;"><button id="yes" class="btn btn-success" display ="none">Correct</button> <button id="no" class="btn btn-danger">Incorrect</button> </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>

    <script>

        (function(){

          sendStatus = function(s){
              socket.emit('status', s);
          }
            var element = function(id){
                return document.getElementById(id);
            }
            // Connect to socket.io
            var socket = io.connect('http://127.0.0.1:4000');
            //var socket = io.connect('http://1372aecb.ngrok.io:4000');
            socket.emit('clear'); //  need to make sure that text area is clear before it can work
            // Get Elements
            var status = element('status');
            var messages = element('messages');
            var textarea = element('textarea');
            var username = element('username');
            var clearBtn = element('clear');
            var yesBtn = element('yes');
            var noBtn = element('no');

            // Set default status
            var statusDefault = status.textContent;

            var setStatus = function(s){
                // Set status
                status.textContent = s;

                if(s !== statusDefault){
                    var delay = setTimeout(function(){
                        setStatus(statusDefault);
                    }, 4000);
                }
            }


            // Check for connection
            if(socket !== undefined){

                console.log('Connected to socket...');


                // Handle Output
                socket.on('output', function(data){
                    //console.log(data);
                    if(data.length){
                        for(var x = 0;x < data.length;x++){

                            // Build out message div
                            var message = document.createElement('div');
                            message.setAttribute('class', 'chat-message');
                            if (data[x].name[0] != 'C'){
                            message.innerHTML = "<preBot>" + data[x].name+ data[x].message +'</preBot>';

                            }
                            else {
                                message.innerHTML = "<preUser>" + data[x].name + ": " + data[x].message + '</preUser>';
                            }

                            messages.appendChild(message);
                            messages.appendChild(document.createElement('hr'));
                            messages.classList.add('break-all');
                            console.log(message);
                            messages.insertBefore(message, messages.nextSibling);
                        }
                    }
                });


                // Get Status From Server
                socket.on('status', function(data){
                    // get message status
                    setStatus((typeof data === 'object')? data.message : data);

                    // If status is clear, clear text
                    if(data.clear){
                        textarea.value = '';
                    }
                });

                // Handle Input
                textarea.addEventListener('keydown', function(event){
                    if(event.which === 13 && event.shiftKey == false){
                        // Emit to server input
                        socket.emit('input', {
                            name:'Customer',
                            message:textarea.value
                        });

                        //takes the text from the user and sends it to the pythoncode
                        //returns the query code and emits it
                        $.ajax({
                                url: '/sendToBot',
                                data: $('textarea').serialize(),
                                type: 'POST',
                        }).done(function(data){
                          console.log(data);
                          item_summary = data['summary'];
                          auto_correct = data['autocorrect'];
                          console.log(item_summary);
                          console.log(auto_correct);
                          //emit the bot message summary
                          socket.emit('input',{
                            name: '',
                            message:item_summary
                          });
                          //emit the bot message autocorrect
                           // socket.emit('input',{
                            //name: 'SpellCorrect',
                           // message:auto_correct
                          //});
                          //dump the bot data

                          //if the item summary is there, activate the buttons
                          var bot_message = item_summary;
                          if(bot_message[0] == 'Q'){
                            $(".yes").show(1000);
                          }
                        });
                        event.preventDefault();
                      }
                });//end of text click event

                //use socket to clear to run the success/fail button execution
                yesBtn.addEventListener('click', function(){
                  //ajax a trigger to add a correct tag to the messages
                  $.ajax({
                                url: '/correct',
                                data: $('textarea').serialize(),//just a placeholder
                                type: 'POST',
                                success: function(response){
                                    console.log(response);
                                },
                                error: function(error){
                                    console.log(error);
                                }
                            });
                  socket.emit('clear');
                  socket.emit('input',{
                    name: '',
                    message:'Thanks! Try Again'
                  });
                  $('.yes').hide(1000);

                });
                //handle the no button click
                noBtn.addEventListener('click', function(){
                  //ajax a trigger to add an incorrect tag to the messages
                  $.ajax({
                          url: '/incorrect',
                          data: $('textarea').serialize(),//just a placeholder
                          type: 'POST',
                          success: function(response){
                            console.log(response);
                          },
                          error: function(error){
                            console.log(error);
                          }
                        });
                  //wipe the message box
                  socket.emit('clear');
                  //output the repeate code
                  socket.emit('input',{
                    name: '',
                    message:'Thanks! Try Again'
                  });
                  $('.yes').hide(1000);
                });

                // Handle Chat Clear
                clearBtn.addEventListener('click', function(){
                    socket.emit('clear');
                });
                // Clear Message
                socket.on('cleared', function(){
                    $('.yes').hide(1000);
                    messages.textContent = '';
                });
            }



        })();
    </script>
</body>
</html>

Это приложение-фляга:

import os
import time
from flask import Flask,render_template, request,json,jsonify
import chatbot
import pandas as pd
#pip install pandas
#pip install nltk
#pip install

app = Flask(__name__)
messagesList = [

]
#this basically just sets the excel file to a couple of empty cells
def reset_excel():
    cols = ['User TimeStamp', 'Bot TimeStamp', 'User Message', 'Bot Message', 'Status']
    empty_data = [['','','','','']]
    df = pd.DataFrame(empty_data, columns=cols)
    df.to_csv('database.csv', encoding='utf-8', index=False)

#this makes sure that the dict is in order for the excel file
def append_in_order(dictionary_list):
    the_data = [[dictionary_list[0]['user_time'], dictionary_list[2]['bot time'],
                dictionary_list[3]['user'],dictionary_list[1]['bot'],dictionary_list[4]['status']]]
    return the_data

#function that dumps the data to a panda then a csv
def dumpData(messagesList):
    cols = ['User TimeStamp', 'Bot TimeStamp', 'User Message', 'Bot Message', 'Status']
    the_data =  append_in_order(messagesList)
    df = pd.DataFrame(the_data, columns= cols)
    with open('database.csv', 'a') as file:
        df.to_csv(file, header=False, index = False)
    messagesList.clear()

#initialize the time variable
ts = time.gmtime()

def printmessage(txt):
    if txt == 'message list':
        print(messagesList)
    elif txt == 'bot fail':
        print('bot failed')
    print(txt)
def dummmybot(txt):
    msg = chatbot.bot(txt)

    return {'message': msg}

#this will lauch the html page
@app.route('/')
def chat():
    return render_template('index.html')

#this will collect the input from the user
@app.route('/sendToBot', methods=['POST'])
def sendToBot():
    messagesList.clear()
    message = request.form['message'] #this is a string that is returned from the ajax
    if message == 'reset_excel_database': #sec
        reset_excel()
    message_time = time.strftime("%m-%d %H:%M:%S") #grab the timestamp for the user message
    messagesList.append({'user_time':message_time})
    bot_message = chatbot.bot(message)

    item_summary = bot_message[0]
    autocorrect = bot_message[1]
    send_to_chat = {'summary': item_summary, 'autocorrect':autocorrect}#pass message into bot
    printmessage(bot_message[0])
    printmessage(bot_message[1])

    messagesList.append({'bot':send_to_chat['summary']})#append the bot message
    bot_message_time = time.strftime("%m-%d %H:%M:%S")
    messagesList.append({'bot time':bot_message_time}) #append the bot time

    new_message = {'user':message}
    messagesList.append(new_message)

    return jsonify(send_to_chat) #returns the message from the bot

@app.route('/correct', methods=['POST'])
def correct():
    ignore = request.form['message']#just a placeholder
    correct_id = {'status':'Correct'}
    messagesList.append(correct_id)
    #dump the message list to a csv file using pandas
    printmessage('message list')
    dumpData(messagesList)
    return jsonify(correct_id)

@app.route('/incorrect', methods= ['POST'])
def incorrect():
    ignore = request.form['message']#just a placeholder
    incorrect_id = {'status':'inc   orrect'}
    messagesList.append(incorrect_id)
    printmessage('message list')
    #dump the message list int a csv file using pandas
    dumpData(messagesList)
    return jsonify(incorrect_id)

if __name__=="__main__":
    app.run(port = 27017)

Решено

Оказывается, мне нужно использовать Flask-socketio вместе с моей существующей флягой. В html мне просто нужна строка var socket = io.connect ()


Ответы:


1

Кажется, у вас есть несколько проблем - вот два наблюдения, просто глядя на ваш интерфейс на стороне клиента (я вообще не читал ваш опубликованный код)

Во-первых, клиентский JS-ресурс https://143bd63a.ngrok.io/bundle.js возвращает 404, поэтому, если он должен обслуживать функциональную логику на стороне клиента, он никогда не загружается в браузер.

Во-вторых, ваше веб-приложение, похоже, выполняет вызовы веб-сокетов не на тот хост. Если вы используете «Network Inspector» своего любимого браузера, я вижу, что ваши исходящие запросы сообщений чата будут:

http://127.0.0.1:4000/socket.io/?EIO=3&transport=polling&t=MFIA9lc

Это неверно, так как мой компьютер не единственная служба ответов -

Похоже, что приложение действительно должно делать запрос сокета на

https://143bd63a.ngrok.io:4000

Однако этот порт, похоже, не перенаправляется через ваш брандмауэр - потому что, хотя кажется, что ваше приложение должно прослушивать порт 4000, это дает мне тайм-аут соединения, когда я пытаюсь открыть сокет.

05.06.2018
  • Ресурс JS - это постоянная работа, и на самом деле он пока не предназначен для работы, где мне сделать изменения, чтобы сокет отправлял свои запросы на порт: 4000, и когда я перенаправляю порт, я делаю это через, скажем, брандмауэр Windows или настройки роутера? Спасибо за помощь 06.06.2018
  • var socket = io.connect('http://127.0.0.1:4000'); это должно быть подключено к вашему домену http://yourdomain:4000. Порт 4000 должен быть перенаправлен точно так же, как вы перенаправили порт 80/443 на тот же хост. 06.06.2018
  • Я еще не переадресовал ни одного порта. Я использовал только программу, которая делает это для меня i, когда она выставляет localhost: 5000 и создает для него домен. и спасибо за ответ 06.06.2018
  • Попался, можете ли вы использовать ту же программу, чтобы открыть порт 4000 во втором домене? Затем используйте этот адрес в качестве адреса подключения sockets.io. 06.06.2018
  • Я открыл порт: 4000 по URL-адресу: 31dcbdc2.ngrok.io, я установил var socket = io.connect ('31dcbdc2.ngrok.io:4000'), однако проблема сохраняется. 06.06.2018
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..