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. ...
随机推荐
- 【英雄帖】FreeRedis 邀请您一起优化项目。
嘿!各位!自 FreeRedis 开库以来,相继出现了很多贡献者,我们正在对 FreeRedis 的各功能模块做优化,这并不意味着现版的 FreeRedis 有问题,我们只是希望在某些方面做得更好.如 ...
- Python高级语法-私有属性-with上下文管理器(4.7.3)
@ 目录 1.说明 2.代码 关于作者 1.说明 上下文管理器 这里使用with open操作文件,让文件对象实现了自动释放资源.我们也能自定义上下文管理器,通过__enter__()和__exit_ ...
- 一场由fork引发的超时,让我们重新探讨了Redis的抖动问题
摘要:一次由fork引发的时延抖动问题. 背景介绍 华为云数据库GaussDB(for Redis) 是一款基于计算存储分离架构,兼容Redis生态的云原生NoSQL数据库:它依靠共享存储池实现了强一 ...
- EF Core 三 、 骚操作 (导航属性,内存查询...)
EF Core 高阶操作 本文之前,大家已经阅读了前面的系列文档,对其有了大概的了解 我们来看下EF Core中的一些常见高阶操作,来丰富我们业务实现,从而拥有更多的实现选择 1.EF 内存查找 wh ...
- Mac电脑 Android Studio连接小米手机
1.设置>关于本机>点击5下MIUI版本>激活开发者模式 2.设置>更多设置>开发者选项>开启开发者选项>开启USB调试>开启USB安装>开启显示 ...
- 基于Let's Encrypt生成免费证书-支持多域名泛域名证书
目录 客户端 certbot acme.sh 安装acme.sh 1. 自动安装 2. 手动安装 3. 测试收否安装成功 使用acme.sh生成证书 1. HTTP 方式 2. DNS 方式 1. 生 ...
- 编写高质量JAVA代码之让接口的职责保持单一
上述标题读者朋友应该也注意到了是让接口的职责保持单一,而不是实现者单一. 设计模式六大原则之单一原则: 定义 不要存在多于一个导致类变更的原因.**通俗的说,即一个类只负责一项职责. 下面以一个电话模 ...
- Hive 中的四种排序详解,再也不会混淆用法了
Hive 中的四种排序 排序操作是一个比较常见的操作,尤其是在数据分析的时候,我们往往需要对数据进行排序,hive 中和排序相关的有四个关键字,今天我们就看一下,它们都是什么作用. 数据准备 下面我们 ...
- Hbase性能调优(二)
一.HBase关键参数配置指导 如果同时存在读和写的操作,这两种操作的性能会相互影响.如果写入导致的flush和Compaction操作频繁发生,会占用大量的磁盘IO操作,从而影响读取的性能.如果写入 ...
- C#扫盲篇(一):反射机制--情真意切的说
在一线编码已有多年,积累了不少非常实用的技能,最近的更新会逐步的分享出来,希望能帮助到还有一丢丢喜欢.Net的朋友,当然这些都比较适合入门选手,虽然自己已是个精通抄代码的老猿,但技术造诣仍是渣渣. 犹 ...