fix timeout, cors and token issues

This commit is contained in:
Krrish Ghimire
2026-07-10 11:39:19 +05:45
parent 3e77b54d71
commit 24ca1521b4
8 changed files with 55 additions and 13 deletions

View File

@@ -5,7 +5,6 @@ import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
@@ -13,7 +12,6 @@ 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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
@@ -33,9 +31,6 @@ public class SecurityConfig {
private final JwtConfig jwtConfig;
@Value("${indie.cors.allowed-origins:http://localhost:4200}")
private String[] allowedOrigins;
public SecurityConfig(JwtConfig jwtConfig) {
this.jwtConfig = jwtConfig;
}
@@ -72,7 +67,7 @@ public class SecurityConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(List.of(allowedOrigins));
config.setAllowedOriginPatterns(List.of("*"));
config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
config.setAllowedHeaders(List.of("*"));
config.setAllowCredentials(true);

View File

@@ -72,7 +72,7 @@ public class LLMController {
SiteStructure structure = llmService.generateSite(
principal.id(), siteId, prompt, references, provider, apiKey, baseUrl, model);
return ResponseEntity.ok(structure);
} catch (IllegalStateException e) {
} catch (IllegalStateException | IllegalArgumentException e) {
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
}
}
@@ -130,7 +130,7 @@ public class LLMController {
SiteStructure structure = llmService.refineSite(principal.id(), siteId,
currentStructure, prompt, references, provider, apiKey, baseUrl, model);
return ResponseEntity.ok(structure);
} catch (IllegalStateException e) {
} catch (IllegalStateException | IllegalArgumentException e) {
return ResponseEntity.badRequest().body(Map.of("error", e.getMessage()));
}
}

View File

@@ -13,7 +13,7 @@ public class LLMOptions {
private double temperature = 0.9;
@Builder.Default
private int maxTokens = 4096;
private int maxTokens = 16384;
@Builder.Default
private int timeoutSeconds = 60;

View File

@@ -6,6 +6,7 @@ import com.krrishg.dto.LLMResult;
import com.krrishg.dto.Reference;
import com.krrishg.dto.SiteStructure;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.ResourceAccessException;
import com.krrishg.model.GenerationVersion;
import com.krrishg.model.User;
import com.krrishg.repository.UserRepository;
@@ -204,6 +205,9 @@ public class LLMService {
LLMProvider p = providerFactory.createProvider(provider, apiKey, baseUrl, model);
try {
return p.generate(systemPrompt, userPrompt, references, options);
} catch (ResourceAccessException e) {
throw new IllegalStateException(
provider + " timed out. Please try again or use a simpler prompt.");
} catch (HttpClientErrorException e) {
String detail = e.getResponseBodyAsString();
String msg = switch (e.getStatusCode().value()) {

View File

@@ -14,14 +14,17 @@ public class ProviderFactory {
private final RestTemplateBuilder restTemplateBuilder;
private final Map<String, ProviderConfig> providerConfigs;
private final Duration readTimeout;
public ProviderFactory(
@Value("${indie.llm.providers.gemini.model:gemini-3.1-flash-lite}") String geminiModel,
@Value("${indie.llm.providers.gemini.url:https://generativelanguage.googleapis.com/v1beta/models}") String geminiUrl,
@Value("${indie.llm.providers.openai.model:gpt-4o-mini}") String openaiModel,
@Value("${indie.llm.providers.openai.url:https://api.openai.com/v1/chat/completions}") String openaiUrl,
@Value("${indie.llm.read-timeout:180s}") Duration readTimeout,
RestTemplateBuilder restTemplateBuilder) {
this.restTemplateBuilder = restTemplateBuilder;
this.readTimeout = readTimeout;
this.providerConfigs = Map.of(
"gemini", new ProviderConfig(geminiModel, geminiUrl),
"openai", new ProviderConfig(openaiModel, openaiUrl)
@@ -52,7 +55,7 @@ public class ProviderFactory {
}
RestTemplate rt = restTemplateBuilder
.setConnectTimeout(Duration.ofSeconds(30))
.setReadTimeout(Duration.ofSeconds(60))
.setReadTimeout(readTimeout)
.build();
return switch (name) {
case "gemini" -> new GeminiProvider(apiKey, resolvedModel, url, rt);

View File

@@ -55,9 +55,6 @@ indie:
repos-path: ${INDIE_GIT_REPOS_PATH:/home/krrish/git/sites/}
author-name: ${INDIE_GIT_AUTHOR_NAME:Indie Platform}
author-email: ${INDIE_GIT_AUTHOR_EMAIL:git@indie.local}
cors:
allowed-origins: ${INDIE_CORS_ORIGINS:http://localhost:4200,http://localhost:3000}
storage:
endpoint: ${INDIE_STORAGE_ENDPOINT:http://localhost:9000}
region: ${INDIE_STORAGE_REGION:auto}
@@ -74,6 +71,7 @@ indie:
verification-token-expiration-minutes: ${INDIE_VERIFICATION_TOKEN_EXPIRATION:1440}
llm:
read-timeout: ${INDIE_LLM_READ_TIMEOUT:180s}
rate-limit:
max-requests-per-hour: ${INDIE_LLM_RATE_LIMIT:10}
providers: