Add client persistence
This commit is contained in:
Binary file not shown.
@@ -30,6 +30,26 @@
|
||||
<java.version>17</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.xerial</groupId>
|
||||
<artifactId>sqlite-jdbc</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-community-dialects</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.flywaydb</groupId>
|
||||
<artifactId>flyway-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
package com.litoralregas.backend_gateway;
|
||||
|
||||
import com.litoralregas.backend_gateway.gateway.ProxyProperties;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties(ProxyProperties.class)
|
||||
public class BackendGatewayApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(BackendGatewayApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,56 @@
|
||||
package com.litoralregas.backend_gateway.client;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "clients")
|
||||
public class ClientEntity {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(nullable = false, unique = true)
|
||||
private String name;
|
||||
|
||||
@Column(name = "backend_base_url", nullable = false)
|
||||
private String backendBaseUrl;
|
||||
|
||||
@Column(nullable = false)
|
||||
private boolean enabled = true;
|
||||
|
||||
@Column(name = "created_at", nullable = false, insertable = false, updatable = false)
|
||||
private String createdAt;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getBackendBaseUrl() {
|
||||
return backendBaseUrl;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public String getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setBackendBaseUrl(String backendBaseUrl) {
|
||||
this.backendBaseUrl = backendBaseUrl;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,10 @@
|
||||
package com.litoralregas.backend_gateway.client;
|
||||
|
||||
public class ClientRepository {
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface ClientRepository extends JpaRepository<ClientEntity, Long> {
|
||||
|
||||
Optional<ClientEntity> findByName(String name);
|
||||
}
|
||||
@@ -1,14 +1,25 @@
|
||||
package com.litoralregas.backend_gateway.config;
|
||||
|
||||
import com.litoralregas.backend_gateway.gateway.ProxyProperties;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import reactor.netty.http.client.HttpClient;
|
||||
|
||||
@Configuration
|
||||
public class WebClientConfig {
|
||||
|
||||
@Bean
|
||||
public WebClient webClient(WebClient.Builder builder) {
|
||||
return builder.build();
|
||||
public WebClient webClient(WebClient.Builder builder, ProxyProperties proxyProperties) {
|
||||
HttpClient httpClient = HttpClient.create()
|
||||
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS,
|
||||
Math.toIntExact(proxyProperties.getConnectTimeout().toMillis()))
|
||||
.responseTimeout(proxyProperties.getResponseTimeout());
|
||||
|
||||
return builder
|
||||
.clientConnector(new ReactorClientHttpConnector(httpClient))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,79 @@
|
||||
package com.litoralregas.backend_gateway.gateway;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
import org.springframework.web.reactive.function.client.WebClientResponseException;
|
||||
|
||||
@Service
|
||||
public class BackendProxyService {
|
||||
|
||||
private final WebClient webClient;
|
||||
private final String devBackendUrl;
|
||||
private final ProxyProperties proxyProperties;
|
||||
|
||||
public BackendProxyService(
|
||||
WebClient webClient,
|
||||
@Value("${gateway.dev-backend-url}") String devBackendUrl
|
||||
) {
|
||||
public BackendProxyService(WebClient webClient, ProxyProperties proxyProperties) {
|
||||
this.webClient = webClient;
|
||||
this.devBackendUrl = devBackendUrl;
|
||||
this.proxyProperties = proxyProperties;
|
||||
}
|
||||
|
||||
public String getHealth() {
|
||||
return webClient.get()
|
||||
.uri(devBackendUrl + "/actuator/health")
|
||||
.uri(proxyProperties.getBackendBaseUrl() + "/actuator/health")
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.block();
|
||||
}
|
||||
|
||||
public ResponseEntity<String> proxy(HttpServletRequest request, String body) {
|
||||
|
||||
String path = request.getRequestURI().replaceFirst("/api/backend", "");
|
||||
String query = request.getQueryString();
|
||||
|
||||
String targetUrl = devBackendUrl + path + (query != null ? "?" + query : "");
|
||||
String targetUrl =
|
||||
proxyProperties.getBackendBaseUrl()
|
||||
+ path
|
||||
+ (query != null ? "?" + query : "");
|
||||
|
||||
String response = webClient
|
||||
try {
|
||||
WebClient.RequestBodySpec requestSpec = webClient
|
||||
.method(HttpMethod.valueOf(request.getMethod()))
|
||||
.uri(targetUrl)
|
||||
.uri(targetUrl);
|
||||
|
||||
String contentType = request.getContentType();
|
||||
|
||||
if (contentType != null) {
|
||||
requestSpec.header("Content-Type", contentType);
|
||||
}
|
||||
|
||||
String accept = request.getHeader("Accept");
|
||||
|
||||
if (accept != null) {
|
||||
requestSpec.header("Accept", accept);
|
||||
}
|
||||
|
||||
ResponseEntity<String> response = requestSpec
|
||||
.bodyValue(body != null ? body : "")
|
||||
.retrieve()
|
||||
.bodyToMono(String.class)
|
||||
.toEntity(String.class)
|
||||
.block();
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
return ResponseEntity
|
||||
.status(response.getStatusCode())
|
||||
.headers(response.getHeaders())
|
||||
.body(response.getBody());
|
||||
|
||||
} catch (WebClientResponseException ex) {
|
||||
return ResponseEntity
|
||||
.status(ex.getStatusCode())
|
||||
.body(ex.getResponseBodyAsString());
|
||||
|
||||
} catch (Exception ex) {
|
||||
return ResponseEntity
|
||||
.status(HttpStatus.BAD_GATEWAY)
|
||||
.body("Backend unavailable");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.litoralregas.backend_gateway.gateway;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
@ConfigurationProperties(prefix = "gateway.proxy")
|
||||
public class ProxyProperties {
|
||||
|
||||
private String backendBaseUrl;
|
||||
private Duration connectTimeout = Duration.ofSeconds(3);
|
||||
private Duration responseTimeout = Duration.ofSeconds(10);
|
||||
|
||||
public String getBackendBaseUrl() {
|
||||
return backendBaseUrl;
|
||||
}
|
||||
|
||||
public void setBackendBaseUrl(String backendBaseUrl) {
|
||||
this.backendBaseUrl = backendBaseUrl;
|
||||
}
|
||||
|
||||
public Duration getConnectTimeout() {
|
||||
return connectTimeout;
|
||||
}
|
||||
|
||||
public void setConnectTimeout(Duration connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
public Duration getResponseTimeout() {
|
||||
return responseTimeout;
|
||||
}
|
||||
|
||||
public void setResponseTimeout(Duration responseTimeout) {
|
||||
this.responseTimeout = responseTimeout;
|
||||
}
|
||||
}
|
||||
@@ -5,5 +5,22 @@ spring:
|
||||
application:
|
||||
name: backend-gateway
|
||||
|
||||
datasource:
|
||||
url: jdbc:sqlite:./data/backend-gateway.db
|
||||
driver-class-name: org.sqlite.JDBC
|
||||
|
||||
jpa:
|
||||
database-platform: org.hibernate.community.dialect.SQLiteDialect
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
show-sql: true
|
||||
|
||||
flyway:
|
||||
enabled: true
|
||||
locations: classpath:db/migration
|
||||
|
||||
gateway:
|
||||
dev-backend-url: http://10.100.1.2:18450
|
||||
proxy:
|
||||
backend-base-url: http://10.100.1.2:18450
|
||||
connect-timeout: 3s
|
||||
response-timeout: 10s
|
||||
@@ -0,0 +1,7 @@
|
||||
CREATE TABLE clients (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
backend_base_url TEXT NOT NULL,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
Reference in New Issue
Block a user