HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端
HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端
发表时间:2020-03-05
1 背景
由于公司前端的页面部署在以https(加了证书)协议的域名下,去请求http协议的域名的某个服务,并且该http域名下的服务,不仅要处理普通请求(POST、GET),还需要处理websocket请求。由于浏览器禁止https域名的内容请求http的服务,甚至嵌入子页面都禁止,因为浏览器会认为http的内容是不安全的,所以为解决该问题,研究出如下解决方案。
2 解决办法
由于浏览器禁止,但是服务器并不会禁止,所以,我在https的域名下,解析一台代理服务器,由该代理服务器去代替https去请求,再把结果返给前端。
3 开发环境
PyCharm,语言:Python3,服务框架:django
4 用到的库
pip3 install Django==1.11.3 django-cors-headers==3.2.1 dwebsocket==0.5.12 websocket==0.2.1 websocket-client==0.57.0
5 settings.py配置
# 允许访问的host为所有
ALLOWED_HOSTS = ['*']
# 配置跨域请求问题
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
'VIEW',
)
CORS_ALLOW_HEADERS = (
'XMLHttpRequest',
'X_FILENAME',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
#'myapp.apps.MyappConfig',
# 添加当前的app
'myapp',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 去除csrf校验
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
6 urls.py配置:
from django.contrib import admin
from django.urls import path
from django.conf.urls import url
from myapp import views
urlpatterns = [
path('admin/', admin.site.urls),
# 配置拦截/proxy 映射到 views.py中的方法
url(r'^proxy$',views.proxy),
]
7 views.py代码:仔细看注释
from django.shortcuts import render
from django.shortcuts import HttpResponse
import requests
from dwebsocket.decorators import accept_websocket
import logging
from websocket import create_connection
import time
# 设置日志格式
LOG_FORMAT = "%(asctime)s - %(levelname)s - %(message)s"
DATE_FORMAT = "%m/%d/%Y %H:%M:%S %p"
fs = logging.StreamHandler()
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT, datefmt=DATE_FORMAT, handlers=[fs])
# Create your views here.
# 添加dwebsocket的装饰器,该装饰器会对request属性添加websocket属性
# 并添加 send()推数据 close()关闭连接 is_websocket()是否是websocket请求 等方法
@accept_websocket
def proxy(request):
# 判断请求是否是websocket
if not request.is_websocket():
# 收到的请求的格式是 https://devlab.edu.huaweicloud.com/proxy?url=http://ip:8000/senddata?model=workload-read-mostly
# 我们将这个服务部署到加了证书的服务器上,即可。
# 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
url = request.get_full_path().split('url=')[1]
logging.info('proxy url : {}'.format(url))
# 进行GET请求和POST请求的分别处理
# if request.method == 'GET':
# logging.info('processing a url GET request !')
# 其中省略了将请求的 header/cookie 传递给代理请求的 header/cookie ,由于我们业务不需要这些,我就不加了。
# res = requests.get(url)
# else:
# logging.info('processing a url POST request !')
# res = requests.post(url)
# 由于我们的业务都是g GET 请求,所以就直接处理就好了
res = requests.get(url)
# 将代理请求的结果返回给真正的请求
logging.info('revc : {}'.format(res.content.decode()))
return HttpResponse(res.content.decode())
else:
# 收到的请求的格式是 wss://devlab.edu.huaweicloud.com/proxy?url=ws://ip:8000/senddata?model=workload-read-mostly
# 其中,参数url=后面是要代理的url ,我们将其截取下来,并重新请求。
url = request.get_full_path().split('url=')[1]
logging.info('proxy url : {}'.format(url))
try:
# 这里的header 必须要加上, 或者将 request中的header拿出来逐一存入list中,
# 由于request中保存的headers的格式是dict,websocket中需要的headers是list,所以需要自行转化,
# websocket的header的格式如下, 由于业务没有强制header 是什么,所以我就自己写的,但是注意,
# 需要将以下的header的内容都要补充完整,否则会报 header...相关的错误,返回200或者其他状态码的错误,
# 200在websocket是错误,在http里面是成功,需要注意一下。
header = ['Accept-Encoding: gzip, deflate',
'Connection: Upgrade',
'Pragma: no-cache',
'Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits',
'Sec - WebSocket - Version: 13',
'Upgrade: websocket',
'Access-Control-Allow-Origin: *',
'Access-Control-Allow-Headers: X-Requested-With',
'Access-Control-Allow-Methods: GET,POST,OPTIONS',
'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36']
# 创建长连接/websocket
ws = create_connection(url,header=header)
# 每1秒就收一下消息
while True:
# 接收消息,如果消息中带有Finished,表示消息都接收完毕,跳出循环。
res = ws.recv()
if 'Finished' in res:
logging.info('revc : {}'.format(res))
# 该服务,即作为服务端(接收并处理请求并响应方),又做为客户端(发送请求并接收另一个服务的响应)
# 所以将代理服务推过来的结果再推给浏览器
request.websocket.send(res)
# 调试的时候,浏览器端好像收不到最后一条消息,所以我在以这种方式再发送一遍吧
# return HttpResponse(res)
# websocket 相当占用网络资源,请及时关闭,由于生产环境中,网络资源的不稳定性,
# 可能数据还没推出去,就把websocket关闭了,会造成数据的丢失。
time.sleep(5)
ws.close()
request.websocket.close()
break
if not res == None:
logging.info('revc : {}'.format(res))
# 如果有数据, 将代理服务推过来的结果再推给浏览器
request.websocket.send(res)
time.sleep(1)
# websocket 相当占用网络资源,请及时关闭,其实逻辑是走不到这里的,但是还是加上保险
ws.close()
request.websocket.close()
except BaseException as e:
logging.error(e)
8 部署
python3 manage.py runserver 0.0.0.0:8080
https://www.pythonf.cn/read/51639
HTTPS请求HTTP接口被浏览器阻塞,python实现websocket客户端,websocket服务器,跨域问题,dwebsocket,https,拦截,服务端的更多相关文章
- 解决前后端分离的“两次请求”引出的Web服务器跨域请求访问问题的解决方案
在前后端分离的项目中,前端和后端可能是在不同的服务器上,也可以是Docker上,那就意味着前端请求后端Restful接口时,存在跨域情况. 后端在做了通用的跨域资源共享CORS设置后,前端在做ajax ...
- Chrome浏览器扩展开发系列之十五:跨域访问的XMLHttpRequest对象
XMLHttpRequest对象是W3C的标准API,用于访问服务器资源.XMLHttpRequest对象支持多种文本格式,如XML和JSON等.XMLHttpRequest对象可以通过HTTP和HT ...
- chrome浏览器下用jQuery的load函数来跨域加载页面,响应状态status为(canceled)是什么情况? JSON和JSONP,也许你会豁然开朗,含jQuery用例
http://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html 问题来源:http://q.cnblogs.com ...
- 由一个“两次请求”引出的Web服务器跨域请求访问问题的解决方案
http://blog.csdn.net/cnhnnyzhy/article/details/53128179 (4)Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有 ...
- Django之jsonp跨域请求原理
在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsonp 二.XMLHttpRequest2 ...
- 深入理解jsonp跨域请求原理
在进行网站开发的过程中经常会用到第三方的数据,但是由于同源策略的限制导致ajax不能发送请求,因此也无法获得数据.解决ajax的跨域问题有两种方法: 一.jsop 二.XMLHttpRequest2中 ...
- springboot + websocket + spring-messaging实现服务器向浏览器广播式
目录结构 pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http:// ...
- Web 跨域请求问题的解决方案- CORS 方案
1.什么是跨域 跨域是指跨域名的访问,以下情况都属于跨域: 跨域现象 实例 域名不相同 www.baidu.com与www.taobao 一级域名相同,但是端口不相同 www.baidu.com:80 ...
- [二十七]SpringBoot 之 Restful接口的跨域请求
什么是跨域 简单的说即为浏览器限制访问A站点下的js代码对B站点下的url进行ajax请求.比如说,前端域名是www.abc.com,那么在当前环境中运行的js代码,出于安全考虑,访问www.xyz. ...
随机推荐
- Java中的命名规范。
类:所有单词的首字母大写,如:TestJava. 方法:第1个单词的首字母小写,之后每个单词的首字母大写,如:getInfo(). 属性:第1个单词的首字母小写,之后每个单词的首字母大写,如:stud ...
- JYadmin-react-antd react+antd封装的优秀后台模板集成方案("^1.0.0")
版本:[ "JYadmin-react-antd": "^1.0.0"] 版权所有:微信公众号[微新悦] 原文链接:https://www.weixinyue. ...
- 这可能是目前最轻量级、最支持MVVM、可定制性最高的开源Chart控件!
由于项目中经常用到Series Chart,而目前市面又实在找不到既支持MVVM,又轻量级的开源Chart控件,于是干脆就花了两周时间随手写了一个.昨天感觉还比较满意,就发布到了Github上:htt ...
- PHP连接数据库的方式
1,旧的方式 - mysql(面向过程) 1 <?php 2 //定义连接参数 3 $host = 'localhost'; 4 $user = 'root'; 5 $password = '' ...
- BOM主数据-用ECN实现可变BOM
用ECN变更号实现可变BOM:通过ECN变更号的参数类型来实现BOM的可变配置. 物料编号:2104 (1)首先BOM的父项物料主数据<基本数据1>必须设置栏位"参数有效值&qu ...
- 为什么 StackOverflow 上的代码片段会摧毁你的项目?
昨天公司里碰到一件令人哑然失笑的事情.帮朋友公司做的一个项目,做SIT测试的时候发现一些bug,仔细查了下原因,原来是因为当初觉得这个项目比较简单,交给了几个新入职的新丁,也算是给他们练练手,结果其中 ...
- win8.1默认输入法设置
1.右击左下角,选择控制面板 2.选择更改输入法 3.选择高级设置 4.在替代默认输入法,从下拉列表中选择自己已安装的输入法,比如搜狗拼音输入法,qq拼音输入法等其他输入法
- 杭电OJ1062---Text Reverse(c++)(C++库getline的使用)
Text Reverse Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...
- Cocos Creator 新资源管理系统剖析
目录 1.资源与构建 1.1 creator资源文件基础 1.2 资源构建 1.2.1 图片.图集.自动图集 1.2.2 Prefab与场景 1.2.3 资源文件合并规则 2. 理解与使用 Asset ...
- 为Github仓库添加Github Actions实现持续集成: Android apk自动编译发布以及github pages同步推送coding.net
内容转载自我的博客 目录 说明 1. 编写Android项目的CI配置文件 2. 编写Jekyll项目的CI配置文件 2.1 配置coding.net 2.2 配置github 2.3 自动部署到co ...