mirror of
https://github.com/qaiu/netdisk-fast-download.git
synced 2025-12-16 12:23:03 +00:00
Compare commits
16 Commits
0.1.6-rele
...
0.1.7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da063461be | ||
|
|
3234f643d5 | ||
|
|
332cc587a2 | ||
|
|
b30d01e154 | ||
|
|
79d8aa0868 | ||
|
|
a724d703ed | ||
|
|
18478b2a0b | ||
|
|
dde54ed9cc | ||
|
|
3c56a7183e | ||
|
|
38a3ae8a56 | ||
|
|
00b30331eb | ||
|
|
8397c24715 | ||
|
|
3ee113e81f | ||
|
|
cde641c8db | ||
|
|
30cd2f5850 | ||
|
|
71066ded98 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -38,3 +38,4 @@ gradlew
|
||||
gradlew.bat
|
||||
unused.txt
|
||||
/web-service/src/main/generated/
|
||||
/db
|
||||
|
||||
23
README.md
23
README.md
@@ -1,4 +1,5 @@
|
||||
# netdisk-fast-download
|
||||
云盘解析服务 (nfd云解析)
|
||||
预览地址 https://lz.qaiu.top
|
||||
|
||||
[](https://github.com/qaiu/netdisk-fast-download/actions/workflows/maven.yml)
|
||||
@@ -6,9 +7,17 @@
|
||||
[](https://vertx-china.github.io/)
|
||||
[](https://github.com/qaiu/netdisk-fast-download/releases/tag/0.1.6-releases)
|
||||
|
||||
## 网盘支持情况:
|
||||
> 20230722 UC网盘解析失效,需要登录
|
||||
## 项目介绍
|
||||
网盘直链解析工具能把网盘分享下载链接转化为直链,已支持蓝奏云/奶牛快传/移动云云空间/小飞机盘/亿方云/123云盘等,支持私密分享。
|
||||
|
||||
## 应用场景:
|
||||
1. 游戏:使用本站工具可自动生成高速直流下载器,用于游戏客户端自动化高速下载安装、更新等。
|
||||
2. 下载:可根据网盘分享的地址解析为直链,方便放到自己网站上供用户下载,节约服务器带宽和磁盘。
|
||||
3. 音视频:可解析为音视频直链,可直接在网页上播放,高清,高速,节约服务器带宽和磁盘。
|
||||
|
||||
## 网盘支持情况:
|
||||
> 20230722 UC网盘解析失效,需要登录
|
||||
> 20230824 123云盘解析大文件(>100MB)失效,需要登录
|
||||
|
||||
`网盘名称(网盘标识):`
|
||||
|
||||
@@ -149,9 +158,9 @@ mvn package
|
||||
> 注意: netdisk-fast-download.service中的ExecStart的路径改为实际路径
|
||||
```shell
|
||||
cd ~
|
||||
wget -O netdisk-fast-download-0.1.6-bin.zip https://github.com/qaiu/netdisk-fast-download/releases/download/0.1.6-releases/netdisk-fast-download-0.1.6-bin.zip
|
||||
unzip netdisk-fast-download-*-bin.zip
|
||||
cd netdisk-fast-download-*-bin
|
||||
wget -O netdisk-fast-download.zip https://github.com/qaiu/netdisk-fast-download/releases/download/0.1.7/netdisk-fast-download.zip
|
||||
unzip netdisk-fast-download.zip
|
||||
cd netdisk-fast-download
|
||||
bash service-install.sh
|
||||
```
|
||||
服务相关命令:
|
||||
@@ -175,8 +184,8 @@ systemctl enable netdisk-fast-download.servic
|
||||
systemctl disable netdisk-fast-download.servic
|
||||
|
||||
## Windows服务部署
|
||||
1. 下载并解压releases版本netdisk-fast-download-0.1.6-bin.zip
|
||||
2. 进入netdisk-fast-download-0.1.6-bin目录
|
||||
1. 下载并解压releases版本netdisk-fast-download.zip
|
||||
2. 进入netdisk-fast-download下的bin目录
|
||||
3. 使用管理员权限运行nfd-service-install.bat
|
||||
如果不想使用服务运行可以直接运行run.bat
|
||||
> 注意: 如果jdk环境变量的java版本不是17请修改nfd-service-template.xml中的java命令的路径改为实际路径
|
||||
|
||||
@@ -8,7 +8,7 @@ Wants=network-online.target
|
||||
Type=simple
|
||||
# User=USER
|
||||
# 需要JDK17及以上版本 注意修改为自己的路径
|
||||
ExecStart=/root/java/jdk-17.0.2/bin/java -server -Xmx128m -jar /root/java/netdisk-fast-download-0.1.6/netdisk-fast-download-0.1.6.jar
|
||||
ExecStart=/root/java/jdk-17.0.2/bin/java -server -Xmx128m -jar /root/java/netdisk-fast-download/netdisk-fast-download.jar
|
||||
ExecStop=/bin/kill -s QUIT $MAINPID
|
||||
Restart=always
|
||||
StandOutput=syslog
|
||||
|
||||
@@ -7,7 +7,7 @@ pushd %~dp0
|
||||
set MY_DIR=%~dp0
|
||||
set MY_DIR=%MY_DIR:~0,-1%
|
||||
|
||||
for /f "delims=X" %%i in ('dir /b %MY_DIR%\netdisk-fast-download-*.jar') do (
|
||||
for /f "delims=X" %%i in ('dir /b %MY_DIR%\netdisk-fast-download.jar') do (
|
||||
set LAUNCH_JAR=%MY_DIR%\%%i
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
@echo off && @chcp 65001 > nul
|
||||
pushd %~dp0
|
||||
set LIB_DIR=%~dp0
|
||||
for /f "delims=X" %%i in ('dir /b %LIB_DIR%\netdisk-fast-download-*.jar') do (
|
||||
for /f "delims=X" %%i in ('dir /b %LIB_DIR%\netdisk-fast-download.jar') do (
|
||||
set LAUNCH_JAR=%LIB_DIR%%%i
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# set -x
|
||||
LAUNCH_JAR="netdisk-fast-download-0.1.6.jar"
|
||||
LAUNCH_JAR="netdisk-fast-download.jar"
|
||||
nohup java -Xmx512M -jar "$LAUNCH_JAR" "$@" >startup.log 2>&1 &
|
||||
tail -f startup.log
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>netdisk-fast-download</artifactId>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<version>0.1.6</version>
|
||||
<version>0.1.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package cn.qaiu;
|
||||
|
||||
public class StartH2DatabaseServer {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public class CreateTable {
|
||||
javaProperty2SqlColumnMap.put(Boolean.class, "BOOLEAN");
|
||||
javaProperty2SqlColumnMap.put(String.class, "VARCHAR");
|
||||
javaProperty2SqlColumnMap.put(java.util.Date.class, "TIMESTAMP");
|
||||
javaProperty2SqlColumnMap.put(java.time.LocalDateTime.class, "TIMESTAMP");
|
||||
javaProperty2SqlColumnMap.put(java.sql.Timestamp.class, "TIMESTAMP");
|
||||
javaProperty2SqlColumnMap.put(java.sql.Date.class, "DATE");
|
||||
javaProperty2SqlColumnMap.put(java.sql.Time.class, "TIME");
|
||||
@@ -157,8 +158,8 @@ public class CreateTable {
|
||||
return sql.substring(0, sql.length() - 1) + ");\r\n";
|
||||
}
|
||||
|
||||
public static void createTable(JDBCPool pool, String tableClassPath) {
|
||||
Set<Class<?>> tableClassList = ReflectionUtil.getReflections(tableClassPath).getTypesAnnotatedWith(Table.class);
|
||||
public static void createTable(JDBCPool pool) {
|
||||
Set<Class<?>> tableClassList = ReflectionUtil.getReflections().getTypesAnnotatedWith(Table.class);
|
||||
if (tableClassList.isEmpty()) LOGGER.info("Table model class not fount");
|
||||
tableClassList.forEach(clazz -> {
|
||||
String createTableSQL = getCreateTableSQL(clazz);
|
||||
|
||||
@@ -92,7 +92,7 @@ public class JDBCPoolInit {
|
||||
private void poolInitExecute(Promise<String> promise) {
|
||||
// 初始化连接池
|
||||
pool = JDBCPool.pool(vertx, dbConfig);
|
||||
CreateTable.createTable(pool, dbConfig.getString("tableClassPath"));
|
||||
CreateTable.createTable(pool);
|
||||
promise.complete("init jdbc pool success");
|
||||
|
||||
}
|
||||
|
||||
17
core/pom.xml
17
core/pom.xml
@@ -5,21 +5,14 @@
|
||||
<parent>
|
||||
<artifactId>netdisk-fast-download</artifactId>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<version>0.1.6</version>
|
||||
<version>0.1.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>1.0.8</version>
|
||||
<artifactId>core</artifactId>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<vertx.version>4.4.1</vertx.version>
|
||||
<org.reflections.version>0.10.2</org.reflections.version>
|
||||
<lombok.version>1.18.12</lombok.version>
|
||||
<slf4j.version>2.0.5</slf4j.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<jackson.version>2.14.2</jackson.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
@@ -39,7 +32,7 @@
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
@@ -90,6 +83,12 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.datatype</groupId>
|
||||
<artifactId>jackson-datatype-jsr310</artifactId>
|
||||
<version>${jackson.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package cn.qaiu.vx.core;
|
||||
|
||||
import cn.qaiu.vx.core.util.ConfigConstant;
|
||||
import cn.qaiu.vx.core.util.ConfigUtil;
|
||||
import cn.qaiu.vx.core.util.VertxHolder;
|
||||
import cn.qaiu.vx.core.verticle.ReverseProxyVerticle;
|
||||
@@ -18,6 +17,8 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ConfigConstant.*;
|
||||
|
||||
/**
|
||||
* vertx启动类 需要在主启动类完成回调
|
||||
* <br>Create date 2021-05-07 10:26:54
|
||||
@@ -43,6 +44,11 @@ public final class Deploy {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param args 启动参数
|
||||
* @param handle 启动完成后回调处理函数
|
||||
*/
|
||||
public void start(String[] args, Handler<JsonObject> handle) {
|
||||
this.mainThread = Thread.currentThread();
|
||||
this.handle = handle;
|
||||
@@ -81,7 +87,7 @@ public final class Deploy {
|
||||
var calendar = Calendar.getInstance();
|
||||
calendar.setTime(new Date());
|
||||
var year = calendar.get(Calendar.YEAR);
|
||||
var logoTemplete = """
|
||||
var logoTemplate = """
|
||||
|
||||
Web Server powered by:\s
|
||||
____ ____ _ _ _ \s
|
||||
@@ -94,7 +100,7 @@ public final class Deploy {
|
||||
|
||||
""";
|
||||
|
||||
System.out.printf(logoTemplete,
|
||||
System.out.printf(logoTemplate,
|
||||
conf.getString("version_app"),
|
||||
VersionCommand.getVersion(),
|
||||
conf.getString("copyright"),
|
||||
@@ -108,10 +114,10 @@ public final class Deploy {
|
||||
private void deployVerticle() {
|
||||
tempVertx.close();
|
||||
LOGGER.info("配置读取成功");
|
||||
customConfig = globalConfig.getJsonObject(ConfigConstant.CUSTOM);
|
||||
customConfig = globalConfig.getJsonObject(CUSTOM);
|
||||
|
||||
JsonObject vertxConfig = globalConfig.getJsonObject(ConfigConstant.VERTX);
|
||||
Integer vertxConfigELPS = vertxConfig.getInteger(ConfigConstant.EVENT_LOOP_POOL_SIZE);
|
||||
JsonObject vertxConfig = globalConfig.getJsonObject(VERTX);
|
||||
Integer vertxConfigELPS = vertxConfig.getInteger(EVENT_LOOP_POOL_SIZE);
|
||||
var vertxOptions = vertxConfigELPS == 0 ?
|
||||
new VertxOptions() : new VertxOptions(vertxConfig);
|
||||
|
||||
@@ -122,10 +128,10 @@ public final class Deploy {
|
||||
VertxHolder.init(vertx);
|
||||
//配置保存在共享数据中
|
||||
var sharedData = vertx.sharedData();
|
||||
LocalMap<String, Object> localMap = sharedData.getLocalMap(ConfigConstant.LOCAL);
|
||||
localMap.put(ConfigConstant.GLOBAL_CONFIG, globalConfig);
|
||||
localMap.put(ConfigConstant.CUSTOM_CONFIG, customConfig);
|
||||
localMap.put(ConfigConstant.SERVER, globalConfig.getJsonObject(ConfigConstant.SERVER));
|
||||
LocalMap<String, Object> localMap = sharedData.getLocalMap(LOCAL);
|
||||
localMap.put(GLOBAL_CONFIG, globalConfig);
|
||||
localMap.put(CUSTOM_CONFIG, customConfig);
|
||||
localMap.put(SERVER, globalConfig.getJsonObject(SERVER));
|
||||
var future0 = vertx.createSharedWorkerExecutor("other-handle").executeBlocking(bch -> {
|
||||
handle.handle(globalConfig);
|
||||
bch.complete("other handle complete");
|
||||
@@ -169,7 +175,7 @@ public final class Deploy {
|
||||
* @return Deployment Options
|
||||
*/
|
||||
private DeploymentOptions getWorkDeploymentOptions(String name) {
|
||||
return getWorkDeploymentOptions(name, customConfig.getInteger(ConfigConstant.ASYNC_SERVICE_INSTANCES));
|
||||
return getWorkDeploymentOptions(name, customConfig.getInteger(ASYNC_SERVICE_INSTANCES));
|
||||
}
|
||||
|
||||
private DeploymentOptions getWorkDeploymentOptions(String name, int ins) {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.qaiu.vx.core.annotaions;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
@Documented
|
||||
@Inherited
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface HandleSortFilter {
|
||||
/**
|
||||
* 注册顺序,数字越大越先注册<br>
|
||||
* 值<0时会过滤掉该处理器
|
||||
*/
|
||||
int value() default 0;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.qaiu.vx.core.annotaions;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 拦截器配置注解
|
||||
* 正则匹配拦截途径
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface InterceptorConfig {
|
||||
|
||||
String pattern() default "";
|
||||
|
||||
/**
|
||||
* 注册顺序,数字越大越先注册
|
||||
*/
|
||||
int order() default 0;
|
||||
}
|
||||
@@ -1,9 +1,16 @@
|
||||
package cn.qaiu.vx.core.base;
|
||||
|
||||
import cn.qaiu.vx.core.interceptor.AfterInterceptor;
|
||||
import cn.qaiu.vx.core.model.JsonResult;
|
||||
import cn.qaiu.vx.core.util.CommonUtil;
|
||||
import cn.qaiu.vx.core.util.ReflectionUtil;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ResponseUtil.*;
|
||||
|
||||
/**
|
||||
* 统一响应处理
|
||||
@@ -13,22 +20,43 @@ import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
|
||||
*/
|
||||
public interface BaseHttpApi {
|
||||
|
||||
default void fireJsonResponse(RoutingContext ctx, JsonObject jsonResult) {
|
||||
ctx.response().putHeader(CONTENT_TYPE, "application/json; charset=utf-8")
|
||||
.setStatusCode(200)
|
||||
.end(jsonResult.encode());
|
||||
// 需要扫描注册的Router路径
|
||||
Reflections reflections = ReflectionUtil.getReflections();
|
||||
|
||||
default void doFireJsonObjectResponse(RoutingContext ctx, JsonObject jsonObject) {
|
||||
if (!ctx.response().ended()) {
|
||||
fireJsonObjectResponse(ctx, jsonObject);
|
||||
}
|
||||
handleAfterInterceptor(ctx, jsonObject);
|
||||
}
|
||||
|
||||
default <T> void fireJsonResponse(RoutingContext ctx, T jsonResult) {
|
||||
JsonObject jsonObject = JsonObject.mapFrom(jsonResult);
|
||||
fireJsonResponse(ctx, jsonObject);
|
||||
|
||||
default <T> void doFireJsonResultResponse(RoutingContext ctx, JsonResult<T> jsonResult) {
|
||||
if (!ctx.response().ended()) {
|
||||
fireJsonResultResponse(ctx, jsonResult);
|
||||
}
|
||||
handleAfterInterceptor(ctx, jsonResult.toJsonObject());
|
||||
}
|
||||
|
||||
default void fireTextResponse(RoutingContext ctx, String text) {
|
||||
ctx.response().putHeader("content-type", "text/html; charset=utf-8").end(text);
|
||||
|
||||
default Set<AfterInterceptor> getAfterInterceptor() {
|
||||
|
||||
Set<Class<? extends AfterInterceptor>> afterInterceptorClassSet =
|
||||
reflections.getSubTypesOf(AfterInterceptor.class);
|
||||
if (afterInterceptorClassSet == null) {
|
||||
return null;
|
||||
}
|
||||
return CommonUtil.sortClassSet(afterInterceptorClassSet);
|
||||
}
|
||||
|
||||
default void sendError(int statusCode, RoutingContext ctx) {
|
||||
ctx.response().setStatusCode(statusCode).end();
|
||||
default void handleAfterInterceptor(RoutingContext ctx, JsonObject jsonObject) {
|
||||
Set<AfterInterceptor> afterInterceptor = getAfterInterceptor();
|
||||
if (afterInterceptor != null) {
|
||||
afterInterceptor.forEach(ai -> ai.handle(ctx, jsonObject));
|
||||
}
|
||||
if (!ctx.response().ended()) {
|
||||
fireTextResponse(ctx, "handleAfterInterceptor: response not end");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@ import cn.qaiu.vx.core.annotaions.RouteHandler;
|
||||
import cn.qaiu.vx.core.annotaions.RouteMapping;
|
||||
import cn.qaiu.vx.core.annotaions.SockRouteMapper;
|
||||
import cn.qaiu.vx.core.base.BaseHttpApi;
|
||||
import cn.qaiu.vx.core.enums.MIMEType;
|
||||
import cn.qaiu.vx.core.interceptor.BeforeInterceptor;
|
||||
import cn.qaiu.vx.core.model.JsonResult;
|
||||
import cn.qaiu.vx.core.util.*;
|
||||
import io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.MultiMap;
|
||||
@@ -19,15 +20,12 @@ import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.Route;
|
||||
import io.vertx.ext.web.Router;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.ext.web.handler.BodyHandler;
|
||||
import io.vertx.ext.web.handler.CorsHandler;
|
||||
import io.vertx.ext.web.handler.StaticHandler;
|
||||
import io.vertx.ext.web.handler.*;
|
||||
import io.vertx.ext.web.handler.sockjs.SockJSHandler;
|
||||
import io.vertx.ext.web.handler.sockjs.SockJSHandlerOptions;
|
||||
import javassist.CtClass;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.reflections.Reflections;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -38,6 +36,7 @@ import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ConfigConstant.ROUTE_TIME_OUT;
|
||||
import static io.vertx.core.http.HttpHeaders.*;
|
||||
|
||||
/**
|
||||
@@ -57,15 +56,11 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
add(HttpMethod.DELETE);
|
||||
add(HttpMethod.HEAD);
|
||||
}};
|
||||
// 需要扫描注册的Router路径
|
||||
private static volatile Reflections reflections;
|
||||
|
||||
private final String gatewayPrefix;
|
||||
|
||||
public RouterHandlerFactory(String routerScanAddress, String gatewayPrefix) {
|
||||
Objects.requireNonNull(routerScanAddress, "The router package address scan is empty.");
|
||||
public RouterHandlerFactory(String gatewayPrefix) {
|
||||
Objects.requireNonNull(gatewayPrefix, "The gateway prefix is empty.");
|
||||
reflections = ReflectionUtil.getReflections(routerScanAddress);
|
||||
this.gatewayPrefix = gatewayPrefix;
|
||||
}
|
||||
|
||||
@@ -73,21 +68,22 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
* 开始扫描并注册handler
|
||||
*/
|
||||
public Router createRouter() {
|
||||
Router router = Router.router(VertxHolder.getVertxInstance());
|
||||
// 主路由
|
||||
Router mainRouter = Router.router(VertxHolder.getVertxInstance());
|
||||
|
||||
// 静态资源
|
||||
String path = SharedDataUtil.getJsonConfig("server")
|
||||
.getString("staticResourcePath");
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
// 静态资源
|
||||
router.route("/*").handler(StaticHandler
|
||||
mainRouter.route("/*").handler(StaticHandler
|
||||
.create(path)
|
||||
.setCachingEnabled(true)
|
||||
.setDefaultContentEncoding("UTF-8"));
|
||||
}
|
||||
|
||||
|
||||
router.route().handler(ctx -> {
|
||||
mainRouter.route().handler(ctx -> {
|
||||
LOGGER.debug("The HTTP service request address information ===>path:{}, uri:{}, method:{}",
|
||||
ctx.request().path(), ctx.request().absoluteURI(), ctx.request().method());
|
||||
ctx.response().headers().add(ACCESS_CONTROL_ALLOW_ORIGIN, "*");
|
||||
@@ -98,11 +94,15 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
ctx.next();
|
||||
});
|
||||
// 添加跨域的方法
|
||||
router.route().handler(CorsHandler.create().addRelativeOrigin(".*").allowCredentials(true).allowedMethods(httpMethods));
|
||||
mainRouter.route().handler(CorsHandler.create().addRelativeOrigin(".*").allowCredentials(true).allowedMethods(httpMethods));
|
||||
|
||||
// 配置文件上传路径
|
||||
router.route().handler(BodyHandler.create().setUploadsDirectory("uploads"));
|
||||
mainRouter.route().handler(BodyHandler.create().setUploadsDirectory("uploads"));
|
||||
|
||||
// 拦截器
|
||||
Set<Handler<RoutingContext>> interceptorSet = getInterceptorSet();
|
||||
Route route0 = mainRouter.route("/*");
|
||||
interceptorSet.forEach(route0::handler);
|
||||
|
||||
try {
|
||||
Set<Class<?>> handlers = reflections.getTypesAnnotatedWith(RouteHandler.class);
|
||||
@@ -116,7 +116,7 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
for (Class<?> handler : sortedHandlers) {
|
||||
try {
|
||||
// 注册请求处理方法
|
||||
registerNewHandler(router, handler);
|
||||
registerNewHandler(mainRouter, handler);
|
||||
} catch (Throwable e) {
|
||||
LOGGER.error("Error register {}, Error details:", handler, e.getCause());
|
||||
|
||||
@@ -126,12 +126,12 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
LOGGER.error("Manually Register Handler Fail, Error details:" + e.getMessage());
|
||||
}
|
||||
// 错误请求处理
|
||||
router.errorHandler(405, ctx -> fireJsonResponse(ctx, JsonResult
|
||||
mainRouter.errorHandler(405, ctx -> doFireJsonResultResponse(ctx, JsonResult
|
||||
.error("Method Not Allowed", 405)));
|
||||
router.errorHandler(404, ctx -> ctx.response().setStatusCode(404).setChunked(true)
|
||||
mainRouter.errorHandler(404, ctx -> ctx.response().setStatusCode(404).setChunked(true)
|
||||
.end("Internal server error: 404 not found"));
|
||||
|
||||
return router;
|
||||
return mainRouter;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,15 +155,13 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
method -> method.isAnnotationPresent(SockRouteMapper.class)
|
||||
).toList());
|
||||
|
||||
// 拦截器
|
||||
Handler<RoutingContext> interceptor = getInterceptor();
|
||||
// 依次注册处理方法
|
||||
for (Method method : methodList) {
|
||||
if (method.isAnnotationPresent(RouteMapping.class)) {
|
||||
// 普通路由
|
||||
RouteMapping mapping = method.getAnnotation(RouteMapping.class);
|
||||
HttpMethod routeMethod = HttpMethod.valueOf(mapping.method().name());
|
||||
String routeUrl = getRouteUrl(method.getName(), mapping.value());
|
||||
String routeUrl = getRouteUrl(mapping.value());
|
||||
String url = root.concat(routeUrl);
|
||||
// 匹配方法
|
||||
Route route = router.route(routeMethod, url);
|
||||
@@ -173,17 +171,18 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
route.consumes(mineType);
|
||||
}
|
||||
|
||||
// 先执行拦截方法, 再进入业务请求
|
||||
route.handler(interceptor);
|
||||
// 设置默认超时
|
||||
route.handler(TimeoutHandler.create(SharedDataUtil.getCustomConfig().getInteger(ROUTE_TIME_OUT)));
|
||||
route.handler(ResponseTimeHandler.create());
|
||||
route.handler(ctx -> handlerMethod(instance, method, ctx)).failureHandler(ctx -> {
|
||||
if (ctx.response().ended()) return;
|
||||
ctx.failure().printStackTrace();
|
||||
fireJsonResponse(ctx, JsonResult.error(ctx.failure().getMessage(), 500));
|
||||
doFireJsonResultResponse(ctx, JsonResult.error(ctx.failure().getMessage(), 500));
|
||||
});
|
||||
} else if (method.isAnnotationPresent(SockRouteMapper.class)) {
|
||||
// websocket 基于sockJs
|
||||
SockRouteMapper mapping = method.getAnnotation(SockRouteMapper.class);
|
||||
String routeUrl = getRouteUrl(method.getName(), mapping.value());
|
||||
String routeUrl = getRouteUrl(mapping.value());
|
||||
String url = root.concat(routeUrl);
|
||||
LOGGER.info("Register New Websocket Handler -> {}", url);
|
||||
SockJSHandlerOptions options = new SockJSHandlerOptions()
|
||||
@@ -210,10 +209,9 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
/**
|
||||
* 获取并处理路由URL分隔符
|
||||
*
|
||||
* @param methodName 路由method
|
||||
* @return String
|
||||
*/
|
||||
private String getRouteUrl(String methodName, String mapperValue) {
|
||||
private String getRouteUrl(String mapperValue) {
|
||||
String routeUrl;
|
||||
if ("/".equals(mapperValue)) {
|
||||
routeUrl = mapperValue;
|
||||
@@ -229,15 +227,10 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
* 配置拦截
|
||||
*
|
||||
* @return Handler
|
||||
* @throws Throwable Throwable
|
||||
*/
|
||||
private Handler<RoutingContext> getInterceptor() throws Throwable {
|
||||
private Set<Handler<RoutingContext>> getInterceptorSet() {
|
||||
// 配置拦截
|
||||
Class<?> interceptorClass = Class.forName(SharedDataUtil.getValueForCustomConfig("interceptorClassPath"));
|
||||
Object handleInstance = ReflectionUtil.newWithNoParam(interceptorClass);
|
||||
Method doHandle = interceptorClass.getMethod("doHandle");
|
||||
// 反射调用
|
||||
return CastUtil.cast(ReflectionUtil.invoke(doHandle, handleInstance));
|
||||
return getBeforeInterceptor().stream().map(BeforeInterceptor::doHandle).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,7 +252,7 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
if (handler.isAnnotationPresent(RouteHandler.class)) {
|
||||
RouteHandler routeHandler = handler.getAnnotation(RouteHandler.class);
|
||||
String value = routeHandler.value();
|
||||
root += ("/".equals(value) ? "" : value);
|
||||
root += (value.startsWith("/") ? value.substring(1) : value);
|
||||
}
|
||||
if (!root.endsWith("/")) {
|
||||
root = root + "/";
|
||||
@@ -302,37 +295,12 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
});
|
||||
}
|
||||
|
||||
final MultiMap queryParams = ctx.queryParams();
|
||||
if ("POST".equals(ctx.request().method().name())) {
|
||||
queryParams.addAll(ctx.request().params());
|
||||
}
|
||||
|
||||
JsonArray entityPackagesReg = SharedDataUtil.getJsonArrayForCustomConfig("entityPackagesReg");
|
||||
// 绑定get或post请求头的请求参数
|
||||
methodParametersTemp.forEach((k, v) -> {
|
||||
if (ReflectionUtil.isBasicType(v.getRight())) {
|
||||
String fmt = getFmt(v.getLeft(), v.getRight());
|
||||
String value = queryParams.get(k);
|
||||
parameterValueList.put(k, ReflectionUtil.conversion(v.getRight(), value, fmt));
|
||||
} else if (RoutingContext.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx);
|
||||
} else if (HttpServerRequest.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx.request());
|
||||
} else if (HttpServerResponse.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx.response());
|
||||
} else if (CommonUtil.matchRegList(entityPackagesReg.getList(), v.getRight().getName())) {
|
||||
// 绑定实体类
|
||||
try {
|
||||
Class<?> aClass = Class.forName(v.getRight().getName());
|
||||
Object entity = ParamUtil.multiMapToEntity(queryParams, aClass);
|
||||
parameterValueList.put(k, entity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final MultiMap queryParams = ctx.queryParams();
|
||||
// 解析body-json参数
|
||||
if ("application/json".equals(ctx.parsedHeaders().contentType().value()) && ctx.body().asJsonObject() != null) {
|
||||
if (HttpHeaderValues.APPLICATION_JSON.toString().equals(ctx.parsedHeaders().contentType().value())
|
||||
&& ctx.body().asJsonObject() != null) {
|
||||
JsonObject body = ctx.body().asJsonObject();
|
||||
if (body != null) {
|
||||
methodParametersTemp.forEach((k, v) -> {
|
||||
@@ -352,26 +320,66 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (ctx.body() != null) {
|
||||
queryParams.addAll(ParamUtil.paramsToMap(ctx.body().asString()));
|
||||
}
|
||||
|
||||
// 解析其他参数
|
||||
if ("POST".equals(ctx.request().method().name())) {
|
||||
queryParams.addAll(ctx.request().params());
|
||||
}
|
||||
// 绑定get或post请求头的请求参数
|
||||
methodParametersTemp.forEach((k, v) -> {
|
||||
if (ReflectionUtil.isBasicType(v.getRight())) {
|
||||
String fmt = getFmt(v.getLeft(), v.getRight());
|
||||
String value = queryParams.get(k);
|
||||
parameterValueList.put(k, ReflectionUtil.conversion(v.getRight(), value, fmt));
|
||||
} else if (RoutingContext.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx);
|
||||
} else if (HttpServerRequest.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx.request());
|
||||
} else if (HttpServerResponse.class.getName().equals(v.getRight().getName())) {
|
||||
parameterValueList.put(k, ctx.response());
|
||||
} else if (parameterValueList.get(k) == null
|
||||
&& CommonUtil.matchRegList(entityPackagesReg.getList(), v.getRight().getName())) {
|
||||
// 绑定实体类
|
||||
try {
|
||||
Class<?> aClass = Class.forName(v.getRight().getName());
|
||||
Object entity = ParamUtil.multiMapToEntity(queryParams, aClass);
|
||||
parameterValueList.put(k, entity);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
// 调用handle 获取响应对象
|
||||
Object[] parameterValueArray = parameterValueList.values().toArray(new Object[0]);
|
||||
try {
|
||||
// 反射调用
|
||||
Object data = ReflectionUtil.invokeWithArguments(method, instance, parameterValueArray);
|
||||
if (data != null) {
|
||||
|
||||
if (data instanceof JsonResult) {
|
||||
fireJsonResponse(ctx, data);
|
||||
doFireJsonResultResponse(ctx, (JsonResult<?>) data);
|
||||
}
|
||||
if (data instanceof JsonObject) {
|
||||
doFireJsonObjectResponse(ctx, ((JsonObject) data));
|
||||
} else if (data instanceof Future) { // 处理异步响应
|
||||
((Future<?>) data).onSuccess(res -> {
|
||||
if (res instanceof JsonObject) {
|
||||
fireJsonResponse(ctx, res);
|
||||
} else if (res != null) {
|
||||
fireJsonResponse(ctx, JsonResult.data(res));
|
||||
if (res instanceof JsonResult) {
|
||||
doFireJsonResultResponse(ctx, (JsonResult<?>) res);
|
||||
}
|
||||
}).onFailure(e -> fireJsonResponse(ctx, JsonResult.error(e.getMessage())));
|
||||
if (res instanceof JsonObject) {
|
||||
doFireJsonObjectResponse(ctx, ((JsonObject) res));
|
||||
} else if (res != null) {
|
||||
doFireJsonResultResponse(ctx, JsonResult.data(res));
|
||||
} else {
|
||||
handleAfterInterceptor(ctx, null);
|
||||
}
|
||||
|
||||
}).onFailure(e -> doFireJsonResultResponse(ctx, JsonResult.error(e.getMessage())));
|
||||
} else {
|
||||
ctx.response().headers().set(CONTENT_TYPE, MIMEType.TEXT_HTML.getValue());
|
||||
ctx.end(data.toString());
|
||||
doFireJsonResultResponse(ctx, JsonResult.data(data));
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
@@ -384,7 +392,7 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
err = e.getCause().getMessage();
|
||||
}
|
||||
}
|
||||
fireJsonResponse(ctx, JsonResult.error(err));
|
||||
doFireJsonResultResponse(ctx, JsonResult.error(err));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,4 +410,13 @@ public class RouterHandlerFactory implements BaseHttpApi {
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
private Set<BeforeInterceptor> getBeforeInterceptor() {
|
||||
Set<Class<? extends BeforeInterceptor>> interceptorClassSet =
|
||||
reflections.getSubTypesOf(BeforeInterceptor.class);
|
||||
if (interceptorClassSet == null) {
|
||||
return new HashSet<>();
|
||||
}
|
||||
return CommonUtil.sortClassSet(interceptorClassSet);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.qaiu.vx.core.interceptor;
|
||||
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
|
||||
/**
|
||||
* 后置拦截器接口
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
*/
|
||||
public interface AfterInterceptor {
|
||||
|
||||
void handle(RoutingContext ctx, JsonObject responseData);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cn.qaiu.vx.core.interceptor;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ResponseUtil.sendError;
|
||||
|
||||
/**
|
||||
* 前置拦截器接口
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
*/
|
||||
public interface BeforeInterceptor extends Handler<RoutingContext> {
|
||||
String IS_NEXT = "RoutingContextIsNext";
|
||||
|
||||
default Handler<RoutingContext> doHandle() {
|
||||
|
||||
return ctx -> {
|
||||
ctx.put(IS_NEXT, false);
|
||||
BeforeInterceptor.this.handle(ctx);
|
||||
if (!(Boolean) ctx.get(IS_NEXT) && !ctx.response().ended()) {
|
||||
sendError(ctx, 403);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
default void doNext(RoutingContext context) {
|
||||
context.put(IS_NEXT, true);
|
||||
context.next();
|
||||
}
|
||||
|
||||
void handle(RoutingContext context);
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package cn.qaiu.vx.core.interceptor;
|
||||
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
|
||||
/**
|
||||
* 拦截器接口
|
||||
* <br>Create date 2021-05-06 09:20:37
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
*/
|
||||
public interface Interceptor {
|
||||
|
||||
default Handler<RoutingContext> doHandle() {
|
||||
return this::beforeHandle;
|
||||
}
|
||||
|
||||
void beforeHandle(RoutingContext context);
|
||||
|
||||
void afterHandle(RoutingContext context);
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package cn.qaiu.vx.core.model;
|
||||
|
||||
|
||||
import cn.qaiu.vx.core.util.CastUtil;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serial;
|
||||
@@ -159,4 +162,16 @@ public class JsonResult<T> implements Serializable {
|
||||
public static <T> JsonResult<T> success() {
|
||||
return new JsonResult<>(SUCCESS_CODE, SUCCESS_MESSAGE, true, null);
|
||||
}
|
||||
|
||||
// 转为json对象
|
||||
public JsonObject toJsonObject() {
|
||||
return JsonObject.mapFrom(this);
|
||||
}
|
||||
|
||||
private static final ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
// 转为json对象
|
||||
public static JsonResult<?> toJsonResult(JsonObject json) {
|
||||
return CastUtil.cast(json.mapTo(JsonResult.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package cn.qaiu.vx.core.util;
|
||||
|
||||
import cn.qaiu.vx.core.annotaions.HandleSortFilter;
|
||||
import io.vertx.core.buffer.Buffer;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import org.apache.commons.beanutils.ConvertUtils;
|
||||
@@ -15,6 +16,8 @@ import java.net.URL;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* CommonUtil
|
||||
@@ -70,10 +73,11 @@ public class CommonUtil {
|
||||
} catch (UnknownHostException e) {
|
||||
return false;
|
||||
}
|
||||
try(Socket ignored = new Socket(Address, port)) {
|
||||
//建立一个Socket连接
|
||||
try (Socket ignored = new Socket(Address, port)) {
|
||||
//建立一个Socket连接
|
||||
flag = true;
|
||||
} catch (IOException ignoredException) {}
|
||||
} catch (IOException ignoredException) {
|
||||
}
|
||||
return flag;
|
||||
}
|
||||
|
||||
@@ -126,4 +130,32 @@ public class CommonUtil {
|
||||
LocalConstant.put(configName, map);
|
||||
LOGGER.info("读取配置{}成功", configName);
|
||||
}
|
||||
|
||||
public static <T> Set<T> sortClassSet(Set<Class<? extends T>> set) {
|
||||
return set.stream().filter(c1 -> {
|
||||
HandleSortFilter s1 = c1.getAnnotation(HandleSortFilter.class);
|
||||
if (s1 != null) {
|
||||
return s1.value() > 0;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}).sorted((c1, c2) -> {
|
||||
HandleSortFilter s1 = c1.getAnnotation(HandleSortFilter.class);
|
||||
HandleSortFilter s2 = c2.getAnnotation(HandleSortFilter.class);
|
||||
int n1 = 0, n2 = 0;
|
||||
if (s1 != null) {
|
||||
n1 = s1.value();
|
||||
}
|
||||
if (s2 != null) {
|
||||
n2 = s2.value();
|
||||
}
|
||||
return n1 - n2;
|
||||
}).map(c -> {
|
||||
try {
|
||||
return ReflectionUtil.newWithNoParam(c);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,14 @@ package cn.qaiu.vx.core.util;
|
||||
public interface ConfigConstant {
|
||||
String CUSTOM = "custom";
|
||||
String VERTX = "vertx";
|
||||
|
||||
String EVENT_LOOP_POOL_SIZE = "eventLoopPoolSize";
|
||||
String LOCAL = "local";
|
||||
String SERVER = "server";
|
||||
String GLOBAL_CONFIG = "globalConfig";
|
||||
String CUSTOM_CONFIG = "customConfig";
|
||||
String ASYNC_SERVICE_INSTANCES = "asyncServiceInstances";
|
||||
String IGNORES_REG="ignoresReg";
|
||||
String BASE_LOCATIONS="baseLocations";
|
||||
|
||||
String ROUTE_TIME_OUT="routeTimeOut";
|
||||
}
|
||||
|
||||
@@ -27,12 +27,12 @@ public final class ParamUtil {
|
||||
return map;
|
||||
}
|
||||
|
||||
public static <T> T multiMapToEntity(MultiMap multiMap,Class<T> tClass) throws NoSuchMethodException {
|
||||
Map<String,String> map = multiMapToMap(multiMap);
|
||||
public static <T> T multiMapToEntity(MultiMap multiMap, Class<T> tClass) throws NoSuchMethodException {
|
||||
Map<String, String> map = multiMapToMap(multiMap);
|
||||
T obj = null;
|
||||
try {
|
||||
obj = tClass.getDeclaredConstructor().newInstance();
|
||||
BeanUtils.populate(obj,map);
|
||||
BeanUtils.populate(obj, map);
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
LOGGER.error("实例化异常");
|
||||
@@ -42,4 +42,21 @@ public final class ParamUtil {
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static MultiMap paramsToMap(String paramString) {
|
||||
MultiMap entries = MultiMap.caseInsensitiveMultiMap();
|
||||
if (paramString == null) return entries;
|
||||
String[] params = paramString.split("&");
|
||||
if (params.length == 0) return entries;
|
||||
for (String param : params) {
|
||||
String[] kv = param.split("=");
|
||||
if (kv.length == 2) {
|
||||
entries.set(kv[0], kv[1]);
|
||||
} else {
|
||||
entries.set(kv[0], "");
|
||||
}
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,8 @@ import java.net.URL;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ConfigConstant.BASE_LOCATIONS;
|
||||
|
||||
/**
|
||||
* 基于org.reflection和javassist的反射工具包
|
||||
* 通过包扫描实现路由地址的注解映射
|
||||
@@ -33,6 +35,16 @@ import java.util.*;
|
||||
*/
|
||||
public final class ReflectionUtil {
|
||||
|
||||
|
||||
/**
|
||||
* 以默认配置的基础包路径获取反射器
|
||||
*
|
||||
* @return Reflections object
|
||||
*/
|
||||
public static Reflections getReflections() {
|
||||
return getReflections(SharedDataUtil.getStringForCustomConfig(BASE_LOCATIONS));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取反射器
|
||||
*
|
||||
@@ -48,6 +60,7 @@ public final class ReflectionUtil {
|
||||
} else {
|
||||
packageAddressList = Collections.singletonList(packageAddress);
|
||||
}
|
||||
|
||||
return getReflections(packageAddressList);
|
||||
}
|
||||
|
||||
@@ -70,10 +83,11 @@ public final class ReflectionUtil {
|
||||
// 发现注解api层 没有继承父类时 这里反射一直有问题(Scanner SubTypesScanner was not configured)
|
||||
// 因此这里需要手动配置各种Scanner扫描器 -- https://blog.csdn.net/qq_29499107/article/details/106889781
|
||||
configurationBuilder.setScanners(
|
||||
Scanners.SubTypes.filterResultsBy(s -> true), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes 会报错.默认为true.
|
||||
Scanners.SubTypes.filterResultsBy(s -> true), //允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes
|
||||
// 会报错.默认为true.
|
||||
new MethodParameterNamesScanner(), //设置方法参数名称 扫描器,否则调用getConstructorParamNames 会报错
|
||||
Scanners.MethodsAnnotated, //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
|
||||
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错, 不推荐使用,有可能会报错 Caused by: java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot be cast to javassist.bytecode.MethodrefInfo
|
||||
new MemberUsageScanner(), //设置 member 扫描器,否则 getMethodUsage 会报错
|
||||
Scanners.TypesAnnotated //设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
|
||||
);
|
||||
|
||||
@@ -98,7 +112,8 @@ public final class ReflectionUtil {
|
||||
MethodInfo methodInfo = cm.getMethodInfo();
|
||||
CtClass[] parameterTypes = cm.getParameterTypes();
|
||||
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
|
||||
LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
|
||||
LocalVariableAttribute attr =
|
||||
(LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag);
|
||||
|
||||
boolean flag = true;
|
||||
boolean flag2 = cm.getModifiers() - 1 != AccessFlag.STATIC;
|
||||
@@ -110,7 +125,8 @@ public final class ReflectionUtil {
|
||||
continue;
|
||||
}
|
||||
flag = false;
|
||||
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k], parameterTypes[j - k]));
|
||||
paramMap.put(attr.variableName(j + (flag2 ? 1 : 0)), Pair.of(parameterAnnotations[j - k],
|
||||
parameterTypes[j - k]));
|
||||
}
|
||||
} catch (NotFoundException e) {
|
||||
e.printStackTrace();
|
||||
@@ -214,7 +230,8 @@ public final class ReflectionUtil {
|
||||
if (ctClass.isPrimitive() || "java.util.Date".equals(ctClass.getName())) {
|
||||
return true;
|
||||
}
|
||||
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|(Float)|(Double)|(String))$");
|
||||
return ctClass.getName().matches("^java\\.lang\\.((Boolean)|(Character)|(Byte)|(Short)|(Integer)|(Long)|" +
|
||||
"(Float)|(Double)|(String))$");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +255,8 @@ public final class ReflectionUtil {
|
||||
* @throws InstantiationException InstantiationException
|
||||
* @throws IllegalAccessException IllegalAccessException
|
||||
*/
|
||||
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||
public static <T> T newWithNoParam(Class<T> handler) throws NoSuchMethodException, InvocationTargetException,
|
||||
InstantiationException, IllegalAccessException {
|
||||
return handler.getConstructor().newInstance();
|
||||
}
|
||||
|
||||
|
||||
40
core/src/main/java/cn/qaiu/vx/core/util/ResponseUtil.java
Normal file
40
core/src/main/java/cn/qaiu/vx/core/util/ResponseUtil.java
Normal file
@@ -0,0 +1,40 @@
|
||||
package cn.qaiu.vx.core.util;
|
||||
|
||||
import cn.qaiu.vx.core.model.JsonResult;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.core.http.HttpHeaders;
|
||||
import io.vertx.core.http.HttpServerResponse;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
|
||||
import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
|
||||
|
||||
public class ResponseUtil {
|
||||
|
||||
public static void redirect(HttpServerResponse response, String url) {
|
||||
response.putHeader(HttpHeaders.LOCATION, url).setStatusCode(302).end();
|
||||
}
|
||||
|
||||
public static void redirect(HttpServerResponse response, String url, Promise<?> promise) {
|
||||
redirect(response, url);
|
||||
promise.complete();
|
||||
}
|
||||
|
||||
public static void fireJsonObjectResponse(RoutingContext ctx, JsonObject jsonObject) {
|
||||
ctx.response().putHeader(CONTENT_TYPE, "application/json; charset=utf-8")
|
||||
.setStatusCode(200)
|
||||
.end(jsonObject.encode());
|
||||
}
|
||||
|
||||
public static <T> void fireJsonResultResponse(RoutingContext ctx, JsonResult<T> jsonResult) {
|
||||
fireJsonObjectResponse(ctx, jsonResult.toJsonObject());
|
||||
}
|
||||
|
||||
public static void fireTextResponse(RoutingContext ctx, String text) {
|
||||
ctx.response().putHeader(CONTENT_TYPE, "text/html; charset=utf-8").end(text);
|
||||
}
|
||||
|
||||
public static void sendError(RoutingContext ctx, int statusCode) {
|
||||
ctx.response().setStatusCode(statusCode).end();
|
||||
}
|
||||
}
|
||||
@@ -32,11 +32,11 @@ public class SharedDataUtil {
|
||||
return (JsonObject) localMap.get(key);
|
||||
}
|
||||
|
||||
public static JsonObject getJsonObjectForCustomConfig(String key) {
|
||||
return getJsonConfig("customConfig").getJsonObject(key);
|
||||
public static JsonObject getCustomConfig() {
|
||||
return getJsonConfig("customConfig");
|
||||
}
|
||||
|
||||
public static String getJsonStringForCustomConfig(String key) {
|
||||
public static String getStringForCustomConfig(String key) {
|
||||
return getJsonConfig("customConfig").getString(key);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ public class RouterVerticle extends AbstractVerticle {
|
||||
|
||||
private static final int port = SharedDataUtil.getValueForServerConfig("port");
|
||||
private static final Router router = new RouterHandlerFactory(
|
||||
SharedDataUtil.getJsonStringForCustomConfig("routerLocations"),
|
||||
SharedDataUtil.getJsonStringForServerConfig("contextPath")).createRouter();
|
||||
|
||||
private static final JsonObject globalConfig = SharedDataUtil.getJsonConfig("globalConfig");
|
||||
|
||||
@@ -3,7 +3,6 @@ package cn.qaiu.vx.core.verticle;
|
||||
import cn.qaiu.vx.core.annotaions.Service;
|
||||
import cn.qaiu.vx.core.base.BaseAsyncService;
|
||||
import cn.qaiu.vx.core.util.ReflectionUtil;
|
||||
import cn.qaiu.vx.core.util.SharedDataUtil;
|
||||
import io.vertx.core.AbstractVerticle;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.serviceproxy.ServiceBinder;
|
||||
@@ -27,8 +26,7 @@ public class ServiceVerticle extends AbstractVerticle {
|
||||
private static final Set<Class<?>> handlers;
|
||||
|
||||
static {
|
||||
String handlerLocations = SharedDataUtil.getJsonStringForCustomConfig("handlerLocations");
|
||||
Reflections reflections = ReflectionUtil.getReflections(handlerLocations);
|
||||
Reflections reflections = ReflectionUtil.getReflections();
|
||||
handlers = reflections.getTypesAnnotatedWith(Service.class);
|
||||
}
|
||||
|
||||
|
||||
68
parser/pom.xml
Normal file
68
parser/pom.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>netdisk-fast-download</artifactId>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<version>0.1.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>parser</artifactId>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!--logback日志实现-->
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web-client</artifactId>
|
||||
<version>${vertx.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.openjdk.nashorn/nashorn-core -->
|
||||
<dependency>
|
||||
<groupId>org.openjdk.nashorn</groupId>
|
||||
<artifactId>nashorn-core</artifactId>
|
||||
<version>15.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
19
parser/src/main/java/cn/qaiu/WebClientVertxInit.java
Normal file
19
parser/src/main/java/cn/qaiu/WebClientVertxInit.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package cn.qaiu;
|
||||
|
||||
import io.vertx.core.Vertx;
|
||||
|
||||
public class WebClientVertxInit {
|
||||
private Vertx vertx = null;
|
||||
private static final WebClientVertxInit INSTANCE = new WebClientVertxInit();
|
||||
|
||||
public static void init(Vertx vx) {
|
||||
INSTANCE.vertx = vx;
|
||||
}
|
||||
|
||||
public static Vertx get() {
|
||||
if (INSTANCE.vertx == null) {
|
||||
throw new IllegalArgumentException("VertxInit getVertx: vertx is null");
|
||||
}
|
||||
return INSTANCE.vertx;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.qaiu.lz.common.parser;//package cn.qaiu.lz.common.parser;
|
||||
package cn.qaiu.parser;//package cn.qaiu.lz.common.parser;
|
||||
|
||||
import cn.qaiu.lz.common.parser.impl.*;
|
||||
import cn.qaiu.parser.impl.*;
|
||||
import io.vertx.core.Future;
|
||||
|
||||
public interface IPanTool {
|
||||
@@ -15,6 +15,7 @@ public interface IPanTool {
|
||||
case "uc" -> new UcTool(key, pwd);
|
||||
case "ye" -> new YeTool(key, pwd);
|
||||
case "fj" -> new FjTool(key, pwd);
|
||||
case "qk" -> new QkTool(key, pwd);
|
||||
default -> {
|
||||
throw new UnsupportedOperationException("未知分享类型");
|
||||
}
|
||||
@@ -23,7 +24,7 @@ public interface IPanTool {
|
||||
|
||||
static IPanTool shareURLPrefixMatching(String url, String pwd) {
|
||||
|
||||
if (url.startsWith(CowTool.SHARE_URL_PREFIX)) {
|
||||
if (url.contains(CowTool.LINK_KEY)) {
|
||||
return new CowTool(url, pwd);
|
||||
} else if (url.startsWith(EcTool.SHARE_URL_PREFIX)) {
|
||||
return new EcTool(url, pwd);
|
||||
@@ -35,7 +36,7 @@ public interface IPanTool {
|
||||
return new YeTool(url, pwd);
|
||||
} else if (url.startsWith(FjTool.SHARE_URL_PREFIX)) {
|
||||
return new FjTool(url, pwd);
|
||||
} else if (url.contains("lanzou")) {
|
||||
} else if (url.contains(LzTool.LINK_KEY)) {
|
||||
return new LzTool(url, pwd);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.qaiu.lz.common.parser;
|
||||
package cn.qaiu.parser;
|
||||
|
||||
import cn.qaiu.vx.core.util.VertxHolder;
|
||||
import cn.qaiu.WebClientVertxInit;
|
||||
import io.vertx.core.Handler;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.ext.web.client.WebClient;
|
||||
@@ -13,8 +13,8 @@ public abstract class PanBase {
|
||||
|
||||
protected Promise<String> promise = Promise.promise();
|
||||
|
||||
protected WebClient client = WebClient.create(VertxHolder.getVertxInstance());
|
||||
protected WebClient clientNoRedirects = WebClient.create(VertxHolder.getVertxInstance(), OPTIONS);
|
||||
protected WebClient client = WebClient.create(WebClientVertxInit.get());
|
||||
protected WebClient clientNoRedirects = WebClient.create(WebClientVertxInit.get(), OPTIONS);
|
||||
private static final WebClientOptions OPTIONS = new WebClientOptions().setFollowRedirects(false);
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
package cn.qaiu.lz.common.parser;
|
||||
|
||||
import cn.qaiu.lz.common.parser.impl.LzTool;
|
||||
package cn.qaiu.parser;
|
||||
|
||||
/**
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -18,6 +18,8 @@ public class CowTool extends PanBase implements IPanTool {
|
||||
private static final String API_REQUEST_URL = "https://cowtransfer.com/core/api/transfer/share";
|
||||
public static final String SHARE_URL_PREFIX = "https://cowtransfer.com/s/";
|
||||
|
||||
public static final String LINK_KEY = "cowtransfer.com/s/";
|
||||
|
||||
public CowTool(String key, String pwd) {
|
||||
super(key, pwd);
|
||||
}
|
||||
@@ -30,8 +32,16 @@ public class CowTool extends PanBase implements IPanTool {
|
||||
if ("success".equals(resJson.getString("message")) && resJson.containsKey("data")) {
|
||||
JsonObject dataJson = resJson.getJsonObject("data");
|
||||
String guid = dataJson.getString("guid");
|
||||
String fileId = dataJson.getJsonObject("firstFile").getString("id");
|
||||
String url2 = API_REQUEST_URL + "/download?transferGuid=" + guid + "&fileId=" + fileId;
|
||||
StringBuilder url2Build = new StringBuilder(API_REQUEST_URL + "/download?transferGuid=" + guid);
|
||||
if (dataJson.getBoolean("zipDownload")) {
|
||||
// &title=xxx
|
||||
JsonObject firstFolder = dataJson.getJsonObject("firstFolder");
|
||||
url2Build.append("&title=").append(firstFolder.getString("title"));
|
||||
} else {
|
||||
String fileId = dataJson.getJsonObject("firstFile").getString("id");
|
||||
url2Build.append("&fileId=").append(fileId);
|
||||
}
|
||||
String url2 = url2Build.toString();
|
||||
client.getAbs(url2).send().onSuccess(res2 -> {
|
||||
JsonObject res2Json = res2.bodyAsJsonObject();
|
||||
if ("success".equals(res2Json.getString("message")) && res2Json.containsKey("data")) {
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.json.JsonArray;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.MultiMap;
|
||||
import io.vertx.core.Promise;
|
||||
@@ -1,15 +1,13 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.AESUtils;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.vx.core.util.VertxHolder;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.AESUtils;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.MultiMap;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.client.WebClient;
|
||||
import io.vertx.ext.web.client.WebClientOptions;
|
||||
import io.vertx.uritemplate.UriTemplate;
|
||||
|
||||
import java.util.UUID;
|
||||
@@ -37,8 +35,7 @@ public class FjTool extends PanBase implements IPanTool {
|
||||
public Future<String> parse() {
|
||||
String dataKey = CommonUtils.adaptShortPaths(SHARE_URL_PREFIX, key);
|
||||
|
||||
WebClient client = WebClient.create(VertxHolder.getVertxInstance(),
|
||||
new WebClientOptions().setFollowRedirects(false));
|
||||
WebClient client = clientNoRedirects;
|
||||
String shareId = String.valueOf(AESUtils.idEncrypt(dataKey));
|
||||
|
||||
// 第一次请求 获取文件信息
|
||||
@@ -1,15 +1,17 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.vx.core.util.VertxHolder;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.JsExecUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.MultiMap;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.client.WebClient;
|
||||
import io.vertx.ext.web.client.WebClientOptions;
|
||||
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
|
||||
import javax.script.ScriptException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -23,49 +25,82 @@ public class LzTool extends PanBase implements IPanTool {
|
||||
|
||||
public static final String SHARE_URL_PREFIX = "https://wwwa.lanzoui.com";
|
||||
|
||||
public static final String LINK_KEY = "lanzou";
|
||||
|
||||
public LzTool(String key, String pwd) {
|
||||
super(key, pwd);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Future<String> parse() {
|
||||
String sUrl = key.startsWith("https://") ? key : SHARE_URL_PREFIX + "/" + key;
|
||||
|
||||
WebClient client = WebClient.create(VertxHolder.getVertxInstance(),
|
||||
new WebClientOptions().setFollowRedirects(false));
|
||||
WebClient client = clientNoRedirects;
|
||||
client.getAbs(sUrl).send().onSuccess(res -> {
|
||||
String html = res.bodyAsString();
|
||||
// 匹配iframe
|
||||
Pattern compile = Pattern.compile("src=\"(/fn\\?[a-zA-Z\\d_+/=]{16,})\"");
|
||||
Matcher matcher = compile.matcher(html);
|
||||
// 没有Iframe说明是加密分享, 匹配sign通过密码请求下载页面
|
||||
if (!matcher.find()) {
|
||||
// 没有Iframe说明是加密分享, 匹配sign通过密码请求下载页面
|
||||
Pattern compile2 = Pattern.compile("sign=(\\w{16,})");
|
||||
Matcher matcher2 = compile2.matcher(html);
|
||||
if (!matcher2.find()) {
|
||||
fail(sUrl + ": sign正则匹配失败, 可能分享已失效");
|
||||
// 处理一下JS
|
||||
String jsText = getJsText(html);
|
||||
|
||||
if (jsText == null) {
|
||||
fail(SHARE_URL_PREFIX + " -> " + sUrl + ": js脚本匹配失败, 可能分享已失效");
|
||||
return;
|
||||
}
|
||||
|
||||
jsText = jsText.replace("document.getElementById('pwd').value", "\"" + pwd + "\"");
|
||||
jsText = jsText.substring(0, jsText.indexOf("document.getElementById('rpt')"));
|
||||
try {
|
||||
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, "down_p");
|
||||
getDownURL(promise, sUrl, client, (Map<String, String>) scriptObjectMirror.get("data"));
|
||||
} catch (ScriptException | NoSuchMethodException e) {
|
||||
fail(e, "js引擎执行失败");
|
||||
return;
|
||||
}
|
||||
String sign = matcher2.group(1);
|
||||
getDownURL(promise, sUrl, client, sign);
|
||||
return;
|
||||
}
|
||||
String iframePath = matcher.group(1);
|
||||
client.getAbs(SHARE_URL_PREFIX + iframePath).send().onSuccess(res2 -> {
|
||||
String html2 = res2.bodyAsString();
|
||||
System.out.println(html);
|
||||
Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'(\\w+)'").matcher(html2);
|
||||
if (!matcher2.find()) {
|
||||
fail(SHARE_URL_PREFIX + iframePath + " -> " + sUrl + ": sign正则匹配失败, 可能分享已失效");
|
||||
|
||||
// 去TMD正则
|
||||
// Matcher matcher2 = Pattern.compile("'sign'\s*:\s*'(\\w+)'").matcher(html2);
|
||||
String jsText = getJsText(html2);
|
||||
if (jsText == null) {
|
||||
fail(SHARE_URL_PREFIX + iframePath + " -> " + sUrl + ": js脚本匹配失败, 可能分享已失效");
|
||||
return;
|
||||
}
|
||||
String sign = matcher2.group(1);
|
||||
getDownURL(promise, sUrl, client, sign);
|
||||
try {
|
||||
ScriptObjectMirror scriptObjectMirror = JsExecUtils.executeDynamicJs(jsText, null);
|
||||
getDownURL(promise, sUrl, client, (Map<String, String>) scriptObjectMirror.get("data"));
|
||||
} catch (ScriptException | NoSuchMethodException e) {
|
||||
fail(e, "js引擎执行失败");
|
||||
}
|
||||
}).onFailure(handleFail(SHARE_URL_PREFIX));
|
||||
}).onFailure(handleFail(sUrl));
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
private void getDownURL(Promise<String> promise, String key, WebClient client, String sign) {
|
||||
private String getJsText(String html) {
|
||||
String jsTagStart = "<script type=\"text/javascript\">";
|
||||
String jsTagEnd = "</script>";
|
||||
int index = html.lastIndexOf(jsTagStart);
|
||||
if (index == -1) {
|
||||
return null;
|
||||
}
|
||||
int startPos = index + jsTagStart.length();
|
||||
int endPos = html.indexOf(jsTagEnd, startPos);
|
||||
return html.substring(startPos, endPos);
|
||||
}
|
||||
|
||||
private void getDownURL(Promise<String> promise, String key, WebClient client, Map<String, ?> signMap) {
|
||||
MultiMap map = MultiMap.caseInsensitiveMultiMap();
|
||||
signMap.forEach((k, v) -> {
|
||||
map.set(k, v.toString());
|
||||
});
|
||||
MultiMap headers = MultiMap.caseInsensitiveMultiMap();
|
||||
var userAgent2 = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, " +
|
||||
"like " +
|
||||
@@ -79,8 +114,7 @@ public class LzTool extends PanBase implements IPanTool {
|
||||
String url = SHARE_URL_PREFIX + "/ajaxm.php";
|
||||
client.postAbs(url).putHeaders(headers).sendForm(MultiMap
|
||||
.caseInsensitiveMultiMap()
|
||||
.set("action", "downprocess")
|
||||
.set("sign", sign).set("p", pwd)).onSuccess(res2 -> {
|
||||
.setAll(map)).onSuccess(res2 -> {
|
||||
JsonObject urlJson = res2.bodyAsJsonObject();
|
||||
if (urlJson.getInteger("zt") != 1) {
|
||||
fail(urlJson.getString("inf"));
|
||||
20
parser/src/main/java/cn/qaiu/parser/impl/QkTool.java
Normal file
20
parser/src/main/java/cn/qaiu/parser/impl/QkTool.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Promise;
|
||||
|
||||
public class QkTool extends PanBase implements IPanTool {
|
||||
|
||||
public QkTool(String key, String pwd) {
|
||||
super(key, pwd);
|
||||
}
|
||||
|
||||
public Future<String> parse() {
|
||||
Promise<String> promise = Promise.promise();
|
||||
|
||||
promise.complete("https://lz.qaiu.top");
|
||||
return promise.future();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.json.JsonArray;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
@@ -1,9 +1,9 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
package cn.qaiu.parser.impl;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.PanBase;
|
||||
import cn.qaiu.lz.common.util.CommonUtils;
|
||||
import cn.qaiu.lz.common.util.JsExecUtils;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.PanBase;
|
||||
import cn.qaiu.util.CommonUtils;
|
||||
import cn.qaiu.util.JsExecUtils;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.client.WebClient;
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.lz.common.util;
|
||||
package cn.qaiu.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.lz.common.util;
|
||||
package cn.qaiu.util;
|
||||
|
||||
public class ArrayUtil {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.lz.common.util;
|
||||
package cn.qaiu.util;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
@@ -8,12 +8,16 @@ import java.util.Map;
|
||||
public class CommonUtils {
|
||||
|
||||
public static String adaptShortPaths(String urlPrefix, String url) {
|
||||
if (!url.startsWith(urlPrefix)) {
|
||||
url = urlPrefix + url;
|
||||
}
|
||||
if (url.endsWith(".html")) {
|
||||
url = url.substring(0, url.length() - 5);
|
||||
}
|
||||
String prefix = "https://";
|
||||
if (!url.startsWith(urlPrefix) && url.startsWith(prefix)) {
|
||||
urlPrefix = urlPrefix.substring(prefix.length());
|
||||
return url.substring(url.indexOf(urlPrefix) + urlPrefix.length());
|
||||
} else if (!url.startsWith(urlPrefix)) {
|
||||
url = urlPrefix + url;
|
||||
}
|
||||
return url.substring(urlPrefix.length());
|
||||
}
|
||||
|
||||
89
parser/src/main/java/cn/qaiu/util/JsExecUtils.java
Normal file
89
parser/src/main/java/cn/qaiu/util/JsExecUtils.java
Normal file
@@ -0,0 +1,89 @@
|
||||
package cn.qaiu.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
|
||||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* 执行Js脚本
|
||||
*
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* @date 2023/7/29 17:35
|
||||
*/
|
||||
public class JsExecUtils {
|
||||
private static final String JS_PATH = "js/ye123.js";
|
||||
private static final String LZ_JS_PATH = "js/lz.js";
|
||||
|
||||
private static final String RES_PATH;
|
||||
private static final Invocable inv;
|
||||
|
||||
// 初始化脚本引擎
|
||||
static {
|
||||
ScriptEngineManager engineManager = new ScriptEngineManager();
|
||||
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
|
||||
//获取文件所在的相对路径
|
||||
URL resource = JsExecUtils.class.getResource("/");
|
||||
if (resource == null) {
|
||||
throw new RuntimeException("js resource path is null");
|
||||
}
|
||||
RES_PATH = resource.getPath();
|
||||
String reader = RES_PATH + JS_PATH;
|
||||
try (FileReader fReader = new FileReader(reader)) {
|
||||
engine.eval(fReader);
|
||||
fReader.close();
|
||||
inv = (Invocable) engine;
|
||||
} catch (IOException | ScriptException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用js文件
|
||||
*/
|
||||
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException,
|
||||
NoSuchMethodException {
|
||||
//调用js中的函数
|
||||
return (ScriptObjectMirror) inv.invokeFunction(functionName, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用执行蓝奏云js文件
|
||||
*/
|
||||
public static ScriptObjectMirror executeDynamicJs(String jsText, String funName) throws ScriptException,
|
||||
NoSuchMethodException {
|
||||
ScriptEngineManager engineManager = new ScriptEngineManager();
|
||||
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
|
||||
try {
|
||||
//获取文件所在的相对路径
|
||||
Path path;
|
||||
try {
|
||||
path = Paths.get(RES_PATH + LZ_JS_PATH);
|
||||
} catch (RuntimeException ioe) {
|
||||
path = Paths.get(RES_PATH.substring(1) + LZ_JS_PATH);
|
||||
}
|
||||
String jsContent = Files.readString(path) + "\n" + jsText;
|
||||
engine.eval(jsContent);
|
||||
Invocable inv = (Invocable) engine;
|
||||
//调用js中的函数
|
||||
if (StringUtils.isNotEmpty(funName)) {
|
||||
inv.invokeFunction(funName);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return (ScriptObjectMirror) engine.get("signObj");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.lz.common.util;
|
||||
package cn.qaiu.util;
|
||||
|
||||
/**
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
46
parser/src/main/resources/js/lz.js
Normal file
46
parser/src/main/resources/js/lz.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 蓝奏云解析器js签名获取工具
|
||||
*/
|
||||
|
||||
var signObj;
|
||||
|
||||
|
||||
var $, jQuery;
|
||||
|
||||
$ = jQuery = function () {
|
||||
return new jQuery.fn.init();
|
||||
}
|
||||
|
||||
jQuery.fn = jQuery.prototype = {
|
||||
init: function () {
|
||||
return {
|
||||
focus: function (a) {
|
||||
|
||||
},
|
||||
keyup: function(a) {
|
||||
|
||||
},
|
||||
ajax: function (obj) {
|
||||
signObj = obj
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
jQuery.fn.init.prototype = jQuery.fn;
|
||||
|
||||
|
||||
// 伪装jquery.ajax函数获取关键数据
|
||||
$.ajax = function (obj) {
|
||||
signObj = obj
|
||||
}
|
||||
|
||||
var document = {
|
||||
getElementById: function (v) {
|
||||
return {
|
||||
value: 'v'
|
||||
}
|
||||
},
|
||||
}
|
||||
95
parser/src/main/resources/js/ye123.js
Normal file
95
parser/src/main/resources/js/ye123.js
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
https://statics.123pan.com/share-static/dist/umi.fb72555e.js
|
||||
eaefamemdead
|
||||
eaefameidldy
|
||||
_0x4f141a(1690439821|5790548|/b/api/share/download/info|web|3|1946841013) = 秘钥
|
||||
|
||||
_0x1e2592 1690439821 时间戳
|
||||
_0x48562f 5790548 随机码
|
||||
_0x1e37d5 /b/api/share/download/info
|
||||
_0x4e2d74 web
|
||||
_0x56f040 3
|
||||
_0x43bdc6 1946841013 加密时间HASH戳
|
||||
|
||||
>>>>
|
||||
_0x43bdc6=''['concat'](_0x1e2592, '-')['concat'](_0x48562f, '-')['concat'](_0x406c4e)
|
||||
加密时间HASH戳 = 时间戳-随机码-秘钥
|
||||
*/
|
||||
|
||||
function _0x1b5d95(_0x278d1a) {
|
||||
var _0x839b57,
|
||||
_0x4ed4dc = arguments['length'] > 0x2 && void 0x0 !== arguments[0x2] ? arguments[0x2] : 0x8;
|
||||
if (0x0 === arguments['length'])
|
||||
return null;
|
||||
'object' === typeof _0x278d1a ? _0x839b57 = _0x278d1a : (0xa === ('' + _0x278d1a)['length'] && (_0x278d1a = 0x3e8 * parseInt(_0x278d1a)),
|
||||
_0x839b57 = new Date(_0x278d1a));
|
||||
var _0xc5c54a = _0x278d1a + 0xea60 * new Date(_0x278d1a)['getTimezoneOffset']()
|
||||
, _0x3732dc = _0xc5c54a + 0x36ee80 * _0x4ed4dc;
|
||||
return _0x839b57 = new Date(_0x3732dc),
|
||||
{
|
||||
'y': _0x839b57['getFullYear'](),
|
||||
'm': _0x839b57['getMonth']() + 0x1 < 0xa ? '0' + (_0x839b57['getMonth']() + 0x1) : _0x839b57['getMonth']() + 0x1,
|
||||
'd': _0x839b57['getDate']() < 0xa ? '0' + _0x839b57['getDate']() : _0x839b57['getDate'](),
|
||||
'h': _0x839b57['getHours']() < 0xa ? '0' + _0x839b57['getHours']() : _0x839b57['getHours'](),
|
||||
'f': _0x839b57['getMinutes']() < 0xa ? '0' + _0x839b57['getMinutes']() : _0x839b57['getMinutes']()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function _0x4f141a(_0x4075b1) {
|
||||
|
||||
for (var _0x4eddcb = arguments['length'] > 0x1 && void 0x0 !== arguments[0x1] ? arguments[0x1] : 0xa,
|
||||
_0x2fc680 = function() {
|
||||
for (var _0x515c63, _0x361314 = [], _0x4cbdba = 0x0; _0x4cbdba < 0x100; _0x4cbdba++) {
|
||||
_0x515c63 = _0x4cbdba;
|
||||
for (var _0x460960 = 0x0; _0x460960 < 0x8; _0x460960++)
|
||||
_0x515c63 = 0x1 & _0x515c63 ? 0xedb88320 ^ _0x515c63 >>> 0x1 : _0x515c63 >>> 0x1;
|
||||
_0x361314[_0x4cbdba] = _0x515c63;
|
||||
}
|
||||
return _0x361314;
|
||||
},
|
||||
_0x4aed86 = _0x2fc680(),
|
||||
_0x5880f0 = _0x4075b1,
|
||||
_0x492393 = -0x1, _0x25d82c = 0x0;
|
||||
_0x25d82c < _0x5880f0['length'];
|
||||
_0x25d82c++)
|
||||
|
||||
_0x492393 = _0x492393 >>> 0x8 ^ _0x4aed86[0xff & (_0x492393 ^ _0x5880f0.charCodeAt(_0x25d82c))];
|
||||
return _0x492393 = (-0x1 ^ _0x492393) >>> 0x0,
|
||||
_0x492393.toString(_0x4eddcb);
|
||||
}
|
||||
|
||||
|
||||
function getSign(_0x1e37d5) {
|
||||
var _0x4e2d74 = 'web';
|
||||
var _0x56f040 = 3;
|
||||
var _0x1e2592 = Math.round((new Date().getTime() + 0x3c * new Date().getTimezoneOffset() * 0x3e8 + 28800000) / 0x3e8).toString();
|
||||
var key = 'a,d,e,f,g,h,l,m,y,i,j,n,o,p,k,q,r,s,t,u,b,c,v,w,s,z';
|
||||
var _0x48562f = Math['round'](0x989680 * Math['random']());
|
||||
|
||||
var _0x2f7dfc;
|
||||
var _0x35a889;
|
||||
var _0x36f983;
|
||||
var _0x3b043d;
|
||||
var _0x5bc73b;
|
||||
var _0x4b30b2;
|
||||
var _0x32399e;
|
||||
var _0x25d94e;
|
||||
var _0x373490;
|
||||
for (var _0x1c540f in (_0x2f7dfc = key.split(','),
|
||||
_0x35a889 = _0x1b5d95(_0x1e2592),
|
||||
_0x36f983 = _0x35a889['y'],
|
||||
_0x3b043d = _0x35a889['m'],
|
||||
_0x5bc73b = _0x35a889['d'],
|
||||
_0x4b30b2 = _0x35a889['h'],
|
||||
_0x32399e = _0x35a889['f'],
|
||||
_0x25d94e = [_0x36f983, _0x3b043d, _0x5bc73b, _0x4b30b2, _0x32399e].join(''),
|
||||
_0x373490 = [],
|
||||
_0x25d94e))
|
||||
_0x373490['push'](_0x2f7dfc[Number(_0x25d94e[_0x1c540f])]);
|
||||
var _0x43bdc6;
|
||||
var _0x406c4e;
|
||||
return _0x43bdc6 = _0x4f141a(_0x373490['join']('')),
|
||||
_0x406c4e = _0x4f141a(''['concat'](_0x1e2592, '|')['concat'](_0x48562f, '|')['concat'](_0x1e37d5, '|')['concat'](_0x4e2d74, '|')['concat'](_0x56f040, '|')['concat'](_0x43bdc6)),
|
||||
[_0x43bdc6, ''['concat'](_0x1e2592, '-')['concat'](_0x48562f, '-')['concat'](_0x406c4e)];
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package cn.qaiu.web.test;
|
||||
package qaiu.web.test;
|
||||
|
||||
import cn.qaiu.lz.common.util.AESUtils;
|
||||
import cn.qaiu.util.AESUtils;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
@@ -50,6 +50,12 @@ public class TestAESUtil {
|
||||
Assert.assertEquals(146731, AESUtils.idEncrypt("7jy0zlv"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test00() throws IllegalBlockSizeException, NoSuchPaddingException, BadPaddingException,
|
||||
NoSuchAlgorithmException, InvalidKeyException {
|
||||
System.out.println(AESUtils.decryptByBase64AES(AESUtils.CIPHER_AES2, AESUtils.CIPHER_AES));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTs() {
|
||||
System.out.println(System.currentTimeMillis());
|
||||
24
parser/src/test/java/qaiu/web/test/TestRegex.java
Normal file
24
parser/src/test/java/qaiu/web/test/TestRegex.java
Normal file
@@ -0,0 +1,24 @@
|
||||
package qaiu.web.test;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class TestRegex {
|
||||
|
||||
@Test
|
||||
public void regexYFC() {
|
||||
String html = """
|
||||
<input type="hidden" id="typed_id" value="file_559003251828">
|
||||
<input type="hidden" id="share_link_token" value="9cbe4b73521ba4d65a8cd38a8c">
|
||||
""";
|
||||
|
||||
Pattern compile = Pattern.compile("id=\"typed_id\"\\s+value=\"file_(\\d+)\"");
|
||||
Matcher matcher = compile.matcher(html);
|
||||
if (matcher.find()) {
|
||||
System.out.println(matcher.group(0));
|
||||
System.out.println(matcher.group(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,9 @@
|
||||
package cn.qaiu.web.test;
|
||||
package qaiu.web.test;
|
||||
|
||||
import io.vertx.core.MultiMap;
|
||||
import io.vertx.core.Vertx;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.client.WebClient;
|
||||
import org.apache.commons.lang3.RegExUtils;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.web.test;
|
||||
package qaiu.web.test;
|
||||
|
||||
import io.vertx.core.MultiMap;
|
||||
import io.vertx.core.Vertx;
|
||||
23
pom.xml
23
pom.xml
@@ -7,19 +7,31 @@
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<artifactId>netdisk-fast-download</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>0.1.6</version>
|
||||
<version>0.1.7</version>
|
||||
|
||||
<modules>
|
||||
<module>core</module>
|
||||
<module>web-service</module>
|
||||
<module>core-database</module>
|
||||
<module>parser</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
|
||||
<packageDirectory>${project.basedir}/web-service/target/package</packageDirectory>
|
||||
|
||||
<slf4j.version>2.0.5</slf4j.version>
|
||||
<vertx.version>4.4.1</vertx.version>
|
||||
<org.reflections.version>0.10.2</org.reflections.version>
|
||||
<lombok.version>1.18.12</lombok.version>
|
||||
<slf4j.version>2.0.5</slf4j.version>
|
||||
<commons-lang3.version>3.12.0</commons-lang3.version>
|
||||
<jackson.version>2.14.2</jackson.version>
|
||||
<logback.version>1.4.7</logback.version>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
@@ -104,14 +116,7 @@
|
||||
<!--<failOnError>false</failOnError>-->
|
||||
<!--当配置true时,只清理filesets里的文件,构建目录中得文件不被清理.默认是flase.-->
|
||||
<excludeDefaultDirectories>false</excludeDefaultDirectories>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<!--要清理的目录位置-->
|
||||
<directory>${project.basedir}/logs</directory>
|
||||
<!--是否跟随符号链接 (symbolic links)-->
|
||||
<followSymlinks>false</followSymlinks>
|
||||
</fileset>
|
||||
</filesets>
|
||||
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -5,19 +5,17 @@
|
||||
<parent>
|
||||
<artifactId>netdisk-fast-download</artifactId>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<version>0.1.6</version>
|
||||
<version>0.1.7</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<version>0.1.6</version>
|
||||
<version>0.1.7</version>
|
||||
<artifactId>web-service</artifactId>
|
||||
|
||||
<properties>
|
||||
<packageDirectory>${project.basedir}/target/package</packageDirectory>
|
||||
<java.version>17</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<slf4j.version>2.0.5</slf4j.version>
|
||||
<vertx-jooq.version>6.1.0</vertx-jooq.version>
|
||||
<finalName>netdisk-fast-download-${project.version}</finalName>
|
||||
<finalName>netdisk-fast-download</finalName>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -36,13 +34,23 @@
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.4.6</version>
|
||||
<version>${logback.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<artifactId>core-database</artifactId>
|
||||
<version>0.1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<artifactId>parser</artifactId>
|
||||
<version>0.1.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -52,14 +60,9 @@
|
||||
<dependency>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web-client</artifactId>
|
||||
<version>4.4.1</version>
|
||||
<version>${vertx.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.qaiu</groupId>
|
||||
<artifactId>core-database</artifactId>
|
||||
<version>0.1.6</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.openjdk.nashorn/nashorn-core -->
|
||||
<dependency>
|
||||
<groupId>org.openjdk.nashorn</groupId>
|
||||
@@ -105,6 +108,8 @@
|
||||
<exclude>*.**</exclude>
|
||||
<exclude>*/*.xml</exclude>
|
||||
<exclude>conf/**</exclude>
|
||||
<exclude>js/**</exclude>
|
||||
<exclude>http-tools/**</exclude>
|
||||
</excludes>
|
||||
<archive>
|
||||
<manifest>
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package cn.qaiu.lz;
|
||||
|
||||
import cn.qaiu.WebClientVertxInit;
|
||||
import cn.qaiu.db.pool.JDBCPoolInit;
|
||||
import cn.qaiu.vx.core.Deploy;
|
||||
import cn.qaiu.vx.core.util.ConfigConstant;
|
||||
import cn.qaiu.vx.core.util.VertxHolder;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.core.json.jackson.DatabindCodec;
|
||||
|
||||
|
||||
/**
|
||||
@@ -24,6 +28,8 @@ public class AppMain {
|
||||
* @param jsonObject 配置
|
||||
*/
|
||||
private static void exec(JsonObject jsonObject) {
|
||||
WebClientVertxInit.init(VertxHolder.getVertxInstance());
|
||||
DatabindCodec.mapper().registerModule(new JavaTimeModule());
|
||||
if (jsonObject.getJsonObject(ConfigConstant.SERVER).getBoolean("enableDatabase")) {
|
||||
JDBCPoolInit.builder().config(jsonObject.getJsonObject("dataSource")).build().initPool();
|
||||
}
|
||||
|
||||
@@ -1,29 +1,27 @@
|
||||
package cn.qaiu.lz.common.interceptorImpl;
|
||||
|
||||
import cn.qaiu.vx.core.base.BaseHttpApi;
|
||||
import cn.qaiu.vx.core.interceptor.Interceptor;
|
||||
import cn.qaiu.vx.core.annotaions.HandleSortFilter;
|
||||
import cn.qaiu.vx.core.interceptor.BeforeInterceptor;
|
||||
import cn.qaiu.vx.core.util.SharedDataUtil;
|
||||
import io.vertx.core.json.JsonArray;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ConfigConstant.IGNORES_REG;
|
||||
|
||||
/**
|
||||
* 默认拦截器实现
|
||||
* 校验用户是否合法 <br>
|
||||
* TODO 暂时只做简单实现
|
||||
* 前置拦截器实现
|
||||
*/
|
||||
@Slf4j
|
||||
public class DefaultInterceptor implements Interceptor, BaseHttpApi {
|
||||
@HandleSortFilter(1)
|
||||
public class DefaultInterceptor implements BeforeInterceptor {
|
||||
|
||||
private final JsonArray ignores = SharedDataUtil.getJsonArrayForCustomConfig("ignoresReg");
|
||||
protected final JsonArray ignores = SharedDataUtil.getJsonArrayForCustomConfig(IGNORES_REG);
|
||||
|
||||
@Override
|
||||
public void beforeHandle(RoutingContext ctx) {
|
||||
ctx.next();
|
||||
public void handle(RoutingContext ctx) {
|
||||
System.out.println("进入前置拦截器1->" + ctx.request().path());
|
||||
doNext(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterHandle(RoutingContext context) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package cn.qaiu.lz.common.interceptorImpl;
|
||||
|
||||
import cn.qaiu.db.pool.JDBCPoolInit;
|
||||
import cn.qaiu.lz.common.model.ParserLogInfo;
|
||||
import cn.qaiu.vx.core.annotaions.HandleSortFilter;
|
||||
import cn.qaiu.vx.core.interceptor.AfterInterceptor;
|
||||
import cn.qaiu.vx.core.model.JsonResult;
|
||||
import cn.qaiu.vx.core.util.CommonUtil;
|
||||
import cn.qaiu.vx.core.util.SharedDataUtil;
|
||||
import io.vertx.core.json.JsonArray;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.ext.web.RoutingContext;
|
||||
import io.vertx.jdbcclient.JDBCPool;
|
||||
import io.vertx.sqlclient.templates.SqlTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static cn.qaiu.vx.core.util.ConfigConstant.IGNORES_REG;
|
||||
|
||||
|
||||
/**
|
||||
* 记录解析日志
|
||||
*/
|
||||
@Slf4j
|
||||
@HandleSortFilter(99)
|
||||
public class LogStatistics implements AfterInterceptor {
|
||||
|
||||
JDBCPool client = JDBCPoolInit.instance().getPool();
|
||||
private final JsonArray ignores = SharedDataUtil.getJsonArrayForCustomConfig(IGNORES_REG);
|
||||
@Override
|
||||
public void handle(RoutingContext ctx, JsonObject responseData) {
|
||||
|
||||
// 判断是否忽略
|
||||
if (CommonUtil.matchRegList(ignores.getList(), ctx.request().path())) {
|
||||
return;
|
||||
}
|
||||
|
||||
ParserLogInfo parserLogInfo = new ParserLogInfo();
|
||||
parserLogInfo.setPath(ctx.request().uri());
|
||||
if (responseData == null) {
|
||||
String location = ctx.response().headers().get("location");
|
||||
if (location != null) {
|
||||
parserLogInfo.setCode(200);
|
||||
parserLogInfo.setData(location);
|
||||
} else {
|
||||
log.error("location不存在且responseData为空, path={}", ctx.request().path());
|
||||
}
|
||||
insert(parserLogInfo);
|
||||
|
||||
} else if (responseData.containsKey("code")) {
|
||||
JsonResult<?> result = JsonResult.toJsonResult(responseData);
|
||||
parserLogInfo.setCode(result.getCode());
|
||||
parserLogInfo.setData(result.getCode() == 500 ? result.getMsg() : result.getData().toString());
|
||||
insert(parserLogInfo);
|
||||
} else {
|
||||
log.error("未知json日志: {}, path: {}", responseData.encode(), ctx.request().path());
|
||||
}
|
||||
}
|
||||
|
||||
void insert(ParserLogInfo info) {
|
||||
SqlTemplate
|
||||
.forUpdate(client, "INSERT INTO t_parser_log_info VALUES (#{id},#{logTime},#{path},#{code},#{data})")
|
||||
.mapFrom(ParserLogInfo.class)
|
||||
.execute(info)
|
||||
.onSuccess(res -> {
|
||||
log.info("inserted log: id={}, path={}, code={}", info.getId(), info.getPath(), info.getCode());
|
||||
}).onFailure(Throwable::printStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.qaiu.lz.common.model;
|
||||
|
||||
import cn.qaiu.lz.common.util.SnowflakeIdWorker;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
abstract public class BaseModel {
|
||||
public static final long serialVersionUID = 1L;
|
||||
|
||||
|
||||
private String id = String.valueOf(SnowflakeIdWorker.idWorker().nextId());
|
||||
|
||||
private String createBy;
|
||||
|
||||
private Date createTime;
|
||||
|
||||
private String updateBy;
|
||||
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package cn.qaiu.lz.common.model;
|
||||
|
||||
import io.vertx.core.MultiMap;
|
||||
|
||||
public class FileInfo extends BaseModel {
|
||||
|
||||
private String fileName;
|
||||
|
||||
private String fileType;
|
||||
|
||||
private Long fileSize;
|
||||
|
||||
private String download;
|
||||
|
||||
private MultiMap header;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package cn.qaiu.lz.common.model;
|
||||
|
||||
import cn.qaiu.db.ddl.Length;
|
||||
import cn.qaiu.db.ddl.Table;
|
||||
import cn.qaiu.lz.common.util.SnowflakeIdWorker;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@Table("t_parser_log_info")
|
||||
public class ParserLogInfo {
|
||||
String id = SnowflakeIdWorker.getStringId();
|
||||
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS", timezone = "GMT+8")
|
||||
Date logTime = new Date();
|
||||
String path;
|
||||
Integer code;
|
||||
|
||||
@Length(varcharSize = 4096)
|
||||
String data;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package cn.qaiu.lz.common.parser.impl;
|
||||
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Promise;
|
||||
|
||||
public class QkTool {
|
||||
public static Future<String> parse() {
|
||||
Promise<String> promise = Promise.promise();
|
||||
|
||||
return promise.future();
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package cn.qaiu.lz.common.util;
|
||||
|
||||
import org.openjdk.nashorn.api.scripting.ScriptObjectMirror;
|
||||
|
||||
import javax.script.Invocable;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
import javax.script.ScriptException;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* 执行Js脚本
|
||||
* @author <a href="https://qaiu.top">QAIU</a>
|
||||
* @date 2023/7/29 17:35
|
||||
*/
|
||||
public class JsExecUtils {
|
||||
private static final String JS_PATH = "/js/ye123.js";
|
||||
private static Invocable inv;
|
||||
|
||||
// 初始化脚本引擎
|
||||
static {
|
||||
ScriptEngineManager engineManager = new ScriptEngineManager();
|
||||
ScriptEngine engine = engineManager.getEngineByName("JavaScript"); // 得到脚本引擎
|
||||
//获取文件所在的相对路径
|
||||
URL resource = JsExecUtils.class.getResource("/");
|
||||
if (resource == null) {
|
||||
throw new RuntimeException("js resource path is null");
|
||||
}
|
||||
String path = resource.getPath();
|
||||
String reader = path + JS_PATH;
|
||||
try (FileReader fReader = new FileReader(reader)){
|
||||
engine.eval(fReader);
|
||||
fReader.close();
|
||||
inv = (Invocable) engine;
|
||||
} catch (IOException | ScriptException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用js文件
|
||||
*/
|
||||
public static ScriptObjectMirror executeJs(String functionName, Object... args) throws ScriptException, NoSuchMethodException {
|
||||
//调用js中的方法
|
||||
return (ScriptObjectMirror) inv.invokeFunction(functionName, args);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cn.qaiu.vx.core.util;
|
||||
package cn.qaiu.lz.common.util;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
@@ -30,6 +30,8 @@ public class SnowflakeIdWorker {
|
||||
|
||||
// ==============================Fields===========================================
|
||||
|
||||
//开始时间截 (2021-01-01)
|
||||
private static final long EPOCH = 1609459200000L;
|
||||
/**
|
||||
* 机器id所占的位数
|
||||
*/
|
||||
@@ -94,7 +96,7 @@ public class SnowflakeIdWorker {
|
||||
*
|
||||
* @return SnowflakeId
|
||||
*/
|
||||
public synchronized long nextId() {
|
||||
public synchronized Long nextId() {
|
||||
long timestamp = timeGen();
|
||||
|
||||
//如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
@@ -133,9 +135,7 @@ public class SnowflakeIdWorker {
|
||||
//时间截向左移22位(5+5+12)
|
||||
long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
|
||||
|
||||
//开始时间截 (2021-01-01)
|
||||
long twepoch = 1609459200000L;
|
||||
return ((timestamp - twepoch) << timestampLeftShift) //
|
||||
return ((timestamp - EPOCH) << timestampLeftShift) //
|
||||
| (datacenterId << datacenterIdShift) //
|
||||
| (workerId << sequenceBits) //
|
||||
| sequence;
|
||||
@@ -214,30 +214,18 @@ public class SnowflakeIdWorker {
|
||||
return snowflakeIdWorker;
|
||||
}
|
||||
|
||||
synchronized public static Long getLongId() {
|
||||
return snowflakeIdWorker.nextId();
|
||||
}
|
||||
|
||||
synchronized public static String getStringId() {
|
||||
return snowflakeIdWorker.nextId().toString();
|
||||
}
|
||||
|
||||
synchronized public static SnowflakeIdWorker idWorkerCluster(long workerId, long datacenterId) {
|
||||
if (snowflakeIdWorkerCluster == null) {
|
||||
snowflakeIdWorkerCluster = new SnowflakeIdWorker(workerId, datacenterId);
|
||||
}
|
||||
return snowflakeIdWorkerCluster;
|
||||
}
|
||||
//==============================Test=============================================
|
||||
|
||||
/**
|
||||
* 测试
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
final SnowflakeIdWorker snowflakeIdWorkerCluster = idWorkerCluster(0, 1);
|
||||
final SnowflakeIdWorker idWorker = idWorker();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
long id = idWorker.nextId();
|
||||
System.out.println(Long.toBinaryString(id));
|
||||
System.out.println(id);
|
||||
System.out.println("------------");
|
||||
id = snowflakeIdWorkerCluster.nextId();
|
||||
System.out.println(Long.toBinaryString(id));
|
||||
System.out.println(id);
|
||||
System.out.println("------------\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
32
web-service/src/main/java/cn/qaiu/lz/web/http/ParserApi.java
Normal file
32
web-service/src/main/java/cn/qaiu/lz/web/http/ParserApi.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package cn.qaiu.lz.web.http;
|
||||
|
||||
|
||||
import cn.qaiu.lz.web.model.SysUser;
|
||||
import cn.qaiu.lz.web.service.DbService;
|
||||
import cn.qaiu.lz.web.service.UserService;
|
||||
import cn.qaiu.lz.web.model.StatisticsInfo;
|
||||
import cn.qaiu.vx.core.annotaions.RouteHandler;
|
||||
import cn.qaiu.vx.core.annotaions.RouteMapping;
|
||||
import cn.qaiu.vx.core.enums.RouteMethod;
|
||||
import cn.qaiu.vx.core.util.AsyncServiceUtil;
|
||||
import io.vertx.core.Future;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@RouteHandler(value = "/v2", order = 10)
|
||||
@Slf4j
|
||||
public class ParserApi {
|
||||
|
||||
private final UserService userService = AsyncServiceUtil.getAsyncServiceInstance(UserService.class);
|
||||
private final DbService dbService = AsyncServiceUtil.getAsyncServiceInstance(DbService.class);
|
||||
|
||||
@RouteMapping(value = "/login", method = RouteMethod.POST)
|
||||
public Future<SysUser> login(SysUser user) {
|
||||
log.info("<------- login: {}", user.getUsername());
|
||||
return userService.login(user);
|
||||
}
|
||||
|
||||
@RouteMapping(value = "/statisticsInfo", method = RouteMethod.GET, order = 99)
|
||||
public Future<StatisticsInfo> statisticsInfo() {
|
||||
return dbService.getStatisticsInfo();
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,17 @@
|
||||
package cn.qaiu.lz.web.http;
|
||||
|
||||
import cn.qaiu.lz.common.parser.IPanTool;
|
||||
import cn.qaiu.lz.common.parser.impl.*;
|
||||
import cn.qaiu.lz.web.model.SysUser;
|
||||
import cn.qaiu.lz.web.service.UserService;
|
||||
import cn.qaiu.parser.IPanTool;
|
||||
import cn.qaiu.parser.impl.EcTool;
|
||||
import cn.qaiu.vx.core.annotaions.RouteHandler;
|
||||
import cn.qaiu.vx.core.annotaions.RouteMapping;
|
||||
import cn.qaiu.vx.core.enums.RouteMethod;
|
||||
import cn.qaiu.vx.core.util.AsyncServiceUtil;
|
||||
import cn.qaiu.vx.core.util.ResponseUtil;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.core.http.HttpServerRequest;
|
||||
import io.vertx.core.http.HttpServerResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
|
||||
|
||||
/**
|
||||
* 服务API
|
||||
* <br>Create date 2021/4/28 9:15
|
||||
@@ -26,14 +22,6 @@ import static io.vertx.core.http.HttpHeaders.CONTENT_TYPE;
|
||||
@RouteHandler("/")
|
||||
public class ServerApi {
|
||||
|
||||
private final UserService userService = AsyncServiceUtil.getAsyncServiceInstance(UserService.class);
|
||||
|
||||
@RouteMapping(value = "/login", method = RouteMethod.POST)
|
||||
public Future<String> login(SysUser user) {
|
||||
log.info("<------- login: {}", user.getUsername());
|
||||
return userService.login(user);
|
||||
}
|
||||
|
||||
@RouteMapping(value = "/parser", method = RouteMethod.GET, order = 4)
|
||||
public Future<Void> parse(HttpServerResponse response, HttpServerRequest request, String url, String pwd) {
|
||||
|
||||
@@ -42,14 +30,9 @@ public class ServerApi {
|
||||
// 默认读取Url参数会被截断手动获取一下其他参数
|
||||
url = EcTool.SHARE_URL_PREFIX + request.getParam("data");
|
||||
}
|
||||
try {
|
||||
IPanTool.shareURLPrefixMatching(url, pwd).parse().onSuccess(resUrl -> {
|
||||
response.putHeader("location", resUrl).setStatusCode(302).end();
|
||||
promise.complete();
|
||||
}).onFailure(t -> promise.fail(t.fillInStackTrace()));
|
||||
} catch (Exception e) {
|
||||
promise.fail(e);
|
||||
}
|
||||
IPanTool.shareURLPrefixMatching(url, pwd).parse().onSuccess(resUrl -> {
|
||||
ResponseUtil.redirect(response, resUrl, promise);
|
||||
}).onFailure(t -> promise.fail(t.fillInStackTrace()));
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
@@ -64,7 +47,8 @@ public class ServerApi {
|
||||
|
||||
|
||||
@RouteMapping(value = "/:type/:key", method = RouteMethod.GET, order = 1)
|
||||
public void parseKey(HttpServerResponse response, String type, String key) {
|
||||
public Future<Void> parseKey(HttpServerResponse response, String type, String key) {
|
||||
Promise<Void> promise = Promise.promise();
|
||||
String code = "";
|
||||
if (key.contains("@")) {
|
||||
String[] keys = key.split("@");
|
||||
@@ -72,11 +56,10 @@ public class ServerApi {
|
||||
code = keys[1];
|
||||
}
|
||||
|
||||
IPanTool.typeMatching(type, key, code).parse().onSuccess(resUrl -> response.putHeader("location", resUrl)
|
||||
.setStatusCode(302).end()).onFailure(t -> {
|
||||
response.putHeader(CONTENT_TYPE, "text/html;charset=utf-8");
|
||||
response.end(t.getMessage());
|
||||
});
|
||||
IPanTool.typeMatching(type, key, code).parse()
|
||||
.onSuccess(resUrl -> ResponseUtil.redirect(response, resUrl, promise))
|
||||
.onFailure(t -> promise.fail(t.fillInStackTrace()));
|
||||
return promise.future();
|
||||
}
|
||||
|
||||
@RouteMapping(value = "/json/:type/:key", method = RouteMethod.GET, order = 2)
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package cn.qaiu.lz.web.model;
|
||||
|
||||
public class CowUser {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package cn.qaiu.lz.web.model;
|
||||
|
||||
public class LzUser {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package cn.qaiu.lz.web.model;
|
||||
|
||||
import cn.qaiu.lz.common.ToJson;
|
||||
import io.vertx.codegen.annotations.DataObject;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@DataObject
|
||||
public class StatisticsInfo implements ToJson {
|
||||
Integer fail;
|
||||
Integer success;
|
||||
Integer total;
|
||||
|
||||
|
||||
public StatisticsInfo(JsonObject jsonObject) {
|
||||
this.fail = jsonObject.getInteger("fail");
|
||||
this.success = jsonObject.getInteger("success");
|
||||
this.total = jsonObject.getInteger("total");
|
||||
}
|
||||
}
|
||||
@@ -4,22 +4,20 @@ import cn.qaiu.db.ddl.Table;
|
||||
import cn.qaiu.lz.common.ToJson;
|
||||
import io.vertx.codegen.annotations.DataObject;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@DataObject
|
||||
@NoArgsConstructor
|
||||
@Table("t_user")
|
||||
public class SysUser implements ToJson {
|
||||
private String id;
|
||||
|
||||
private String username;
|
||||
private String password;
|
||||
|
||||
public SysUser(JsonObject json) {
|
||||
this.id = json.getString("id");
|
||||
this.username = json.getString("username");
|
||||
this.password = json.getString("password");
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.qaiu.lz.web.service;
|
||||
|
||||
import cn.qaiu.lz.common.model.UserInfo;
|
||||
import cn.qaiu.lz.web.model.StatisticsInfo;
|
||||
import cn.qaiu.vx.core.base.BaseAsyncService;
|
||||
import io.vertx.codegen.annotations.ProxyGen;
|
||||
import io.vertx.core.Future;
|
||||
@@ -16,4 +17,6 @@ import io.vertx.core.json.JsonObject;
|
||||
public interface DbService extends BaseAsyncService {
|
||||
Future<JsonObject> sayOk(String data);
|
||||
Future<JsonObject> sayOk2(String data, UserInfo holder);
|
||||
|
||||
Future<StatisticsInfo> getStatisticsInfo();
|
||||
}
|
||||
|
||||
@@ -13,5 +13,5 @@ import io.vertx.core.Future;
|
||||
*/
|
||||
@ProxyGen
|
||||
public interface UserService extends BaseAsyncService {
|
||||
Future<String> login(SysUser user);
|
||||
Future<SysUser> login(SysUser user);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
package cn.qaiu.lz.web.service.impl;
|
||||
|
||||
import cn.qaiu.db.pool.JDBCPoolInit;
|
||||
import cn.qaiu.lz.common.model.UserInfo;
|
||||
import cn.qaiu.lz.web.service.DbService;
|
||||
import cn.qaiu.lz.web.model.StatisticsInfo;
|
||||
import cn.qaiu.vx.core.annotaions.Service;
|
||||
import cn.qaiu.vx.core.model.JsonResult;
|
||||
import io.vertx.core.Future;
|
||||
import io.vertx.core.Promise;
|
||||
import io.vertx.core.json.JsonObject;
|
||||
import io.vertx.jdbcclient.JDBCPool;
|
||||
import io.vertx.sqlclient.templates.SqlTemplate;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* lz-web
|
||||
* <br>Create date 2021/7/12 17:26
|
||||
@@ -35,4 +42,25 @@ public class DbServiceImpl implements DbService {
|
||||
// log.info("--> {}", holder.toString());
|
||||
return Future.succeededFuture(JsonObject.mapFrom(JsonResult.data("Hi: " + data)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<StatisticsInfo> getStatisticsInfo() {
|
||||
JDBCPool client = JDBCPoolInit.instance().getPool();
|
||||
Promise<StatisticsInfo> promise = Promise.promise();
|
||||
String sql = """
|
||||
select COUNT(CASE "code" WHEN 500 THEN "code" END ) "fail",
|
||||
COUNT(CASE "code" WHEN 200 THEN "code" END ) "success",
|
||||
count(1) "total"
|
||||
from "t_parser_log_info"
|
||||
""";
|
||||
SqlTemplate.forQuery(client, sql).mapTo(StatisticsInfo.class).execute(new HashMap<>()).onSuccess(row -> {
|
||||
StatisticsInfo info;
|
||||
if ((info = row.iterator().next()) != null) {
|
||||
promise.complete(info);
|
||||
} else {
|
||||
promise.fail("t_parser_log_info查询为空");
|
||||
}
|
||||
}).onFailure(promise::fail);
|
||||
return promise.future();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import cn.qaiu.lz.web.service.UserService;
|
||||
import cn.qaiu.vx.core.annotaions.Service;
|
||||
import io.vertx.core.Future;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* lz-web
|
||||
* <br>Create date 2021/8/27 14:09
|
||||
@@ -15,8 +17,13 @@ import io.vertx.core.Future;
|
||||
public class UserServiceImpl implements UserService {
|
||||
|
||||
@Override
|
||||
public Future<String> login(SysUser user) {
|
||||
public Future<SysUser> login(SysUser user) {
|
||||
|
||||
return Future.succeededFuture("111");
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(2);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return Future.succeededFuture(user);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ server:
|
||||
# 使用静态页面
|
||||
enableStaticHtmlService: false
|
||||
# 使用数据库
|
||||
enableDatabase: false
|
||||
enableDatabase: true
|
||||
staticResourcePath: webroot/
|
||||
# 反向代理服务器配置路径(不用加后缀)
|
||||
proxyConf: server-proxy
|
||||
@@ -19,27 +19,23 @@ custom:
|
||||
# 异步服务线程数
|
||||
asyncServiceInstances: 4
|
||||
# server路由(controller层)所在包路径
|
||||
routerLocations: cn.qaiu.lz.web.http
|
||||
# 拦截器包路径
|
||||
interceptorClassPath: cn.qaiu.lz.common.interceptorImpl.DefaultInterceptor
|
||||
# server层包路径
|
||||
handlerLocations: cn.qaiu.lz.web.service
|
||||
# 匹配规则
|
||||
baseLocations: cn.qaiu.lz
|
||||
# 路由处理默认超时时间(毫秒)
|
||||
routeTimeOut: 15000
|
||||
# 拦截器匹配规则
|
||||
ignoresReg:
|
||||
- .*/login$
|
||||
- /v2/statisticsInfo
|
||||
- .*/test.*$
|
||||
# 实体类包路径匹配正则
|
||||
|
||||
# 参数注入的实体类包路径匹配正则 (防止同名类引发歧义)
|
||||
entityPackagesReg:
|
||||
- ^cn\.qaiu\.lz\.web\.model\..*
|
||||
|
||||
|
||||
# 数据源配置
|
||||
dataSource:
|
||||
provider_class: io.vertx.ext.jdbc.spi.impl.HikariCPDataSourceProvider
|
||||
jdbcUrl: jdbc:h2:tcp://127.0.0.1:9095/./db/myData;MODE=MySQL;DATABASE_TO_LOWER=FALSE
|
||||
jdbcUrl: jdbc:h2:tcp://127.0.0.1:9095/./db/myData;MODE=MySQL;DATABASE_TO_UPPER=FALSE
|
||||
driverClassName: org.h2.Driver
|
||||
username: root
|
||||
password: '123456'
|
||||
tableClassPath: cn.qaiu.lz.web.model
|
||||
|
||||
cowConfig:
|
||||
config: '111'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 要激活的配置: dev--连接本地数据库; prod连接线上数据库
|
||||
active: dev
|
||||
# 版本号
|
||||
version_app: 0.1.6
|
||||
version_app: 0.1.7
|
||||
# 公司名称 -> LOGO版权文字
|
||||
copyright: QAIU
|
||||
|
||||
@@ -46,15 +46,14 @@ Content-Disposition: form-data; name="email"
|
||||
--WebAppBoundary
|
||||
Content-Disposition: form-data; name="joinProToken"
|
||||
|
||||
|
||||
--WebAppBoundary--
|
||||
|
||||
###
|
||||
|
||||
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=eb9df924-7b29-496b-8147-96762fc81d28&title=spring-play
|
||||
|
||||
###
|
||||
git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch web-service/src/main/resources/http-tools/test.http' --prune-empty --tag-name-filter cat -- --all
|
||||
git push origin master --force
|
||||
rmdir .git/refs/original/
|
||||
git reflog expire --expire=now --all
|
||||
git gc --prune=now
|
||||
git gc --aggressive --prune=now
|
||||
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=
|
||||
|
||||
###
|
||||
https://cowtransfer.com/core/api/transfer/share/download?transferGuid=eb9df924-7b29-496b-8147-96762fc81d28
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# offset: 1
|
||||
# limit: 60
|
||||
# @no-cookie-jar
|
||||
POST https://api.feijipan.com/ws/recommend/list?devType=6&devModel=Chrome&extra=2&shareId=146731&type=0&offset=1&limit=60
|
||||
POST https://api.feijipan.com/ws/recommend/list?devType=6&devModel=Chrome&extra=2&shareId=193186&type=0&offset=1&limit=60
|
||||
|
||||
# 654488C79332E7279F9A38367BD72D3B
|
||||
# 4703B103BD6871F83441233393695EF3
|
||||
|
||||
@@ -24,4 +24,13 @@ https://developer.lanzoug.com/file/?VDJbZVxtADFSWwY+U2YHa1FuU2tTYgBnBnUGZFNmWylS
|
||||
###
|
||||
https://developer.lanzoug.com/file/?VTNVa1tqAjMFDAM7BDEAbAE+U2tfbgZhBnVbOQUwVCYEb1IoAToCNwQhVnRXLlcyVWAEdl9uVzkEbFYxVm5VeVVlVSxbNwJ4BWADeAQyAGgBNVN4X3oGbQZxW3sFP1Q8BGhSYAEDAj8ENlY9VzJXZ1U3BDFfMldlBDFWaVY9VXJVM1VxWzsCZwVlA2QEYAAwAWtTYF8wBiIGcVstBWRUZwQ0UjcBbwJ5BGJWNVcsV2RVOgQuX2NXZgQ2VjJWMlVhVWdVNlswAm8FagMxBGAANgE6UzdfYwZgBjFbbAU6VGwEZVIyAWQCZQRkVjZXMFdmVTcENV8uVy8EalYgVixVIVUmVWdbdAI/BTcDaARhADEBblNvXzQGPQY5W3sFLVQ8BGlSYAE6AmsEY1Y2VztXY1U/BDFfM1dnBDRWZFYkVXpVc1VkW2oCIQVuA2QEZgA5AW5TZl8wBjYGMFtkBWFUcwRxUnUBKwJrBGNWNlc7V2NVPwQxXzJXZQQzVmdWLFUhVTxVcls7AmcFYgNnBH4AMwFoU2RfLgY1BjVbawV3VGIEPA==
|
||||
|
||||
### 20230819新规则
|
||||
POST /ajaxm.php
|
||||
|
||||
# var wsk_sign = 'c20230818';
|
||||
# var aihidcms = 'J5Nh';
|
||||
# var iucjdsd = '';
|
||||
# var ws_sign = 'c20230818';
|
||||
# var sasign = 'AGZQbgk4UGEDCgo1ATEGOlY_aBTlSNVRiV2gEMlA1WmkBJ1R3AWFUMVY2VDsDZQE0Vj4CMgNsADdXZw_c_c';
|
||||
# var ajaxdata = '?ctdf';
|
||||
data : { 'action':'downprocess','signs':ajaxdata,'sign':sasign,'websign':iucjdsd,'websignkey':aihidcms,'ves':1 }
|
||||
|
||||
@@ -28,6 +28,10 @@ GET http://127.0.0.1:6400/cow/e4f41b51b5da4f
|
||||
# @no-redirect
|
||||
GET http://127.0.0.1:6400/parser?url=https://cowtransfer.com/s/9a644fe3e3a748
|
||||
|
||||
### 奶牛
|
||||
# @no-redirect
|
||||
GET http://127.0.0.1:6400/parser?url=https://goldrepo.cowtransfer.com/s/026a638795634b
|
||||
|
||||
### 移动云空间 https://www.ecpan.cn/web/#/yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1
|
||||
# @no-redirect
|
||||
GET http://127.0.0.1:6400/parser?url=https://www.ecpan.cn/web//yunpanProxy?path=%2F%23%2Fdrive%2Foutside&data=81027a5c99af5b11ca004966c945cce6W9Bf2&isShare=1
|
||||
@@ -94,6 +98,8 @@ GET http://127.0.0.1:6400/ye/iaKtVv-qOECd
|
||||
GET http://127.0.0.1:6400/parser?url=https://www.123pan.com/s/iaKtVv-6OECd.html&pwd=DcGe
|
||||
|
||||
###
|
||||
POST http://127.0.0.1:6400/login1
|
||||
GET http://127.0.0.1:6400/v2/statisticsInfo
|
||||
|
||||
###
|
||||
POST http://127.0.0.1:6400/v2/login?username=asd
|
||||
|
||||
|
||||
46
web-service/src/main/resources/js/lz.js
Normal file
46
web-service/src/main/resources/js/lz.js
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 蓝奏云解析器js签名获取工具
|
||||
*/
|
||||
|
||||
var signObj;
|
||||
|
||||
|
||||
var $, jQuery;
|
||||
|
||||
$ = jQuery = function () {
|
||||
return new jQuery.fn.init();
|
||||
}
|
||||
|
||||
jQuery.fn = jQuery.prototype = {
|
||||
init: function () {
|
||||
return {
|
||||
focus: function (a) {
|
||||
|
||||
},
|
||||
keyup: function(a) {
|
||||
|
||||
},
|
||||
ajax: function (obj) {
|
||||
signObj = obj
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
jQuery.fn.init.prototype = jQuery.fn;
|
||||
|
||||
|
||||
// 伪装jquery.ajax函数获取关键数据
|
||||
$.ajax = function (obj) {
|
||||
signObj = obj
|
||||
}
|
||||
|
||||
var document = {
|
||||
getElementById: function (v) {
|
||||
return {
|
||||
value: 'v'
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package cn.qaiu.vx.core.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class ParamUtilTest {
|
||||
|
||||
@Test
|
||||
public void paramsToMap() {
|
||||
System.out.println(ParamUtil.paramsToMap(""));
|
||||
System.out.println(ParamUtil.paramsToMap("a=asd&d=23"));
|
||||
System.out.println(ParamUtil.paramsToMap("asdasd&dd"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package cn.qaiu.vx.core.util;
|
||||
|
||||
import cn.qaiu.lz.common.util.SnowflakeIdWorker;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SnowflakeIdWorkerTest {
|
||||
|
||||
@Test
|
||||
public void idWorker() {
|
||||
final SnowflakeIdWorker idWorker = SnowflakeIdWorker.idWorker();
|
||||
for (int i = 0; i < 100; i++) {
|
||||
long id = idWorker.nextId();
|
||||
System.out.println(Long.toBinaryString(id));
|
||||
System.out.println(id);
|
||||
System.out.println("------------");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void idWorkerCluster() {
|
||||
final SnowflakeIdWorker snowflakeIdWorkerCluster = SnowflakeIdWorker.idWorkerCluster(0, 1);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
long id = snowflakeIdWorkerCluster.nextId();
|
||||
System.out.println(Long.toBinaryString(id));
|
||||
System.out.println(id);
|
||||
System.out.println("------------\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import javassist.bytecode.LocalVariableAttribute;
|
||||
import javassist.bytecode.MethodInfo;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -82,4 +83,14 @@ public class Test02 {
|
||||
System.out.println(map);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test4() {
|
||||
LocalDateTime parse = LocalDateTime.parse((String) "2022-01-01T11:22:00");
|
||||
System.out.println(parse);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user