-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathPHPFpm.java
More file actions
122 lines (102 loc) · 3.69 KB
/
PHPFpm.java
File metadata and controls
122 lines (102 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
package roj.plugins.php;
import org.jetbrains.annotations.Nullable;
import roj.concurrent.TaskThread;
import roj.config.node.ConfigValue;
import roj.config.node.MapValue;
import roj.config.node.Type;
import roj.http.server.*;
import roj.io.IOUtil;
import roj.plugin.PanHttp;
import roj.plugin.Plugin;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* @author Roj234
* @since 2024/7/10 3:17
*/
public class PHPFpm extends Plugin implements Router, Predicate<String> {
private fcgiManagerImpl fpm;
@Override
protected void onEnable() throws Exception {
MapValue config = getConfig();
List<String> args;
ConfigValue entry = config.get("fcgi_executable");
args = entry.getType() == Type.LIST ? entry.asList().toStringList() : Collections.singletonList(entry.asString());
Path cgi_exe = getDataFolder().toPath().resolve(Path.of(args.get(0)));
if (!Files.isExecutable(cgi_exe)) {
getLogger().error("PHP可执行文件{}不存在", cgi_exe);
getPluginManager().unloadPlugin(getDescription());
return;
}
Path document_root = getDataFolder().toPath().resolve(Path.of(config.getString("document_root")));
if (!Files.isDirectory(document_root)) {
getLogger().error("文档根目录{}不存在", document_root);
getPluginManager().unloadPlugin(getDescription());
return;
}
fpm = new fcgiManagerImpl(config.getInt("fcgi_process_stale_max"), config.getInt("fcgi_process_max"), config.getInt("fcgi_process_timeout", 600000), args);
fpm.docRoot = document_root.toFile();
fpm.portBase = 40000 + (int)System.nanoTime()%20000;
var dispatcher = new TaskThread();
dispatcher.setName("PHP-FPM 请求分配");
dispatcher.start();
dispatcher.executeUnsafe(fpm);
String pluginRoot = config.getString("url_root");
registerRoute(pluginRoot, this, "PermissionManager");
PanHttp.addStatusProvider((sb, request) ->
sb.append("PHP-FPM for Win32:\n 活动的进程: ").append(fpm.processes.size()).append('/').append(fpm.maxProcess)
.append("\n 排队的请求: ").append(fpm.pendingTask.size()));
getLogger().warn("PHP服务器已在路径{} => {}上启动", fpm.docRoot, pluginRoot);
}
// 然而并不会生效
@Override
public int writeTimeout(@Nullable Request req, @Nullable Content resp) {return Integer.MAX_VALUE;}
@Override
public Content response(Request req, Response resp) throws Exception {
if (req.path().endsWith(".php")) return fpm.response(req, resp);
File file = new File(fpm.docRoot, req.path());
check: {
if (!file.isFile()) {
if (file.isDirectory()) {
if (!req.path().endsWith("/") && !req.path().isEmpty()) {
resp.code(302).setHeader("Location", req.path()+"/");
return null;
}
File[] files = file.listFiles((dir, name) -> name.equals("index.html") || name.equals("index.php"));
if (files != null && files.length > 0 && files[0].isFile()) {
file = files[0];
if (file.getName().endsWith(".php")) {
req.setPath(req.path()+file.getName());
return fpm.response(req, resp);
}
break check;
}
}
resp.code(404);
return Content.httpError(404);
}
}
return Content.file(req, new DiskFileInfo(file));
}
// (Optional) for OKRouter Prefix Delegation check
@Override
public boolean test(String url) {
var file = IOUtil.resolveSafe(fpm.docRoot, url);
return file != null && file.exists();
}
@Override
public void checkHeader(Request req, @Nullable PayloadInfo cfg) throws IllegalRequestException {
if (req.path().endsWith(".php")) fpm.checkHeader(req, cfg);
}
@Override
protected void onDisable() {
if (fpm != null) {
fpm.stop();
fpm.killAll();
}
}
}