简易实现
原理是通过sub_filter实现对callback的替换,具体配置如下:
nginx配置
location /www {
# 关键代码:使用参数中的callback替换数据文件中的特定字串
sub_filter callback_20181229161611 $arg_callback;
sub_filter_types application/json;
sub_filter_once on;
root html;
index index.html index.htm;
}
json文件
//要被替换的字符串
callback_20181229161611(
{
test: "ttlsa"
}
);
自适应实现
思路如下:
- 在location中检验请求参数是否含有callback字段:如有则rewrite到一个专门的jsonp location。
- 在上述的rewrite中加入originpath参数:用于记录原始路径。
- 在jsonp location中使用ssi为返回json包装外层callback函数。
- 在jsonp location中使用sub_filter替换callback函数名。
- 在jsonp location中使用include的virtual属性将原始的url包裹在返回json的内层。
- 为防止循环rewrite,在jsonp location中将原始url中的callback参数删除
location /www {
rewrite ^(.*)\;jsessionid=(.*)$ $1 break;
ssi on;
ssi_silent_errors on;
ssi_types application/json;
if ($query_string ~* %3c|%3e|%27 ){
return 403;
}
if ($query_string ~ [\\\;\$\'\(\)]+){
return 403;
}
if ($arg_callback) {
rewrite ^ /jsonp/test1.json?orginalpath=$uri last;
}
root ../WebContent;
index index.html index.htm;
}
location /jsonp {
rewrite ^(.*)\;jsessionid=(.*)$ $1 break;
ssi on;
ssi_silent_errors on;
ssi_types application/json;
if ($query_string ~* %3c|%3e|%27 ){
return 403;
}
if ($query_string ~ [\\\;\$\'\(\)]+){
return 403;
}
if ($args ~ "orginalpath=([^\&]*)\&(.*)callback=([^&]*)&?(.*)") {
set $original_path $1;
set $args1 $2;
set $callbackv $3;
set $args2 $4;
set $virtual_path "${original_path}?${args1}${args2}";
}
sub_filter callback_20181229161611 $callbackv;
sub_filter_types application/json;
sub_filter_once on;
root ../WebContent;
index index.html index.htm;
}
callback_20181229161611(
<!--# include virtual="$virtual_path" -->
);
去除sub_module的支持
由于sub_module不是默认模块,所以使用ssi方案进行替换,jsonp外壳json变成如下形式:
<!--# echo var="callbackv" default="no" -->(
<!--# include virtual="$virtual_path" -->
);