Fork me on GitHub
image frame

personal notes by mankitty

时间过去,总会丢掉些什么,也总会留下些什么,但留下的必定是最真的东西

OpenWrt 之setfilehandler函数详解

setfilehandler原型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
local fp,fsname
luci.http.setfilehandler(
function(meta, chunk, eof)
-- 防止每一次进入回调函数的时候都执行打开文件的操作
if not fp and not fsname then
if meta and meta.name == "image" then
fp = io.open(image_tmp, "w")
end
end

fsname = true

-- 如果文件流存在,那么将文件流写进文件中
if chunk and fp then fp:write(chunk) end
-- 如果文件已经读取完毕,关闭文件描述符
if eof and fp then fp:close() end
end
)

setfilehandler注意事项

[1]. 在使用该接口之前不能有任何非声明语句的存在
[2]. 在回调函数中有三个参数,分别为meta(包含上传文件的各种信息),chunk(文件流),eof(文件结束标志)
[3]. meta参数
其中,meta具有以下几个参数

1
2
3
4
5
6
["file"] = "xxx-180611.f3.e1f7.bin"	--上传文件的文件名
["name"] = "version" --html控件中的name属性
["headers"] = { --headers属性
["Content-Disposition"] = "form-data; name=\"version\"; filename=\"xxx-180611.f3.e1f7.bin\""
["Content-Type"] = "application/octet-stream"
}

OpenWrt 页面登录认证

页面登录简介

Openwrt在登录的时候默认会寻找相应的index.lua文件,寻找到节点,执行方法
在用户登录的时候,默认会寻找到/usr/lib/lua/luci/controller/admin/index.lua文件,内容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
module("luci.controller.admin.index", package.seeall)

function index()
local root = node()
if not root.target then
root.target = alias("admin")
root.index = true
end

local page = node("admin")
page.target = firstchild()
page.title = _("Administration")
page.order = 10
page.sysauth = luci.sys.user.getloginusers() --获取登录的用户名
page.sysauth_authenticator = "htmlauth" --使用dispatcher.lua文件中定义的htmlauth方法验证用户的合法性
page.ucidata = true
page.index = true

-- Empty services menu to be populated by addons
entry({"admin", "services"}, firstchild(), _("Services"), 40).index = true
end

OpenWrt 页面添加相关介绍

MVC框架

模型(Model) 用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法。
视图(View) 能够实现数据有目的的显示。
控制器(Controller) 可以起到不同层面间的组织作用,用于控制应用程序的流程。主要是可以将Model以及View层紧密的连接起来
这三层是相互独立而又紧密联系的,MVC在我看来是可以更好的实现数据与逻辑等的分离。

OpenWrt 创建页面

OpenWrt也是采用上述的MVC框架,即Model-View-Controller

模块注册

module(“luci.controller.admin.network”, package.seeall) -–模块入口
这行标识了模块的入口,其中luci.controller.admin.network定义了模块注册所在的文件路径,上述的路径为/usr/lib/lua/luci/controller/admin/network.lua

节点注册

节点的注册我了解的有两种方法,其实这两种方法我在使用的时候并没有发现什么大的区别

1
2
3
4
5
6
7
8
9
10
[1]. entry 方法
local page
page = entry({"admin", "network", "hosts"}, cbi("admin_network/hosts"), _("Static Domain"),40)
page.leaf = true
[2]. node 方法
local page
page = node("admin", "network", "hosts")
page.target = cbi("admin_network/hosts")
page.title = _("Static Domain")
page.order = 40

参数解释

