记录第一次建站的过程
最开始建站的时候,是使用魅族note6安装linux虚拟机 + 内网穿透来搭建服务器的,本来想使用树莓派,但是你懂的原因(买不起),然后又突然想起来自己有个废旧手机,于是想试试看能不能搭建服务器来玩玩看。
这里我使用Linux deploy + ubuntu(不要问我为什么不用centos,我对ubuntu有独特情怀),手机详细的root方法和linux depoly环境构建,这里就不详细说明了,主要是为了记录一下第一次搭建网站的不易。搭建完成的效果如下:
网址:www.dayangtuo247.xyz(现已注销,更换为新域名www.wqlblog.cn)
这个网站在大二下学期建设,大三后太久没有维护,然后废弃了。
建站步骤
- 构建前端
- 构建后端(WebApi,处理数据)
- 前后端合并规避CORS(前后端分离也可,不过要注意解决好CORS跨域问题)
- 安装ubuntu
- ubuntu配置环境
- 部署项目
- 开启内网穿透(这里我选择免费的sakuraFtp)
注意内网穿透服务器的选择,国内服务器要备案,国外服务器则不做要求,但访问速度较慢
jQuery
jQuery
是一个 JavaScript
库。
jQuery
极大地简化了 JavaScript
编程。
ajax
Asynchronous JavaScript And XML
使用ajax前请先调用jQuery
库,$.ajax
在该库之中,如未调用将报错jQuery is not defined
AJAX 是开发者的梦想,因为您能够:
- 不刷新页面更新网页
- 在页面加载后从服务器请求数据
- 在页面加载后从服务器接收数据
- 在后台向服务器发送数据
工作原理
语法格式
$.ajax({
type: "", //请求类型 get post ····
url: "", //请求后端API接口
contentType: '', //内容类型
data: '', //待发送数据
dataType: "json", //返回数据类型
success: function(data){//发送成功执行函数
console.log(data);
}
});
get请求和post请求
- GET – 从指定的资源请求数据。
- POST – 向指定的资源提交要被处理的数据。
请求url为:编写好了的后端webapi接口
CORS(跨源资源共享)问题
这个问题解决办法很复杂,请详细了解
(CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它origin(域,协议和端口),这样浏览器可以访问加载这些资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的”预检”请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。
跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。
所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子:
http://www.123.com/index.html 调用 http://www.123.com/server.php (非跨域)
http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)
http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)
http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)
请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
解决方案
- IIS中允许跨域
- nginx反向代理绕过跨域
IIS中允许跨域
对于初次在IIS部署网站的同学,很容易忽略或不知道如何配置使其网站支持跨域请求,这里介绍一个最基础的方式,配置HTTP响应标头。
在IIS上选择HTTP响应标头,选择添加自定义响应标头,通常我们会添加三个HTTP响应标头:
名称 | 值 |
---|---|
Access-Control-Allow-Headers | content-type |
Access-Control-Allow-Methods | GET,POST,PUT,DELETE,OPTIONS |
Access-Control-Allow-Origin | * |
但是IIS中允许跨域我的只能接受GET请求,POST请求还是不行,这和后端处理有关系,因为我的后端还没有写处理OPTIONS请求的代码,因此在浏览器中跨域POST请求还是会失败的。
nginx反向代理绕过跨域
$.ajax({
type: "POST",
url: "http://www.dayangtuo247.xyz/write",
dataType: "json",
contentType: "application/json; charset=utf-8",
//············
}
在postman中,发送post请求正常,而在浏览器中发送post请求报错,查看信息为
Access to XMLHttpRequest at ‘xxx’ from origin ‘xxx’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
原因:浏览器发送post请求会事先发送一次预检请求(OPTIONS请求),而postman等测试软件并不会发送该请求,因此浏览器报错而postman软件不报错
触发预检请求的三类条件:
- 默认情况下,跨域请求只支持GET,HEAD,POST方法,如果不是这三个请求方法(比如:PUT、DELETE、CONNECT、OPTIONS、TRACE和PATCH),那么将触发预检请求
- 默认情况下,浏览器跨域请求时,会自动添加的请求头(HOST,Referer,Connection、Accept、User-Agent,Accept-Languange,Accept-Encoding,Accept-Charset和Content-Type),这些请求中还有其他请求头时,那么将触发预检请求。
- 如1、2所说的情况排除在外的条件下,跨域请求是,浏览器支持的Content-Type值为application/x-www-form-urlencoded,multipart/form-data和text/plain。如果是其他数据类型(如application/json,text/xml…),那么将触发预检请求。
解决办法
nginx中location中插入如下代码以回应预检请求
if ($request_method = 'OPTIONS') {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Max-Age 1728000;
add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS,PUT,DELETE'; add_header Access-Control-Allow-Headers 'Token,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,ACCESS-TOKEN,x-file-name,Cookie';
add_header Content-Type 'application/json;application/x-www-form-urlencoded;text/plain; charset=utf-8';
add_header Content-Length 0 ;
add_header Access-Control-Allow-Credentials true;
return 204;
}
json文件
json是什么?json是JavaScript Object Notation的简写,翻译过来就是js对象简谱,简单点来说就是一种轻量级的数据交换格式。
这里我使用ajax传输json数据,和作为数据库使用。
详细介绍json文件格式详解
后端处理
语言选择:ASP.NET Code 6 C#
编程环境:visual studio 2022
步骤:使用使用ASP.NET C#创建WebApi,来处理前端发送的get和post请求,例如本站的两个接口为
- GETwww.dayangtuo247.xyz/request
- POSTwww.dayangtuo247.xyz/write
写完程序后发布在IIS上事先测试,成功之后在部署到linux中
linux服务器部署(重要)
这里我选择的是在安卓手机上用linux deploy安装arm64架构的ubuntu 18.04 LTS系统,因此,想要将发布的WebApi在linux上运行,请先在ubuntu中搭建ASP.NET Code环境,该环境较难搭配,但是好在树莓派恰好也是arm64架构的CPU,因此我们可以直接套用树莓派的ASP.NET Code环境搭建方法
.NET 6环境部署
- 首先安装.Net Core依赖
sudo apt install -y libunwind8 libunwind8-dev gettext libicu-dev liblttng-ust-dev libcurl4 libcurl4-openssl-dev libssl-dev uuid-dev unzip libgdiplus libc6-dev libkrb5-3
需要安装的依赖微软官方文档已经列出,如果遇到莫名其妙的问题,看看是不是某项依赖没有安装。
-
下载.NET Core SDK
sudo wget https://download.visualstudio.microsoft.com/download/pr/adcd9310-5072-4179-9b8b-16563b897995/15a7595966f488c74909e4a9273c0e24/dotnet-sdk-6.0.100-linux-arm64.tar.gz -O dotnet-sdk-linux-arm.tar.gz --no-check-certificate
当wget不存在时,请
apt install wget
命令安装,我这里使用的是SDK 6.0,可以访问此网站选择合适的版本下载。下载好之后,按照以下命令安装SDK。 -
创建dotnet文件夹并解压
sudo mkdir -p /usr/local/dotnet && sudo tar zxf dotnet-sdk-linux-arm.tar.gz -C /usr/local/dotnet
- 创建软连接
sudo ln -s /usr/local/dotnet/dotnet /usr/local/bin
- 测试
dotnet --version
输出.NET Core提示信息即表示环境安装成功。
安装成功之后可以执行以下语句来创建localhost证书,避免启动Web/Web Api项目时,监听https://localhost报错。
sudo dotnet dev-certs https
- 记得删除下载的文件在wuqiling目录下
sudo rm -r /home/wuqiling/dotnet-sdk-linux-arm.tar.gz
nginx反向代理
可以理解为nginx是一个分发服务器,根据用户的不同请求url来分发给不同的服务器处理,例如,nginx监听8888端口,将8888端口做内网穿透,然后使用nginx反向代理8080端口和9090端口,当用户输入url1时,nginx将该请求发送到8080端口,输入url2时,将该请求发送到9090端口。而如果8080端口和9090端口都部署了不同的网站,那么就可以实现内网穿透一个端口而访问多个网站的请求。
server {
listen 8888;
server_name url1; #ip或域名
location / {
proxy_pass http://127.0.0.1:8080;
}
}
server {
listen 8888;
server_name url2;
location / {
proxy_pass http://127.0.0.1:9090;
}
}
需要注意的是,nginx监听同端口,而分发域名相同时,nginx默认使用第一个server,而分发域名不同时,nginx才会起到分发不同。
开源网盘
这里我选择CloudReve作为私有云网盘,cloud.dayangtuo247.xyz作为子域名
限速问题的解决
由于内网穿透选择的穿透服务器限速是不高于10Mbps的,因此作为个人网盘使用会导致速度过慢,这将导致上传下载大文件时速度会太慢,因此这里我选择修改存储策略为阿里云OSS,将阿里云OSS作为存储网盘,而CloudReve网盘作为url中转,由于开源网盘CloudReve修改存储策略之后上传和下载直接将用户和阿里云OSS直接连接,而阿里云OSS是不限速的,因此解决了限速问题,同时也节省了内网穿透服务器的流量。
CloudReve限制大文件解决
该问题出现在域名打开网站上传超过5M大小的文件时会导致HTTP错误。而使用本地端口打开就不会出现该问题,因此需要考虑nginx的问题。查看nginx的error.log日志,发现有一行代码为413 Request Entity Too Large
,解决办法,在nginx.conf中加入client_max_body_size 1024M
,限制上传大小为1GB。
域名划分
备案备的是主域名,在该域名下还可以申请不同的子域名
举例:
- “.com”是顶级域名(一级域名);
- “aliyun.com”是主域名(二级域名);
- “example.aliyun.com”是子域名(三级域名);
- “www.example.aliyun.com”是子域名的子域(四级域名)。
为什么要设置子域名
1、 因为一个主域名可以设置出不同的子域名,所以能够便于用户将不同的子域名应用到不同的业务中。
例如主域名是 aliyun.com,开发者则可以设置子域名 api.aliyun.com 为接口业务使用,子域名 pay.aliyun.com 为支付系统使用。
2、 实现访问者按照用户指定的子域名进行访问。
例如主域名是 aliyun.com,开发者设置子域名为www.aliyun.com和aliyun.com后, 访问者输入这两个域名时就可以实现访问。