Nginx 禁止未绑定的域名访问

问题

当设置了多个域名解析到同一个 IP 的 Nginx 服务器的时候,就会出现没有设置的域名也可以访问特定的站点,默认的 Nginx Vhost 配置会把没有匹配的域名请求指向到默认的default_server

解决

  1. nginx.conf配置中加入这一段默认的 server 配置
  2. 删除vhostsdefault配置
server {
    listen       80  default_server;
    server_name  _;
    return       444;
}

因为 Nginx 的 Vhost 会根据请求的域名去访问绑定了域名的站点,如果没有匹配到,就会去访问default_server

default_server收到的请求都返回 444

Nginx 配置文件层级

{
    events {
    }
    http {
        server {
            upstream {

            }
            location {
                # lalal
            }
        }
    }
}

HTTP 中 put 和 patch 的区别

在很多 RESTfull 应用中,会使用到POST 方法去创建内容, PUT 方法去更新内容,例如

curl -x PUT /user/1 --data username=zonghua

但是经常混淆的是 PUT 和 PATCH 方法,从字面意义上理解就是,PUT 是重新放置, PATCH 进行局部修改。

当使用 id 做唯一主键的时候,就是 PUT 方法将一个指定 id 对象进行完全替换, PATCH 方法指定 id 去更新这个对象。

RFC 标准 https://tools.ietf.org/html/rfc5789#page-2

The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version
be replaced. With PATCH, however, the enclosed entity contains a set
of instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it
also MAY have side effects on other resources; i.e., new resources
may be created, or existing ones modified, by the application of a
PATCH.

发现微信小程序不给用 PATCH 方法
https://mp.weixin.qq.com/debug/wxadoc/dev/api/network-request.html#wxrequestobject

默认为 GET,有效值:OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, CONNECT

MySQL 按照 in 排序

mysql> select * from auth_permission where id in (23, 4,12, 4,1);
+----+----------------------------+-----------------+-----------------------+
| id | name                       | content_type_id | codename              |
+----+----------------------------+-----------------+-----------------------+
|  1 | Can add bookmark           |               1 | add_bookmark          |
|  4 | Can add pinned application |               2 | add_pinnedapplication |
| 12 | Can delete permission      |               4 | delete_permission     |
| 23 | Can change session         |               8 | change_session        |
+----+----------------------------+-----------------+-----------------------+
4 rows in set (0.00 sec)

默认in查询结果集都会使用id排序

1. 使用field函数

FIELD(str,str1,str2,str3,...)
Returns the index (position) of str in the str1, str2, str3, ... list. Returns 0 if str is not found.

mysql> select * from auth_permission where id in (23, 4,12, 4,1) order by field(id,23,4,12,4,1);
+----+----------------------------+-----------------+-----------------------+
| id | name                       | content_type_id | codename              |
+----+----------------------------+-----------------+-----------------------+
| 23 | Can change session         |               8 | change_session        |
|  4 | Can add pinned application |               2 | add_pinnedapplication |
| 12 | Can delete permission      |               4 | delete_permission     |
|  1 | Can add bookmark           |               1 | add_bookmark          |
+----+----------------------------+-----------------+-----------------------+
4 rows in set (0.00 sec)

2. 使用关联查询

教务系统爬虫的微信小程序

之前在路由器上装的 node.js 运行环境运行的一个抓取脚本现在派上用了。

那么问题来了

1. GBK 编码


首先要解决的教务系统网站 GBK 编码问题,参考过去的记录 《node get post提交中文参数》


更新
发现微信的 wx.request(OBJECT) API 可以直接向 GBK 网站请求,返回的就是 UTF8 字符

wx.request({
  url: 'test.php',
  data: {
     x: '' ,
     y: ''
  },
  header: {
      'Content-Type': 'application/json'
  },
  success: function(res) {
    console.log(res.data) // 自动编码转换
  }
})

2. 使用 npm package

MINA 框架带有require函数加载依赖,但并不是完整的 CommonJS,require 函数仅仅能够加载项目中的文件,而且必须严格定义 JS 文件路径,路径不支持 CommonJS 的路径风格。

