Create backend parser concept

This commit is contained in:
Sandra
2022-01-28 19:52:47 +01:00
parent 3f7a489362
commit 953a54998e
4 changed files with 144 additions and 3 deletions

View File

@@ -0,0 +1,13 @@
package eu.okaeri.timings.api;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class IndexController {
@RequestMapping
public String index() {
return "redirect:/swagger-ui";
}
}

View File

@@ -0,0 +1,36 @@
package eu.okaeri.timings.api.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Arrays;
import java.util.List;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().disable();
http.csrf().disable();
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(List.of("*"));
config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization"));
config.setAllowedMethods(List.of("*"));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

View File

@@ -0,0 +1,90 @@
package eu.okaeri.timings.api.v1;
import lombok.SneakyThrows;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/v1/parse")
public class ParseController {
@SneakyThrows
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> parse(@RequestPart("file") MultipartFile file) {
if (!"text/csv".equals(file.getContentType())) {
return ResponseEntity.badRequest().body(Map.of("error", "Expected text/csv, got: " + file.getContentType()));
}
String content = new String(file.getBytes(), StandardCharsets.UTF_8);
String[] lines = content.split("\r?\n");
Map<String, String> metadata = new LinkedHashMap<>();
List<String> header = null;
List<List<BigDecimal>> records = new ArrayList<>();
for (String line : lines) {
// metadata
if (line.startsWith("#")) {
if (!line.contains(":")) {
continue;
}
String[] parts = line.substring(1).split(":", 2);
if (parts.length != 2) {
throw new RuntimeException("Cannot parse metadata: '" + line + "'");
}
String key = parts[0].trim().toLowerCase(Locale.ROOT);
String value = parts[1].trim();
metadata.put(key, value);
continue;
}
// header
if (header == null) {
String[] parts = line.split(",");
if (parts.length < 2) {
throw new RuntimeException("Cannot parse header: '" + line + "'");
}
header = Arrays.asList(parts);
continue;
}
// data
String[] parts = line.split(",");
if (parts.length != header.size()) {
throw new RuntimeException("Cannot parse record: '" + line + "'");
}
records.add(Arrays.stream(parts)
.map(value -> {
try {
return new BigDecimal(value);
} catch (Exception exception) {
throw new RuntimeException("Cannot parse value: '" + value + "' from record '" + line + "'");
}
})
.collect(Collectors.toList()));
}
if (header == null || records.size() < 2) {
throw new RuntimeException("Invalid report");
}
return ResponseEntity.ok(Map.of(
"meta", metadata,
"header", header,
"data", records
));
}
}

View File

@@ -20,9 +20,11 @@ springdoc:
default-produces-media-type: "application/json" default-produces-media-type: "application/json"
spring: spring:
data: servlet:
rest: multipart:
base-path: /rest enabled: true
max-file-size: 1MB
max-request-size: 1MB
redis: redis:
host: 127.0.0.1 host: 127.0.0.1
port: 6379 port: 6379