entry的原型为:entry(path, target, title=nil, order=nil)
path:定义了节点的路径,即页面访问时的url路径
target:调用的方法,大致上可以分为以下几种
[1]. call,直接调用指定的函数,比如写为"call("function_name")",然后在对该函数做具体的定义就可以调用了。
[2]. cbi,调用Model层的一些方法,比如写为"cbi("admin_network/hosts")"就可以调用/usr/lib/lua/luci/model/cbi/admin_network/hosts.lua文件,这里通常是对业务逻辑的相关处理。
[3]. template,调用指定的页面,比如写为“template("admin_network/login")”就可以调用/usr/lib/lua/luci/view/admin_network/login.htm文件了
[4]. alias,使用别名,即当你点击了某个菜单,相应的动作是另外一个菜单的入口,那么就使用alias来指明另外路口的路径,如:entry({"admin", "advanced"}, alias("admin", "advanced", "ddns"), _("Advanced"), 5)),表示节点("admin", "advanced", "ddns")是节点{"sixing", "advanced"}的别名
[5]. arcombine,暂时没弄的太明白,文档上介绍 Create a combined dispatching target for non argv and argv requests
title:菜单对外显示的名称
order:菜单栏显示的顺序

数据库文件

默认情况下,数据存储都是放在/etc/config目录下,存储格式以及调用接口等可参考 UCI-System-学习之路

Nginx代理模块

