added apiKey
This commit is contained in:
parent
04f3ef22e8
commit
6d0a22a314
@ -12,6 +12,10 @@ import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
public class HttpServerApp {
|
||||
|
||||
// ✅ Statický API klíč
|
||||
private static final String API_KEY = "JustSomeRandomText";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
TransmissionService service = new TransmissionService();
|
||||
service.loadNextDays(10);
|
||||
@ -23,6 +27,8 @@ public class HttpServerApp {
|
||||
server.createContext("/transmissions", exchange -> {
|
||||
try {
|
||||
setCors(exchange);
|
||||
if (!checkApiKey(exchange)) return;
|
||||
|
||||
List<Transmission> all = service.getAll();
|
||||
respondJson(exchange, mapper.writeValueAsString(all));
|
||||
} catch (Exception e) {
|
||||
@ -35,6 +41,8 @@ public class HttpServerApp {
|
||||
server.createContext("/search", exchange -> {
|
||||
try {
|
||||
setCors(exchange);
|
||||
if (!checkApiKey(exchange)) return;
|
||||
|
||||
URI uri = exchange.getRequestURI();
|
||||
String query = null;
|
||||
if (uri.getQuery() != null) {
|
||||
@ -53,10 +61,12 @@ public class HttpServerApp {
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ NEW: /refresh endpoint
|
||||
// /refresh endpoint
|
||||
server.createContext("/refresh", exchange -> {
|
||||
try {
|
||||
setCors(exchange);
|
||||
if (!checkApiKey(exchange)) return;
|
||||
|
||||
if ("GET".equalsIgnoreCase(exchange.getRequestMethod())) {
|
||||
service.reloadDataAsync();
|
||||
respondJson(exchange, "{\"status\":\"ok\",\"message\":\"Data se obnovují na pozadí.\"}");
|
||||
@ -96,17 +106,44 @@ public class HttpServerApp {
|
||||
|
||||
server.start();
|
||||
System.out.println("🚀 HTTP server běží na http://localhost:8080");
|
||||
System.out.println(" ➜ /transmissions (všechny přenosy JSON)");
|
||||
System.out.println(" ➜ /search?q=Brno (vyhledávání JSON)");
|
||||
System.out.println(" ➜ /refresh (spustí opětovné načtení dat)");
|
||||
System.out.println(" ➜ /transmissions (všechny přenosy JSON, vyžaduje X-API-KEY)");
|
||||
System.out.println(" ➜ /search?q=Brno (vyhledávání JSON, vyžaduje X-API-KEY)");
|
||||
System.out.println(" ➜ /refresh (spustí opětovné načtení dat, vyžaduje X-API-KEY)");
|
||||
System.out.println(" ➜ / (web UI)");
|
||||
}
|
||||
|
||||
// ======= API Key ochrana =======
|
||||
private static boolean checkApiKey(HttpExchange exchange) throws IOException {
|
||||
String query = exchange.getRequestURI().getQuery(); // např. apiKey=xxxx
|
||||
String key = null;
|
||||
|
||||
if (query != null) {
|
||||
for (String part : query.split("&")) {
|
||||
if (part.startsWith("apiKey=")) {
|
||||
key = java.net.URLDecoder.decode(part.substring(7), StandardCharsets.UTF_8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!API_KEY.equals(key)) {
|
||||
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
|
||||
byte[] bytes = "{\"error\":\"Unauthorized\"}".getBytes(StandardCharsets.UTF_8);
|
||||
exchange.sendResponseHeaders(401, bytes.length);
|
||||
try (OutputStream os = exchange.getResponseBody()) {
|
||||
os.write(bytes);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ======= CORS =======
|
||||
private static void setCors(HttpExchange exchange) {
|
||||
Headers h = exchange.getResponseHeaders();
|
||||
h.set("Access-Control-Allow-Origin", "*");
|
||||
h.set("Access-Control-Allow-Methods", "GET, OPTIONS");
|
||||
h.set("Access-Control-Allow-Headers", "Content-Type");
|
||||
h.set("Access-Control-Allow-Headers", "Content-Type, X-API-KEY");
|
||||
if ("OPTIONS".equalsIgnoreCase(exchange.getRequestMethod())) {
|
||||
try {
|
||||
exchange.sendResponseHeaders(204, -1);
|
||||
@ -116,6 +153,7 @@ public class HttpServerApp {
|
||||
}
|
||||
}
|
||||
|
||||
// ======= JSON odpověď =======
|
||||
private static void respondJson(HttpExchange exchange, String json) throws IOException {
|
||||
exchange.getResponseHeaders().set("Content-Type", "application/json; charset=utf-8");
|
||||
byte[] bytes = json.getBytes(StandardCharsets.UTF_8);
|
||||
@ -125,6 +163,7 @@ public class HttpServerApp {
|
||||
}
|
||||
}
|
||||
|
||||
// ======= Chyba =======
|
||||
private static void sendError(HttpExchange exchange, int code, String message) throws IOException {
|
||||
exchange.getResponseHeaders().set("Content-Type", "text/plain; charset=utf-8");
|
||||
byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
|
||||
@ -134,6 +173,7 @@ public class HttpServerApp {
|
||||
}
|
||||
}
|
||||
|
||||
// ======= Načtení resource =======
|
||||
private static String readResource(String resourcePath) {
|
||||
try (InputStream is = HttpServerApp.class.getResourceAsStream(resourcePath)) {
|
||||
if (is == null) return null;
|
||||
|
||||
@ -66,6 +66,9 @@
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const apiKey = urlParams.get('apiKey') || '';
|
||||
|
||||
const API = '/transmissions';
|
||||
let all = [];
|
||||
let filtered = [];
|
||||
@ -82,18 +85,20 @@
|
||||
const refreshBtn = document.getElementById('refreshBtn');
|
||||
|
||||
function fetchAll() {
|
||||
fetch(API).then(r => r.json()).then(data => {
|
||||
fetch(API + '?apiKey=' + encodeURIComponent(apiKey))
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
all = data || [];
|
||||
populateFilters();
|
||||
applyFilters();
|
||||
}).catch(err => {
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('Chyba při načítání dat: ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
function populateFilters() {
|
||||
// Sport filter
|
||||
const sports = Array.from(new Set(all.map(x => x.sport).filter(Boolean))).sort();
|
||||
sportFilter.innerHTML = '<option value="">— Všechny sporty —</option>';
|
||||
sports.forEach(s => {
|
||||
@ -102,7 +107,6 @@
|
||||
|
||||
populateLeagueFilter();
|
||||
|
||||
// Date filter
|
||||
const dates = Array.from(new Set(all.map(x => x.date).filter(Boolean))).sort();
|
||||
dateFilter.innerHTML = '<option value="">— Všechna data —</option>';
|
||||
dates.forEach(d => {
|
||||
@ -122,7 +126,6 @@
|
||||
|
||||
function normalizeText(s) {
|
||||
if (!s) return '';
|
||||
// odstranění diakritiky a převod na malá písmena
|
||||
return s.normalize('NFD').replace(/\p{Diacritic}/gu, '').toLowerCase();
|
||||
}
|
||||
|
||||
@ -137,8 +140,6 @@
|
||||
if (league && t.league !== league) return false;
|
||||
if (date && t.date !== date) return false;
|
||||
if (!q) return true;
|
||||
|
||||
// spojíme text a normalizujeme
|
||||
const text = normalizeText((t.title||'') + ' ' + (t.sport||'') + ' ' + (t.league||''));
|
||||
return text.indexOf(q) !== -1;
|
||||
});
|
||||
@ -221,33 +222,33 @@
|
||||
}
|
||||
|
||||
let debounceTimer;
|
||||
searchBox.addEventListener('input', () => {
|
||||
clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(applyFilters, 250);
|
||||
});
|
||||
searchBox.addEventListener('input', () => { clearTimeout(debounceTimer); debounceTimer = setTimeout(applyFilters, 250); });
|
||||
sportFilter.addEventListener('change', () => { populateLeagueFilter(); applyFilters(); });
|
||||
leagueFilter.addEventListener('change', applyFilters);
|
||||
dateFilter.addEventListener('change', applyFilters);
|
||||
sortOrder.addEventListener('change', () => { sortFiltered(); renderTable(); });
|
||||
|
||||
refreshBtn.addEventListener('click', async () => {
|
||||
try {
|
||||
function refreshData() {
|
||||
refreshBtn.disabled = true;
|
||||
refreshBtn.textContent = "Načítám...";
|
||||
const resp = await fetch('/refresh');
|
||||
await resp.json();
|
||||
fetch('/refresh?apiKey=' + encodeURIComponent(apiKey))
|
||||
.then(r => r.json())
|
||||
.then(() => {
|
||||
setTimeout(() => {
|
||||
fetchAll();
|
||||
refreshBtn.disabled = false;
|
||||
refreshBtn.textContent = "Refresh";
|
||||
}, 7000);
|
||||
} catch (err) {
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
alert('Chyba při obnově dat: ' + err);
|
||||
refreshBtn.disabled = false;
|
||||
refreshBtn.textContent = "Refresh";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
refreshBtn.addEventListener('click', refreshData);
|
||||
|
||||
fetchAll();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user