Ошибка CORS при передаче с сервера сокетов Python 3 на клиент Node js - PullRequest
0 голосов
/ 18 января 2019

Я установил сервер сокетов Python3 со ссылкой на:
https://python -socketio.readthedocs.io / en / latest / intro.html # server-examples
Пример кода показан ниже:

from aiohttp import web
import socketio
from eventlet.green import subprocess


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('connect')
def connect(sid, environ):
    print("connect ", sid)

@sio.on('message')
async def message(sid, data):
    ## Some processing that involves subprocess Popen
    ## Using p.communicate to store output of subprocess onto the below variable 'out'
    out = (Json data)
    await sio.emit('reply', out,room=sid)

@sio.on('disconnect')
def disconnect(sid):
    print('disconnect ', sid)


app.router.add_get('/', index)

if __name__ == '__main__':
     web.run_app(app)

Как показывает код, есть подпроцесс, который вызывает другую программу на Python, выполняет небольшую обработку, а затем сохраняет выходные данные (json) в переменной 'out', которая затем передается клиенту. Теперь клиентский код для сокета io написан на узле js. Когда сервер python пытается передать эти данные json клиенту js, я получаю сообщение об ошибке:

В запрашиваемом ресурсе отсутствует заголовок «Access-Control-Allow-Origin»

Я пытался найти ответы в Интернете, но не смог найти ответ, который понадобился бы в моей ситуации. Какую глупую ошибку я совершаю?

1 Ответ

0 голосов
/ 26 июня 2019

Я решил проблему. Во-первых, вы должны передать socketio нормальные cors.

sio = socketio.AsyncServer(async_mode='aiohttp', cors_allowed_origins='*')

Когда sio присоединяется к «app», для socket.io добавляется маршрут с заголовком cors с «» - это означает, что заголовок «Access-Control-Allow-Origin» отображается в ответе HTTP с «» "для разрешенного домена. (Вы можете контролировать разрешенный домен, если хотите.)

Итак, это часть 1 всех ваших проблем. Есть часть 2. Чтобы обслужить "/" или "/index.html", вам нужно добавить тот же заголовок cors для aiohttp. Другими словами, изменение выше одной строки добавляет заголовок cors только для socket.io, а не для aiohttp.

Чтобы aiohttp имел заголовок cors, вам нужно добавить пакет aiohttp_cors, импортировать модуль aiohttp_cors и добавить заголовок cors к каждому маршруту, насколько я понимаю. После того, как вы добавили все маршруты к маршрутизатору, вы делаете:

import aiohttp_cors
cors = aiohttp_cors.setup(app)
# app.router.add_routes(routes) if you have routes
# app.router.add_static("/", rootdir) if you want to serve static, and this has to be absolutely the last route since it's the root. Adding any route after this becomes ignored as '/' matches everthing.
for resource in app.router._resources:
  # Because socket.io already adds cors, if you don't skip socket.io, you get error saying, you've done this already.
  if resource.raw_match("/socket.io/"):
    continue
  cors.add(resource, { '*': aiohttp_cors.ResourceOptions(allow_credentials=True, expose_headers="*", allow_headers="*") })

Чтобы сделать это немного проще, я отправляю запрос в aiohttp.

...