proxy基本设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
server {
listen 24742;

resolver 127.0.0.1;
server_name localhost;

location = / {
proxy_pass http://xxx/yy/index.htm;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

location ~* (.*)\.apk {
proxy_pass http://xxx;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
参数解释:
proxy_pass

常用参数

proxy_buffer_size

语法: proxy_buffer_size the_size
默认值: proxy_buffer_size 4k/8k
上下文: http, server, location
该指令设置缓冲区大小,从被代理的后端服务器取得的响应内容,会先读取放置到这里

proxy_set_header X-real-ip $remote_add

含义:通过X-real-ip可以获取到客户端真正的IP地址

proxy_add_x_forwarded_for

NGINX even provides a $proxy_add_x_forwarded_for variable to automatically append $remote_addr to any incoming X-Forwarded-For headers.
Traditionally, an HTTP reverse proxy uses non-standard headers to inform the upstream server about the user’s IP address and other request properties:

X-Forwarded-For: 12.34.56.78, 23.45.67.89
X-Real-IP: 12.34.56.78
X-Forwarded-Host: example.com
X-Forwarded-Proto: https

Examples

sub_filter_once on;
sub_filter <body ‘www.baidu.com<body’;

nginx sub_filter 模块

sub_filter简介

官方文档上有明确的介绍
The ngx_http_sub_module module is a filter that modifies a response by replacing one specified string by another.
This module is not built by default, it should be enabled with the –with-http_sub_module configuration parameter.

主要指令

sub_filter_once

1
2
3
4
Syntax:	sub_filter_once on | off;
Default:
sub_filter_once on;
Context:http, server, location

Indicates whether to look for each string to replace once or repeatedly.

sub_filter_types

1
2
3
4
Syntax:	sub_filter_types mime-type ...;
Default:
sub_filter_types text/html;
Context:http, server, location

Enables string replacement in responses with the specified MIME types in addition to “text/html”. The special value “*” matches any MIME type (0.8.29)

sub_filter

Syntax: sub_filter string replacement;
Default: —
Context: http, server, location
Sets a string to replace and a replacement string. The string to replace is matched ignoring the case. The string to replace (1.9.4) and replacement string can contain variables. Several sub_filter directives can be specified on one configuration level (1.9.4). These directives are inherited from the previous level if and only if there are no sub_filter directives defined on the current level.

Example Configuration

1
2
3
4
5
location / {
sub_filter '<a href="http://127.0.0.1:8080/' '<a href="https://$host/';
sub_filter '<img src="http://127.0.0.1:8080/' '<img src="https://$host/';
sub_filter_once on;
}

sub_filter_last_modified

Syntax: sub_filter_last_modified on | off;
Default:
sub_filter_last_modified off;
Context: http, server, location
This directive appeared in version 1.5.1.

Allows preserving the “Last-Modified” header field from the original response during replacement to facilitate response caching.

By default, the header field is removed as contents of the response are modified during processing.

nginx规则匹配

location 匹配规则

具体规则

~ #波浪线表示执行一个正则匹配,区分大小写
* #表示执行一个正则匹配,不区分大小写
^
#^~表示普通字符匹配,如果该选项匹配,只匹配该选项,不匹配别的选项,一般用来匹配目录
= #进行普通字符精确匹配
@ #”@” 定义一个命名的 location,使用在内部定向时,例如 error_page, try_files

规则优先级

等号类型(=)的优先级最高,如果匹配成功,则不再查找其他匹配项
^类型表达式,如果匹配成功,则不再查找其他匹配项
正则表达式类型(
~*)的优先级次之,如果有多个location的正则能匹配的话,则使用正则表达式最长的那个
常规字符串匹配类型,按前缀匹配

rewrite语法

last : 相当于Apache的[L]标记,表示完成rewrite
break : 停止执行当前虚拟主机的后续rewrite指令集
redirect : 返回302临时重定向,地址栏会显示跳转后的地址
permanent : 返回301永久重定向,地址栏会显示跳转后的地址

last和break区别

last一般写在server和if中,而break一般使用在location中
last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
break和last都能阻止继续执行后面的rewrite指令

常用正则

‘.’ : 匹配除换行符以外的任意字符
‘?’ : 重复0次或1次
‘+’ : 重复1次或更多次
‘*’ : 重复0次或更多次
‘\d’ :匹配数字
‘^’ : 匹配字符串的开始
‘$’ : 匹配字符串的介绍
{n}’ : 重复n次
{n,} : 重复n次或更多次
[c] : 匹配单个字符c
[a-z] : 匹配a-z小写字母的任意一个
注意:小括号()之间匹配的内容,可以在后面通过$1来引用,$2表示的是前面第二个()里的内容

##全局变量
下面是可以用作if判断的全局变量
$args : #这个变量等于请求行中的参数,同$query_string
$content_length : 请求头中的Content-length字段。
$content_type : 请求头中的Content-Type字段。
$document_root : 当前请求在root指令中指定的值。
$host : 请求主机头字段,否则为服务器名称。
$http_user_agent : 客户端agent信息
$http_cookie : 客户端cookie信息
$limit_rate : 这个变量可以限制连接速率。
$request_method : 客户端请求的动作,通常为GET或POST。
$remote_addr : 客户端的IP地址。
$remote_port : 客户端的端口。
$remote_user : 已经经过Auth Basic Module验证的用户名。
$request_filename : 当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : HTTP方法(如http,https)。
$server_protocol : 请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr : 服务器地址,在完成一次系统调用后可以确定这个值。
$server_name : 服务器名称。
$server_port : 请求到达服务器的端口号。
$request_uri : 包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri : 不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri : 与$uri相同。

全局变量使用举例

1
2
3
4
5
6
7
http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$document_uri:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php

##Rewrite使用举例

1
2
3
4
5
6
7
http://newhouse.bb.house365.com/tool/tiqian/跳转到http://bb.house365.com/tool/tiqian/
nginx正则匹配$host进行跳转的方法
if ($host ~* ^newhouse\.(.+)?\.house365\.com) {
set $host_city $1;
rewrite ^(.*)$ http://$host_city.house365.com$1 permanent;
}
rewrite ^/images/(.*)_(\d+)x(\d+)\.(png|jpg|gif)$ /resizer/$1.$4?width=$2&height=$3? last;

##Location匹配规则
###规则一

1
2
3
4
仅仅匹配"/",若是匹配到,停止匹配
location = / {
[configuration A]
}

###规则二

1
2
3
4
匹配任何请求,因为所有请求都是以"/"开始,所以所有的请求最终都会匹配到,但是更长字符匹配或者正则表达式匹配会优先匹配
location / {
[configuration B]
}

###规则三

1
2
3
4
匹配任何以/images/开始的请求,并停止匹配其它location
location ^~ /images/ {
[configuration C]
}

###规则四

1
2
3
4
匹配以 gif, jpg, or jpeg结尾的请求,但是所有/images/目录的请求将由[Configuration C]处理,所以规则四要比规则三的优先级要低
location ~* .(gif|jpg|jpeg)$ {
[configuration D]
}

UCI System 学习之路

UCI System

简介

UCI是Unified Configuration Interface的缩写,目的是集中管理OpenWrt设备中各个模块的配置。

基本原则

OpenWrt中主要的数据文件默认都是独立的存放在/etc/config/目录中,当然,你也可以单独的指定特
殊的目录存储它们。修改或者设定文件内容的方法有很多,例如可以通过uci命令或者API(例如SHELL,
LUA以及C)来修改,WEB GUI即可以通过LuCI来修改。
当数据文件被修改的时候,需要与之相关的servic才能让修改的数据文件被重新加载。

模型演示

image

UCI usage

root@CGW4000T:~# uci
Usage: uci [] []

Commands:
    batch
    export     [<config>]
    import     [<config>]
    changes    [<config>]
    commit     [<config>]
    add        <config> <section-type>
    add_list   <config>.<section>.<option>=<string>
    del_list   <config>.<section>.<option>=<string>
    show       [<config>[.<section>[.<option>]]]
    get        <config>.<section>[.<option>]
    set        <config>.<section>[.<option>]=<value>
    delete     <config>[.<section>[[.<option>][=<id>]]]
    rename     <config>.<section>[.<option>]=<name>
    revert     <config>[.<section>[.<option>]]
    reorder    <config>.<section>=<position>

Options:
    -c <path>  set the search path for config files (default: /etc/config)
    -d <str>   set the delimiter for list values in uci show
    -f <file>  use <file> as input instead of stdin
    -m         when importing, merge data into an existing package
    -n         name unnamed sections on export (default)
    -N         don't name unnamed sections
    -p <path>  add a search path for config change files
    -P <path>  add a search path for config change files and use as default
    -q         quiet mode (don't print error messages)
    -s         force strict mode (stop on parser errors, default)
    -S         disable strict mode
    -X         do not use extended syntax on 'show'

API

Lua API

实例化uci上下文

local x = luci.model.uci.cursor()

x:set("config","name","type") --增加一个section
x:set("config","sectionname","option","exp") --在section下增加配置
参数说明
config --- 配置文件的名字,配置文件位于/etc/config/下
name --- 配置文件中某个类型的具体名字
type --- 配置文件中类型(type)
option --- 具体配置
exp --- 配置文件中具体参数类型的值

x:delete("config","section") --删除section
x:delete("config,"section","option") -- 在section下删除option

使用'增'中的API即可修改各参数的值

x:foreach("config","type","function(s) ... end") -- 遍历整个config文件
x:get("config","sectionname","option") ---获得option的值
特别解释
在foreach中有两个变量,分别为s[".type"](section type),以及s[".name"](section name),其中
s[".type"]可以没有,但是s[".name"]一定是存在的,遍历时通常都是采用s[".name"]

Shell API

获取

config_get var_name setction_name option_name <default>
参数说明
var_name:        用来存放option值的变量。
settion_name:    就是section 的名字
option_name:    就是option的名字

设置

config_set用来配置config值,命令格式如下:
config_set section_name option_name var_name
参数说明
var_name:        用来存放option值的变量。
settion_name:    就是section 的名字
option_name:    就是option的名字

遍历

config_foreach callback_func section_type <customer_val>
callback_func就是回调函数,它有2个参数,第一个是section type,如果有定义customer_val,那么第二个就是customer_val。我们可以在config_foreach里调用config_get与config_set
  • © 2015-2020 Mankitty
  • Powered by Hexo Theme Ayer
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信