Skip to content

Commit

Permalink
v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kecikeci committed May 28, 2024
1 parent dad7849 commit 9aaa7ce
Show file tree
Hide file tree
Showing 29 changed files with 330 additions and 4,735 deletions.
80 changes: 17 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,30 @@
# plugin-starter
## halo-plugin-image-url-handler

Halo 2.0 插件开发快速开始模板。
Halo 2.0 插件-图片链接处理

## 开发环境
### 插件说明

插件开发的详细文档请查阅:<https://docs.halo.run/developer-guide/plugin/introduction>
本插件主要为对象存储、CDN、nginx配置重定向等可设置图片处理参数的服务提供图片处理功能

所需环境:
### 功能逻辑

1. Java 17
2. Node 18
3. pnpm 8
4. Docker (可选)
拦截所有html页面(默认排除后台页面、系统页面等,也可自定义排除路径),解析出html页面中的图片链接(含`img`标签和`background-image`属性),并在图片链接后拼上配置的图片处理后缀

克隆项目:
### 预览地址

```bash
git clone [email protected]:halo-sigs/plugin-starter.git
[https://4xx.me](https://4xx.me)

# 或者当你 fork 之后
### 主题推荐

git clone [email protected]:{your_github_id}/plugin-starter.git
```
- [4xx-first](https://4xx.me/archives/4xx-first-tutorial)

```bash
cd path/to/plugin-starter
```
### 插件效果图

### 运行方式 1(推荐)
图片处理前
![图片处理前耗时.png](image%2F%CD%BC%C6%AC%B4%A6%C0%ED%C7%B0%BA%C4%CA%B1.png)
图片处理后
![图片处理后耗时.png](image%2F%CD%BC%C6%AC%B4%A6%C0%ED%BA%F3%BA%C4%CA%B1.png)

> 此方式需要本地安装 Docker
### 插件配置界面

```bash
# macOS / Linux
./gradlew pnpmInstall

# Windows
./gradlew.bat pnpmInstall
```

```bash
# macOS / Linux
./gradlew haloServer

# Windows
./gradlew.bat haloServer
```

执行此命令后,会自动创建一个 Halo 的 Docker 容器并加载当前的插件,更多文档可查阅:<https://docs.halo.run/developer-guide/plugin/basics/devtools>

### 运行方式 2

> 此方式需要使用源码运行 Halo
编译插件:

```bash
# macOS / Linux
./gradlew build

# Windows
./gradlew.bat build
```

修改 Halo 配置文件:

```yaml
halo:
plugin:
runtime-mode: development
fixedPluginPath:
- "/path/to/plugin-starter"
```
最后重启 Halo 项目即可。
![图片处理配置.png](image%2F%CD%BC%C6%AC%B4%A6%C0%ED%C5%E4%D6%C3.png)
28 changes: 14 additions & 14 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
plugins {
id 'java'
id "com.github.node-gradle.node" version "5.0.0"
// id "com.github.node-gradle.node" version "5.0.0"
id "io.freefair.lombok" version "8.0.1"
id "run.halo.plugin.devtools" version "0.0.9"
}

group 'run.halo.starter'
group 'me.forxx.plugin'
sourceCompatibility = JavaVersion.VERSION_17

repositories {
Expand All @@ -31,23 +31,23 @@ tasks.withType(JavaCompile).configureEach {
options.encoding = "UTF-8"
}

node {
nodeProjectDir = file("${project.projectDir}/ui")
}

tasks.register('buildFrontend', PnpmTask) {
args = ['build']
dependsOn('installDepsForUI')
}
//node {
// nodeProjectDir = file("${project.projectDir}/ui")
//}

tasks.register('installDepsForUI', PnpmTask) {
args = ['install']
}
//tasks.register('buildFrontend', PnpmTask) {
// args = ['build']
// dependsOn('installDepsForUI')
//}
//
//tasks.register('installDepsForUI', PnpmTask) {
// args = ['install']
//}

build {
// build frontend before build
tasks.named('compileJava').configure {
dependsOn('buildFrontend')
// dependsOn('buildFrontend')
}
}

Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
version=1.0.0-SNAPSHOT
version=1.0.0
Binary file added image/图片处理前耗时.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/图片处理后耗时.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image/图片处理配置.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ pluginManagement {
gradlePluginPortal()
}
}
rootProject.name = 'plugin-starter'
rootProject.name = 'halo-plugin-image-url-handler'

29 changes: 29 additions & 0 deletions src/main/java/me/forxx/plugin/ImageUrlHandlerPlugin.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package me.forxx.plugin;

import org.pf4j.PluginWrapper;
import org.springframework.stereotype.Component;
import run.halo.app.plugin.BasePlugin;

/**
* 返回数据处理插件
* @return
* @exception
* @author GMQ
* @date 2024/5/23 下午5:13
**/
@Component
public class ImageUrlHandlerPlugin extends BasePlugin {


public ImageUrlHandlerPlugin(PluginWrapper wrapper) {
super(wrapper);
}

@Override
public void start() {
}

@Override
public void stop() {
}
}
89 changes: 89 additions & 0 deletions src/main/java/me/forxx/plugin/ImageUrlHandlerWebFilter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package me.forxx.plugin;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatcher;
import org.springframework.security.web.server.util.matcher.ServerWebExchangeMatchers;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
import run.halo.app.plugin.ReactiveSettingFetcher;
import run.halo.app.security.AdditionalWebFilter;

/**
* 返回数据处理
*
* @author GMQ
* @date 2024/5/23 下午6:24
**/
@RequiredArgsConstructor
@Component
public class ImageUrlHandlerWebFilter implements AdditionalWebFilter {

final ServerWebExchangeMatcher
requiresMatcher = ServerWebExchangeMatchers.pathMatchers("/**");

private final ReactiveSettingFetcher reactiveSettingFetcher;

Logger log = LoggerFactory.getLogger(ImageUrlHandlerWebFilter.class);

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Mono<SettingConfig> settingConfigMono = reactiveSettingFetcher.fetch("setting",SettingConfig.class)
.defaultIfEmpty(new SettingConfig());
return requiresMatcher.matches(exchange)
.flatMap(matchResult -> {
// 使用flatMap操作符,将SettingConfig与matchResult组合
return settingConfigMono
.flatMap(settingConfig -> {
String suffix = settingConfig.getSuffix();
if (suffix == null || suffix.isEmpty()) {
return chain.filter(exchange);
}
String path = exchange.getRequest().getPath().toString();
if (isExcludedPath(path,settingConfig.getExcludedPaths())) { // 自定义逻辑判断是否排除
return chain.filter(exchange); // 跳过处理,不进行下一步
} else {
ResponseDecorator decorator = new ResponseDecorator(exchange.getResponse(), settingConfig.getSuffix());
return chain.filter(exchange.mutate().response(decorator).build());
}
});
})
.onErrorResume(ex -> chain.filter(exchange));
}

@Override
public int getOrder() {
return SecurityWebFiltersOrder.LAST.getOrder();
}


private boolean isExcludedPath(String path, String other) {
// 添加你的排除链接逻辑,例如:
String defaultExcludedPaths = "/console,/api,/apis,/actuator,/plugins,/upload,/uc";
String excludedPaths;
if (other == null || other.isEmpty()){
excludedPaths = defaultExcludedPaths;
}else {
excludedPaths = defaultExcludedPaths + "," + other;
}

for (String excludedPath : excludedPaths.split(",")) {
if (path.startsWith(excludedPath)) {
return true;
}
}
return false;
}

@Data
public static class SettingConfig {
String suffix;
String excludedPaths;
}

}
Loading

0 comments on commit 9aaa7ce

Please sign in to comment.