mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2026-10-14 10:44:27 +00:00
Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9be9b3345 | ||
|
|
6acb774c87 | ||
|
|
511515cae4 | ||
|
|
ab8b687837 |
@@ -461,7 +461,7 @@ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock containrrr/watchtow
|
|||||||
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
||||||
```shell
|
```shell
|
||||||
cd ~
|
cd ~
|
||||||
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v0.4.7/netdisk-fast-download-linux-amd64.zip
|
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/v0.4.8/netdisk-fast-download-linux-amd64.zip
|
||||||
unzip netdisk-fast-download.zip
|
unzip netdisk-fast-download.zip
|
||||||
cd netdisk-fast-download
|
cd netdisk-fast-download
|
||||||
bash service-install.sh
|
bash service-install.sh
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package cn.qaiu.parser.impl;
|
|||||||
import cn.qaiu.entity.FileInfo;
|
import cn.qaiu.entity.FileInfo;
|
||||||
import cn.qaiu.entity.ShareLinkInfo;
|
import cn.qaiu.entity.ShareLinkInfo;
|
||||||
import cn.qaiu.parser.PanBase;
|
import cn.qaiu.parser.PanBase;
|
||||||
|
import cn.qaiu.parser.TokenCache;
|
||||||
import cn.qaiu.util.AESUtils;
|
import cn.qaiu.util.AESUtils;
|
||||||
import cn.qaiu.util.AcwScV2Generator;
|
import cn.qaiu.util.AcwScV2Generator;
|
||||||
import cn.qaiu.util.CommonUtils;
|
import cn.qaiu.util.CommonUtils;
|
||||||
@@ -85,12 +86,31 @@ public class IzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
public IzTool(ShareLinkInfo shareLinkInfo) {
|
public IzTool(ShareLinkInfo shareLinkInfo) {
|
||||||
super(shareLinkInfo);
|
super(shareLinkInfo);
|
||||||
|
IzXffHeader.apply(header);
|
||||||
|
String accountId = "_default";
|
||||||
|
if (shareLinkInfo.getOtherParam().containsKey("auths")) {
|
||||||
|
MultiMap auths = (MultiMap) shareLinkInfo.getOtherParam().get("auths");
|
||||||
|
if (auths.contains("_configId")) {
|
||||||
|
accountId = auths.get("_configId");
|
||||||
|
} else if (auths.contains("username")) {
|
||||||
|
accountId = auths.get("username");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.cacheKey = TokenCache.key("iz", accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
String uuid = UUID.randomUUID().toString().toLowerCase(); // 也可以使用 UUID.randomUUID().toString()
|
String uuid = UUID.randomUUID().toString().toLowerCase(); // 也可以使用 UUID.randomUUID().toString()
|
||||||
|
|
||||||
public static volatile String token = null;
|
// 多账号隔离:用 TokenCache 代替 static 变量
|
||||||
public static volatile boolean authFlag = true;
|
private final String cacheKey;
|
||||||
|
|
||||||
|
private String token() {
|
||||||
|
return TokenCache.getToken(cacheKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean authFlag() {
|
||||||
|
return TokenCache.getFlag(cacheKey, true);
|
||||||
|
}
|
||||||
|
|
||||||
public Future<String> parse() {
|
public Future<String> parse() {
|
||||||
|
|
||||||
@@ -101,22 +121,21 @@ public class IzTool extends PanBase {
|
|||||||
// 检查并输出认证状态
|
// 检查并输出认证状态
|
||||||
if (shareLinkInfo.getOtherParam().containsKey("auths")) {
|
if (shareLinkInfo.getOtherParam().containsKey("auths")) {
|
||||||
boolean isTempAuth = shareLinkInfo.getOtherParam().containsKey("__TEMP_AUTH_ADDED");
|
boolean isTempAuth = shareLinkInfo.getOtherParam().containsKey("__TEMP_AUTH_ADDED");
|
||||||
|
String token = token();
|
||||||
log.info("文件解析检测到认证信息: isTempAuth={}, authFlag={}, token={}",
|
log.info("文件解析检测到认证信息: isTempAuth={}, authFlag={}, token={}",
|
||||||
isTempAuth, authFlag, token != null ? "已登录(" + token.substring(0, Math.min(8, token.length())) + "...)" : "未登录");
|
isTempAuth, authFlag(), token != null ? "已登录(" + token.substring(0, Math.min(8, token.length())) + "...)" : "未登录");
|
||||||
|
|
||||||
// 如果需要认证但还没有token,先执行登录
|
// 如果需要认证但还没有token,先执行登录
|
||||||
if ((isTempAuth || authFlag) && token == null) {
|
if ((isTempAuth || authFlag()) && token == null) {
|
||||||
log.info("文件解析需要登录,开始执行登录流程...");
|
log.info("文件解析需要登录,开始执行登录流程...");
|
||||||
MultiMap auths = (MultiMap) shareLinkInfo.getOtherParam().get("auths");
|
MultiMap auths = (MultiMap) shareLinkInfo.getOtherParam().get("auths");
|
||||||
return login(tsEncode, auths)
|
return login(tsEncode, auths)
|
||||||
.compose(v -> {
|
.recover(err -> {
|
||||||
log.info("文件解析预登录成功,继续解析流程");
|
// 预登录失败不终止解析,继续走免登录
|
||||||
return parseWithAuth(shareId, tsEncode);
|
log.warn("文件解析预登录失败: {},使用免登录模式", err.getMessage());
|
||||||
|
return Future.succeededFuture();
|
||||||
})
|
})
|
||||||
.onFailure(err -> {
|
.compose(v -> parseWithAuth(shareId, tsEncode));
|
||||||
log.warn("文件解析预登录失败: {},尝试使用免登录模式", err.getMessage());
|
|
||||||
// 登录失败,继续使用免登录模式
|
|
||||||
});
|
|
||||||
} else if (token != null) {
|
} else if (token != null) {
|
||||||
log.info("文件解析使用已有token: {}...", token.substring(0, Math.min(8, token.length())));
|
log.info("文件解析使用已有token: {}...", token.substring(0, Math.min(8, token.length())));
|
||||||
}
|
}
|
||||||
@@ -231,8 +250,8 @@ public class IzTool extends PanBase {
|
|||||||
// 检查是否为临时认证(临时认证每次都尝试登录)
|
// 检查是否为临时认证(临时认证每次都尝试登录)
|
||||||
boolean isTempAuth = shareLinkInfo.getOtherParam().containsKey("__TEMP_AUTH_ADDED");
|
boolean isTempAuth = shareLinkInfo.getOtherParam().containsKey("__TEMP_AUTH_ADDED");
|
||||||
// 如果是临时认证,或者是后台配置且authFlag为true,则尝试使用认证
|
// 如果是临时认证,或者是后台配置且authFlag为true,则尝试使用认证
|
||||||
if (isTempAuth || authFlag) {
|
if (isTempAuth || authFlag()) {
|
||||||
log.debug("尝试使用认证信息解析, isTempAuth={}, authFlag={}", isTempAuth, authFlag);
|
log.debug("尝试使用认证信息解析, isTempAuth={}, authFlag={}", isTempAuth, authFlag());
|
||||||
HttpRequest<Buffer> httpRequest =
|
HttpRequest<Buffer> httpRequest =
|
||||||
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL_VIP))
|
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL_VIP))
|
||||||
.setTemplateParam("fidEncode", fidEncode)
|
.setTemplateParam("fidEncode", fidEncode)
|
||||||
@@ -241,18 +260,19 @@ public class IzTool extends PanBase {
|
|||||||
.setTemplateParam("auth", auth)
|
.setTemplateParam("auth", auth)
|
||||||
.setTemplateParam("dataKey", dataKey);
|
.setTemplateParam("dataKey", dataKey);
|
||||||
MultiMap auths = (MultiMap) shareLinkInfo.getOtherParam().get("auths");
|
MultiMap auths = (MultiMap) shareLinkInfo.getOtherParam().get("auths");
|
||||||
if (token == null) {
|
if (token() == null) {
|
||||||
// 执行登录
|
// 执行登录,失败则回退免登录
|
||||||
login(tsEncode2, auths).onFailure(failRes-> {
|
login(tsEncode2, auths).onFailure(failRes-> {
|
||||||
log.warn("登录失败: {}", failRes.getMessage());
|
log.warn("登录失败,回退免登录: {}", failRes.getMessage());
|
||||||
fail(failRes.getMessage());
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
}).onSuccess(r-> {
|
}).onSuccess(r-> {
|
||||||
httpRequest.setTemplateParam("appToken", token)
|
httpRequest.setTemplateParam("appToken", token())
|
||||||
.putHeaders(header);
|
.putHeaders(header);
|
||||||
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 验证token
|
// 验证token — 先从缓存恢复到 header
|
||||||
|
header.set("appToken", token());
|
||||||
webClientSession.postAbs(UriTemplate.of(TOKEN_VERIFY_URL))
|
webClientSession.postAbs(UriTemplate.of(TOKEN_VERIFY_URL))
|
||||||
.setTemplateParam("uuid", uuid)
|
.setTemplateParam("uuid", uuid)
|
||||||
.setTemplateParam("ts", tsEncode2)
|
.setTemplateParam("ts", tsEncode2)
|
||||||
@@ -260,15 +280,15 @@ public class IzTool extends PanBase {
|
|||||||
// log.info("res: {}",asJson(res));
|
// log.info("res: {}",asJson(res));
|
||||||
if (asJson(res).getInteger("code") != 200) {
|
if (asJson(res).getInteger("code") != 200) {
|
||||||
login(tsEncode2, auths).onFailure(failRes -> {
|
login(tsEncode2, auths).onFailure(failRes -> {
|
||||||
log.warn("重新登录失败: {}", failRes.getMessage());
|
log.warn("重新登录失败,回退免登录: {}", failRes.getMessage());
|
||||||
fail(failRes.getMessage());
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
}).onSuccess(r-> {
|
}).onSuccess(r-> {
|
||||||
httpRequest.setTemplateParam("appToken", token)
|
httpRequest.setTemplateParam("appToken", token())
|
||||||
.putHeaders(header);
|
.putHeaders(header);
|
||||||
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
httpRequest.setTemplateParam("appToken", token)
|
httpRequest.setTemplateParam("appToken", token())
|
||||||
.putHeaders(header);
|
.putHeaders(header);
|
||||||
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
httpRequest.send().onSuccess(this::down).onFailure(handleFail("请求2"));
|
||||||
}
|
}
|
||||||
@@ -277,18 +297,17 @@ public class IzTool extends PanBase {
|
|||||||
} else {
|
} else {
|
||||||
// authFlag 为 false,使用免登录解析
|
// authFlag 为 false,使用免登录解析
|
||||||
log.debug("authFlag=false,使用免登录解析");
|
log.debug("authFlag=false,使用免登录解析");
|
||||||
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
.putHeaders(header)
|
|
||||||
.setTemplateParam("fidEncode", fidEncode)
|
|
||||||
.setTemplateParam("uuid", uuid)
|
|
||||||
.setTemplateParam("ts", tsEncode2)
|
|
||||||
.setTemplateParam("auth", auth)
|
|
||||||
.setTemplateParam("dataKey", dataKey).send()
|
|
||||||
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有认证信息,使用免登录解析
|
// 没有认证信息,使用免登录解析
|
||||||
log.debug("无认证信息,使用免登录解析");
|
log.debug("无认证信息,使用免登录解析");
|
||||||
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadAnonymous(String fidEncode, String tsEncode2, String auth, String dataKey) {
|
||||||
|
log.debug("使用免登录解析");
|
||||||
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
||||||
.putHeaders(header)
|
.putHeaders(header)
|
||||||
.setTemplateParam("fidEncode", fidEncode)
|
.setTemplateParam("fidEncode", fidEncode)
|
||||||
@@ -298,7 +317,6 @@ public class IzTool extends PanBase {
|
|||||||
.setTemplateParam("dataKey", dataKey).send()
|
.setTemplateParam("dataKey", dataKey).send()
|
||||||
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Future<Void> login(String tsEncode2, MultiMap auths) {
|
private Future<Void> login(String tsEncode2, MultiMap auths) {
|
||||||
Promise<Void> promise1 = Promise.promise();
|
Promise<Void> promise1 = Promise.promise();
|
||||||
@@ -310,8 +328,13 @@ public class IzTool extends PanBase {
|
|||||||
.onSuccess(res2->{
|
.onSuccess(res2->{
|
||||||
JsonObject json = asJson(res2);
|
JsonObject json = asJson(res2);
|
||||||
if (json.getInteger("code") == 200) {
|
if (json.getInteger("code") == 200) {
|
||||||
token = json.getJsonObject("data").getString("appToken");
|
String loginToken = json.getJsonObject("data").getString("appToken");
|
||||||
log.info("登录成功 token: {}...", token != null ? token.substring(0, Math.min(8, token.length())) : "null");
|
TokenCache.putToken(cacheKey, loginToken);
|
||||||
|
TokenCache.queueCachedTokenPersist(cacheKey, loginToken, System.currentTimeMillis() + 24 * 60 * 60 * 1000L);
|
||||||
|
if (loginToken != null) {
|
||||||
|
header.set("appToken", loginToken);
|
||||||
|
}
|
||||||
|
log.info("登录成功 token: {}...", loginToken != null ? loginToken.substring(0, Math.min(8, loginToken.length())) : "null");
|
||||||
promise1.complete();
|
promise1.complete();
|
||||||
} else {
|
} else {
|
||||||
// 检查是否为临时认证
|
// 检查是否为临时认证
|
||||||
@@ -323,7 +346,7 @@ public class IzTool extends PanBase {
|
|||||||
} else {
|
} else {
|
||||||
// 后台配置的认证失败,设置authFlag并返回失败,让下次请求使用免登陆解析
|
// 后台配置的认证失败,设置authFlag并返回失败,让下次请求使用免登陆解析
|
||||||
log.warn("后台配置认证失败: {}, authFlag将设为false,请重新解析", json.getString("msg"));
|
log.warn("后台配置认证失败: {}, authFlag将设为false,请重新解析", json.getString("msg"));
|
||||||
authFlag = false;
|
TokenCache.putFlag(cacheKey, false);
|
||||||
promise1.fail("认证失败: " + json.getString("msg") + ", 请重新解析将使用免登陆模式");
|
promise1.fail("认证失败: " + json.getString("msg") + ", 请重新解析将使用免登陆模式");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -691,7 +714,6 @@ public class IzTool extends PanBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void resetToken() {
|
public static void resetToken() {
|
||||||
token = null;
|
TokenCache.removeByDiskType("iz");
|
||||||
authFlag = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ public class IzToolWithAuth extends PanBase {
|
|||||||
}
|
}
|
||||||
public IzToolWithAuth(ShareLinkInfo shareLinkInfo) {
|
public IzToolWithAuth(ShareLinkInfo shareLinkInfo) {
|
||||||
super(shareLinkInfo);
|
super(shareLinkInfo);
|
||||||
|
IzXffHeader.apply(header);
|
||||||
}
|
}
|
||||||
|
|
||||||
String uuid = UUID.randomUUID().toString().toLowerCase(); // 也可以使用 UUID.randomUUID().toString()
|
String uuid = UUID.randomUUID().toString().toLowerCase(); // 也可以使用 UUID.randomUUID().toString()
|
||||||
@@ -213,8 +214,8 @@ public class IzToolWithAuth extends PanBase {
|
|||||||
if (token == null) {
|
if (token == null) {
|
||||||
// 执行登录
|
// 执行登录
|
||||||
login(tsEncode2, auths).onFailure(failRes-> {
|
login(tsEncode2, auths).onFailure(failRes-> {
|
||||||
log.warn("登录失败: {}", failRes.getMessage());
|
log.warn("登录失败,回退免登录: {}", failRes.getMessage());
|
||||||
fail(failRes.getMessage());
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
}).onSuccess(r-> {
|
}).onSuccess(r-> {
|
||||||
httpRequest.setTemplateParam("appToken", token)
|
httpRequest.setTemplateParam("appToken", token)
|
||||||
.putHeaders(header);
|
.putHeaders(header);
|
||||||
@@ -229,8 +230,8 @@ public class IzToolWithAuth extends PanBase {
|
|||||||
// log.info("res: {}",asJson(res));
|
// log.info("res: {}",asJson(res));
|
||||||
if (asJson(res).getInteger("code") != 200) {
|
if (asJson(res).getInteger("code") != 200) {
|
||||||
login(tsEncode2, auths).onFailure(failRes -> {
|
login(tsEncode2, auths).onFailure(failRes -> {
|
||||||
log.warn("重新登录失败: {}", failRes.getMessage());
|
log.warn("重新登录失败,回退免登录: {}", failRes.getMessage());
|
||||||
fail(failRes.getMessage());
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
}).onSuccess(r-> {
|
}).onSuccess(r-> {
|
||||||
httpRequest.setTemplateParam("appToken", token)
|
httpRequest.setTemplateParam("appToken", token)
|
||||||
.putHeaders(header);
|
.putHeaders(header);
|
||||||
@@ -246,18 +247,17 @@ public class IzToolWithAuth extends PanBase {
|
|||||||
} else {
|
} else {
|
||||||
// authFlag 为 false,使用免登录解析
|
// authFlag 为 false,使用免登录解析
|
||||||
log.debug("authFlag=false,使用免登录解析");
|
log.debug("authFlag=false,使用免登录解析");
|
||||||
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
.putHeaders(header)
|
|
||||||
.setTemplateParam("fidEncode", fidEncode)
|
|
||||||
.setTemplateParam("uuid", uuid)
|
|
||||||
.setTemplateParam("ts", tsEncode2)
|
|
||||||
.setTemplateParam("auth", auth)
|
|
||||||
.setTemplateParam("dataKey", dataKey).send()
|
|
||||||
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 没有认证信息,使用免登录解析
|
// 没有认证信息,使用免登录解析
|
||||||
log.debug("无认证信息,使用免登录解析");
|
log.debug("无认证信息,使用免登录解析");
|
||||||
|
downloadAnonymous(fidEncode, tsEncode2, auth, dataKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void downloadAnonymous(String fidEncode, String tsEncode2, String auth, String dataKey) {
|
||||||
|
log.debug("使用免登录解析");
|
||||||
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
webClientSession.getAbs(UriTemplate.of(SECOND_REQUEST_URL))
|
||||||
.putHeaders(header)
|
.putHeaders(header)
|
||||||
.setTemplateParam("fidEncode", fidEncode)
|
.setTemplateParam("fidEncode", fidEncode)
|
||||||
@@ -267,7 +267,6 @@ public class IzToolWithAuth extends PanBase {
|
|||||||
.setTemplateParam("dataKey", dataKey).send()
|
.setTemplateParam("dataKey", dataKey).send()
|
||||||
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
.onSuccess(this::down).onFailure(handleFail("请求2"));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private Future<Void> login(String tsEncode2, MultiMap auths) {
|
private Future<Void> login(String tsEncode2, MultiMap auths) {
|
||||||
Promise<Void> promise1 = Promise.promise();
|
Promise<Void> promise1 = Promise.promise();
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package cn.qaiu.parser.impl;
|
||||||
|
|
||||||
|
import io.vertx.core.MultiMap;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.concurrent.ThreadLocalRandom;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 蓝奏云优享 X-Forwarded-For 配置。
|
||||||
|
* <p>
|
||||||
|
* 读取系统属性 {@code nfd.iz.xff},其次环境变量 {@code NFD_IZ_XFF}:
|
||||||
|
* <ul>
|
||||||
|
* <li>未设置 / 空 / {@code off}:不发送该头(默认)</li>
|
||||||
|
* <li>{@code random}:每次创建解析器时随机一个国内常见网段 IP</li>
|
||||||
|
* <li>其它值:原样作为头的值,例如 {@code 113.96.181.18}</li>
|
||||||
|
* </ul>
|
||||||
|
*/
|
||||||
|
public final class IzXffHeader {
|
||||||
|
|
||||||
|
public static final String PROP = "nfd.iz.xff";
|
||||||
|
public static final String ENV = "NFD_IZ_XFF";
|
||||||
|
private static final String HEADER = "X-Forwarded-For";
|
||||||
|
|
||||||
|
/** 国内运营商常见 /8 段首字节 */
|
||||||
|
private static final int[] CN_PREFIX = {36, 39, 42, 58, 59, 60, 61, 101, 106, 110, 111, 112, 113, 114,
|
||||||
|
115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 175, 180, 182, 183, 202, 210, 211, 218, 219, 220, 221, 222, 223};
|
||||||
|
|
||||||
|
private IzXffHeader() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static String configured() {
|
||||||
|
String v = System.getProperty(PROP);
|
||||||
|
if (StringUtils.isBlank(v)) {
|
||||||
|
v = System.getenv(ENV);
|
||||||
|
}
|
||||||
|
return v == null ? "" : v.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 根据配置得到头的值,返回 null 表示不发送 */
|
||||||
|
static String resolve(String mode) {
|
||||||
|
if (StringUtils.isBlank(mode) || "off".equalsIgnoreCase(mode)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if ("random".equalsIgnoreCase(mode)) {
|
||||||
|
ThreadLocalRandom r = ThreadLocalRandom.current();
|
||||||
|
return CN_PREFIX[r.nextInt(CN_PREFIX.length)] + "." + r.nextInt(256) + "." + r.nextInt(256) + "." + (1 + r.nextInt(254));
|
||||||
|
}
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 按当前配置写入或移除请求头 */
|
||||||
|
public static void apply(MultiMap headers) {
|
||||||
|
String value = resolve(configured());
|
||||||
|
if (value == null) {
|
||||||
|
headers.remove(HEADER);
|
||||||
|
} else {
|
||||||
|
headers.set(HEADER, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package cn.qaiu.parser.impl;
|
||||||
|
|
||||||
|
import io.vertx.core.MultiMap;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
public class IzXffHeaderTest {
|
||||||
|
@Test
|
||||||
|
public void offByDefault() {
|
||||||
|
assertNull(IzXffHeader.resolve(null));
|
||||||
|
assertNull(IzXffHeader.resolve(""));
|
||||||
|
assertNull(IzXffHeader.resolve("OFF"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void literalAndRandom() {
|
||||||
|
assertEquals("113.96.181.18", IzXffHeader.resolve("113.96.181.18"));
|
||||||
|
String ip = IzXffHeader.resolve("random");
|
||||||
|
assertTrue(ip, ip.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void applyRemovesWhenOff() {
|
||||||
|
MultiMap h = MultiMap.caseInsensitiveMultiMap().set("X-Forwarded-For", "1.1.1.1");
|
||||||
|
System.clearProperty(IzXffHeader.PROP);
|
||||||
|
if (System.getenv(IzXffHeader.ENV) == null) {
|
||||||
|
IzXffHeader.apply(h);
|
||||||
|
assertFalse(h.contains("X-Forwarded-For"));
|
||||||
|
}
|
||||||
|
System.setProperty(IzXffHeader.PROP, "8.8.8.8");
|
||||||
|
IzXffHeader.apply(h);
|
||||||
|
assertEquals("8.8.8.8", h.get("X-Forwarded-For"));
|
||||||
|
System.clearProperty(IzXffHeader.PROP);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@
|
|||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>0.4.7</revision>
|
<revision>0.4.8</revision>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
<maven.compiler.source>17</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>17</maven.compiler.target>
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "nfd-web",
|
"name": "nfd-web",
|
||||||
"version": "0.4.7",
|
"version": "0.4.8",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"serve": "vue-cli-service serve",
|
"serve": "vue-cli-service serve",
|
||||||
|
|||||||
Reference in New Issue
Block a user