refactory
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
//file:noinspection GrUnresolvedAccess
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
dependencies {
|
||||
implementation(project(':mirror-app'))
|
||||
implementation(project(':mirror-core'))
|
||||
|
||||
annotationProcessor('org.springframework.boot:spring-boot-configuration-processor')
|
||||
implementation('org.springframework.boot:spring-boot-starter-web')
|
||||
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor:${springBootVerson}")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web:${springBootVerson}")
|
||||
implementation("org.springframework.boot:spring-boot-starter-freemarker:${springBootVerson}")
|
||||
}
|
||||
|
||||
tasks.named('compileJava') {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package ru.di9.mirror.web.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "maven-mirrors")
|
||||
public class MavenMirrorsProperties {
|
||||
|
||||
@Getter
|
||||
private final List<MirrorData> list = new ArrayList<>();
|
||||
|
||||
public record MirrorData(String id, String url) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,14 @@
|
||||
package ru.di9.mirror.web.config;
|
||||
|
||||
import io.minio.MinioClient;
|
||||
import okhttp3.OkHttpClient;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import ru.di9.mirror.app.service.*;
|
||||
import ru.di9.mirror.core.handler.IndexOfHandler;
|
||||
import ru.di9.mirror.core.handler.MavenHandler;
|
||||
import ru.di9.mirror.core.service.ExternalMavenService;
|
||||
import ru.di9.mirror.core.service.MinioService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -12,20 +16,42 @@ import java.util.List;
|
||||
public class WebConfig {
|
||||
|
||||
@Bean
|
||||
public StorageService mirroredStorageService(FileStorageService fileStorageService,
|
||||
List<MirrorService> mirrors) {
|
||||
return new MirroredStorageService(fileStorageService, mirrors);
|
||||
public MavenHandler mavenHandler(MinioService minioService,
|
||||
List<ExternalMavenService> externalMavenServices) {
|
||||
return new MavenHandler(minioService, externalMavenServices);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FileStorageService fileStorageService(@Value("${maven.storage}") String storagePath) {
|
||||
return new FileStorageService(storagePath);
|
||||
public IndexOfHandler indexOfHandler(MinioService minioService) {
|
||||
return new IndexOfHandler(minioService);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<MirrorService> mirrors() {
|
||||
return List.of(
|
||||
new MavenCentralStorageService(new OkHttpClient())
|
||||
);
|
||||
public MinioService minioService(MinioClient minioClient, @Value("${minio.bucket}") String bucket) {
|
||||
return new MinioService(minioClient, bucket);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MinioClient minioClient(@Value("${minio.url}") String url,
|
||||
@Value("${minio.accessKey}") String accessKey,
|
||||
@Value("${minio.secretKey}") String secretKey) {
|
||||
return MinioClient.builder()
|
||||
.endpoint(url)
|
||||
.credentials(accessKey, secretKey)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public List<ExternalMavenService> externalMavenServices(OkHttpClient okHttpClient,
|
||||
MavenMirrorsProperties mavenMirrorsProperties) {
|
||||
return mavenMirrorsProperties.getList().stream()
|
||||
.map(mirrorData -> new ExternalMavenService(mirrorData.id(), mirrorData.url(), okHttpClient))
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OkHttpClient okHttpClient() {
|
||||
return new OkHttpClient();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,86 +1,79 @@
|
||||
package ru.di9.mirror.web.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.di9.mirror.app.Utils;
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
import ru.di9.mirror.app.domain.PathRecord;
|
||||
import ru.di9.mirror.app.domain.PathType;
|
||||
import ru.di9.mirror.app.domain.WalkerResult;
|
||||
import ru.di9.mirror.app.service.StorageService;
|
||||
import ru.di9.mirror.core.Utils;
|
||||
import ru.di9.mirror.core.domain.ItemRecord2;
|
||||
import ru.di9.mirror.core.handler.IndexOfHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Controller
|
||||
@RequestMapping(path = "/maven")
|
||||
public class IndexOfMavenController {
|
||||
private final StorageService storageService;
|
||||
|
||||
public IndexOfMavenController(@Qualifier("mirroredStorageService") StorageService storageService) {
|
||||
this.storageService = storageService;
|
||||
private final IndexOfHandler indexOfHandler;
|
||||
|
||||
public IndexOfMavenController(IndexOfHandler indexOfHandler) {
|
||||
this.indexOfHandler = indexOfHandler;
|
||||
}
|
||||
|
||||
@GetMapping(path = "/{*path}", headers = "accept=text/html")
|
||||
public ResponseEntity<Object> walker(@PathVariable("path") String httpPath) {
|
||||
ResponseEntity<Object> responseEntity;
|
||||
public String walker(@PathVariable("path") String httpPath,
|
||||
@ModelAttribute("model") ModelMap model) {
|
||||
String path = correctingHttpPath(httpPath);
|
||||
|
||||
Optional<WalkerResult> walkerResultOptional = storageService.walker(httpPath);
|
||||
if (walkerResultOptional.isEmpty()) {
|
||||
responseEntity = ResponseEntity.status(HttpStatus.NOT_FOUND)
|
||||
.body("<html><body><h1>404 - Not Found</h1><hr><p style=\"text-align:right\">Project-Mirror</p></body></html>");
|
||||
} else {
|
||||
WalkerResult walkerResult = walkerResultOptional.get();
|
||||
if (walkerResult.pathType() == PathType.DIRECTORY) {
|
||||
responseEntity = generateIndexOf(httpPath, walkerResult.filesList());
|
||||
} else {
|
||||
responseEntity = downloadFile(walkerResult.fileRecord());
|
||||
List<ItemRecord2> walker = indexOfHandler.walker(path);
|
||||
List<ModelLink> links = new ArrayList<>();
|
||||
|
||||
StringBuilder sb = new StringBuilder("/maven");
|
||||
int resetLength = sb.length();
|
||||
|
||||
if (Utils.isNotEmptyString(path)) {
|
||||
int idx = path.lastIndexOf("/");
|
||||
if (idx > -1) {
|
||||
sb.append("/").append(path, 0, idx);
|
||||
}
|
||||
|
||||
links.add(new ModelLink("..", sb.toString()));
|
||||
}
|
||||
|
||||
return responseEntity;
|
||||
}
|
||||
sb.setLength(resetLength);
|
||||
sb.append("/");
|
||||
resetLength = sb.length();
|
||||
for (ItemRecord2 itemRecord2 : walker) {
|
||||
if (Utils.isNotEmptyString(path)) {
|
||||
sb.append(path).append("/");
|
||||
}
|
||||
sb.append(itemRecord2.name());
|
||||
|
||||
private ResponseEntity<Object> downloadFile(FileRecord fileRecord) {
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + fileRecord.name() + "\"")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(fileRecord.size())
|
||||
.body(new InputStreamResource(fileRecord.inputStream()));
|
||||
}
|
||||
|
||||
private ResponseEntity<Object> generateIndexOf(String httpPath, List<PathRecord> filesList) {
|
||||
ResponseEntity<Object> responseEntity;
|
||||
StringBuilder sb = new StringBuilder("<html><body><h1>Index of</h1><hr><ul>");
|
||||
|
||||
if (!Utils.isEmptyString(httpPath)) {
|
||||
String levelUpPath = httpPath.substring(0, httpPath.lastIndexOf("/"));
|
||||
sb.append("<li><a href=\"/maven").append(levelUpPath).append("\">..</a></li>");
|
||||
links.add(new ModelLink(itemRecord2.name() + (itemRecord2.isDir() ? "/" : ""), sb.toString()));
|
||||
sb.setLength(resetLength);
|
||||
}
|
||||
|
||||
filesList.forEach(pathRecord -> {
|
||||
sb.append("<li><a href=\"/maven")
|
||||
.append(httpPath)
|
||||
.append("/")
|
||||
.append(pathRecord.name())
|
||||
.append("\">")
|
||||
.append(pathRecord.name());
|
||||
if (pathRecord.type() == PathType.DIRECTORY) {
|
||||
sb.append("/");
|
||||
}
|
||||
sb.append("</a></li>");
|
||||
});
|
||||
model.put("links", links);
|
||||
return "list";
|
||||
}
|
||||
|
||||
responseEntity = ResponseEntity.ok(sb.append("</ul><hr><p style=\"text-align:right\">Project-Mirror</p></body></html>").toString());
|
||||
return responseEntity;
|
||||
private String correctingHttpPath(String httpPath) {
|
||||
String path = httpPath;
|
||||
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
if (path.endsWith("/")) {
|
||||
path = path.substring(0, path.length() - 1);
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
public record ModelLink(String name, String link) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package ru.di9.mirror.web.controller;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.io.InputStreamResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -12,43 +11,31 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import ru.di9.mirror.app.domain.FileRecord;
|
||||
import ru.di9.mirror.app.service.StorageService;
|
||||
import ru.di9.mirror.core.handler.MavenHandler;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Optional;
|
||||
|
||||
@Slf4j
|
||||
@Controller
|
||||
@RequestMapping(path = "/maven")
|
||||
public class MavenController {
|
||||
private final StorageService storageService;
|
||||
private final MavenHandler mavenHandler;
|
||||
|
||||
public MavenController(@Qualifier("mirroredStorageService") StorageService storageService) {
|
||||
this.storageService = storageService;
|
||||
public MavenController(MavenHandler mavenHandler) {
|
||||
this.mavenHandler = mavenHandler;
|
||||
}
|
||||
|
||||
@GetMapping(path = "/{*path}")
|
||||
@GetMapping(path = "/{*path}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
|
||||
public ResponseEntity<Resource> mavenGetFile(@PathVariable("path") String httpPath) {
|
||||
ResponseEntity<Resource> responseEntity;
|
||||
|
||||
Optional<FileRecord> fileRecordOptional = storageService.getFile(httpPath);
|
||||
if (fileRecordOptional.isEmpty()) {
|
||||
responseEntity = ResponseEntity.notFound().build();
|
||||
} else {
|
||||
FileRecord fileRecord = fileRecordOptional.get();
|
||||
|
||||
responseEntity = ResponseEntity.ok()
|
||||
return mavenHandler.getFile(httpPath.substring(1))
|
||||
.<ResponseEntity<Resource>>map(response -> ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_DISPOSITION,
|
||||
"attachment; filename=\"" + fileRecord.name() + "\"")
|
||||
"attachment; filename=\"" + response.name() + "\"")
|
||||
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||
.contentLength(fileRecord.size())
|
||||
.body(new InputStreamResource(fileRecord.inputStream()));
|
||||
}
|
||||
|
||||
return responseEntity;
|
||||
.body(new InputStreamResource(response.inputStream())))
|
||||
.orElseGet(() -> ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
@SuppressWarnings("java:S1452")
|
||||
@@ -57,7 +44,7 @@ public class MavenController {
|
||||
HttpServletRequest httpRequest) throws IOException {
|
||||
|
||||
try (InputStream inputStream = httpRequest.getInputStream()) {
|
||||
storageService.putFile(httpPath, inputStream);
|
||||
mavenHandler.putFile(httpPath.substring(1), inputStream);
|
||||
}
|
||||
|
||||
return ResponseEntity.noContent().build();
|
||||
|
||||
@@ -1,8 +1,28 @@
|
||||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "maven.storage",
|
||||
"type": "java.lang.String"
|
||||
"properties": [
|
||||
{
|
||||
"name": "minio.url",
|
||||
"type": "java.lang.String",
|
||||
"description": "MinIO console url."
|
||||
},
|
||||
{
|
||||
"name": "minio.accessKey",
|
||||
"type": "java.lang.String",
|
||||
"description": "MinIO Access key (login)."
|
||||
},
|
||||
{
|
||||
"name": "minio.secretKey",
|
||||
"type": "java.lang.String",
|
||||
"description": "MinIO Secret key (password)."
|
||||
},
|
||||
{
|
||||
"name": "minio.bucket",
|
||||
"type": "java.lang.String",
|
||||
"description": "MinIO Bucket name."
|
||||
},
|
||||
{
|
||||
"name": "maven-mirrors.list",
|
||||
"type": "java.util.List<ru.di9.mirror.web.config.MavenMirrorsProperties.MirrorData>",
|
||||
"sourceType": "java.util.List<ru.di9.mirror.web.config.MavenMirrorsProperties.MirrorData>"
|
||||
}
|
||||
]
|
||||
}
|
||||
] }
|
||||
|
||||
@@ -2,7 +2,22 @@ server:
|
||||
address: 127.0.0.1
|
||||
port: 8080
|
||||
|
||||
spring:
|
||||
freemarker:
|
||||
template-loader-path: classpath:/templates
|
||||
suffix: .ftl
|
||||
|
||||
debug: false
|
||||
|
||||
maven:
|
||||
storage: './storage'
|
||||
minio:
|
||||
url: 'http://dev.di9.ru:9000'
|
||||
accessKey: 'mirror'
|
||||
secretKey: 'mirror123'
|
||||
bucket: 'mirror'
|
||||
|
||||
maven-mirrors:
|
||||
list:
|
||||
- id: 'maven_central'
|
||||
url: 'https://repo1.maven.org/maven2'
|
||||
- id: 'spigot'
|
||||
url: 'https://hub.spigotmc.org/nexus/content/groups/public'
|
||||
|
||||
19
mirror-web/src/main/resources/templates/list.ftl
Normal file
19
mirror-web/src/main/resources/templates/list.ftl
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<header>
|
||||
<meta charset="UTF-8">
|
||||
<title>Project-Mirror</title>
|
||||
</header>
|
||||
<body>
|
||||
<h1>Index of</h1>
|
||||
<hr>
|
||||
<ul>
|
||||
<#--noinspection FtlTypesInspection-->
|
||||
<#list model["links"] as item>
|
||||
<li><a href="${item.link()}">${item.name()}</a></li>
|
||||
</#list>
|
||||
</ul>
|
||||
<hr>
|
||||
<p style="text-align:right">Project-Mirror</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user