需要直接使用相对路径,并且需要指定后缀。

require('node_modules/lodash/map.js');

3. 获取二进制的图片对象

内置的 wx.request(OBJECT) 对象只有返回 Date 和 errorMSg 无法满足需求。

还好 JScore 环境依然提供了本地的 XMLHttpRequest 对象,可以直接调用原生办法。

var getBase64File = function( url, callback ) {
  var xhr = new XMLHttpRequest();
  xhr.responseType = 'blob';
  xhr.onload = function() {
    var reader = new FileReader();
    reader.onloadend = function() {
      var headers = xhr.getAllResponseHeaders();
      callback( reader.result, headers );
    }
    reader.readAsDataURL( xhr.response );
  };
  xhr.open( 'GET', url );
  xhr.send();
}

getBase64('test.jpg', function (base64, headers){
  console.log(headers);
}

4. 微信小程序跨域限制

这是从 Chrome 控制台看到的响应头

HTTP/1.1 200 OK
Date: Fri, 30 Sep 2016 12:46:33 GMT
Server: Microsoft-IIS/6.0
MicrosoftOfficeWebServer: 5.0_Pub
X-Powered-By: ASP.NET
X-AspNet-Version: 1.1.4322
Set-Cookie: ASP.NET_SessionId=hw4tpo55f4005ojii14d2e3r; path=/
Cache-Control: private
Content-Type: image/Gif; charset=gb2312
Content-Length: 2245

这是从 XMLHttpRequest.getAllResponseHeaders() 获取到的信息

Date: Fri, 30 Sep 2016 12:46:33 GMT
Server: Microsoft-IIS/6.0
X-AspNet-Version: 1.1.4322
X-Powered-By: ASP.NET
MicrosoftOfficeWebServer: 5.0_Pub
Content-Type: image/Gif; charset=gb2312
Access-Control-Allow-Origin: *
Cache-Control: private
Access-Control-Allow-Headers: X-Requested-With, Content-Type
Content-Length: 2245

浏览器同源策略,为了安全,同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式

CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

因为跨域限制,暂时没找到小程序去获取 Cookie 的办法,当然这里指的是是仅仅依靠小程序而不依赖自己的应用服务器去处理的情况(实际上小程序也不应当有过多的逻辑处理,仅仅当作一个显示的层面)。

5. Nginx 反向代理解决跨域问题

参考阮一峰的《跨域资源共享 CORS 详解》

解决方案是在服务端响应头加入允许跨域的字段说明

location ~/ {
    add_header 'Access-Control-Allow-Origin' 'https://docs.domain.com';  
    add_header 'Access-Control-Allow-Credentials' 'true';  
    add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, PATCH, OPTIONS'; 
    proxy_pass http://target.com;
}

如果需要匹配所有访问域名可以使用 add_header 'Access-Control-Allow-Origin' '*'

还是写个服务端吧,客户端不适合做这么多处理

黑客马拉松

QQ图片20161007204633.jpg

这几天参加了 ifanr 和 segmentfault 举办的未来小程序为主题的和黑客马拉松活动,作为一名志愿者围观了几十位参赛选手的开发过程,见识到了八个短短二十个小时内完成的设计别出心裁新颖的项目。

关于技术:

  1. ECMAScript 6 在 iOS 10 上出现兼容问题问题,模拟器上运行正常,真机演示却出现了问题;
  2. 限制访问域名,只有五个安全域名可以授权,可能需要反代解决外部资源引用的问题;
  3. 突出“小”的内容,微信小程序限制打包资源 1MB,如果使用图片资源最好使用矢量图或者使用适当的压缩,如果使用外部资源,也只能够提供 5MB 的本地存储,过多的资源也会导致首次使用的时候加载过慢;
  4. 由于还是在内测阶段,内置的地图控件(原生控件,不在 WebView)仅仅开放提供了定位显示的功能,根本无法添加其他视图层实现地理标签等功能

无关技术:

  1. 场地很有互联网公司的范,绿树掩映、陈旧厂房、新潮装修、文艺十足;
  2. 有一半参赛选手是学生,大一的新生表现突出,可见微信的想象力宽泛,早早影响到了初生代