Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .idea/libraries/google_api_client_gson.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions java-kanban.iml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="junit.jupiter" level="project" />
<orderEntry type="library" name="google.api.client.gson" level="project" />
</component>
</module>
10 changes: 5 additions & 5 deletions resources/data.csv
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
id,type,name,status,description,epic, startTime, duration
5,TASK,Name,NEW,Desc,,2025-07-22T21:18:17.670284500,30
9,TASK,Непересекающаяся,NEW,Описание,,2025-07-24T01:18:17.673142600,60
6,EPIC,Отпуск,NEW,Организовать отпуск,,2025-07-23T20:18:17.673142600,
7,SUBTASK,Путёвка,NEW,Выбрать путёвку,6,2025-07-23T20:18:17.673142600,120
8,SUBTASK,Билеты,NEW,Купить билеты,6,2025-07-23T23:18:17.673142600,60
5,TASK,Name,NEW,Desc,,2025-07-31T17:44:00.858235600,30
9,TASK,Непересекающаяся,NEW,Описание,,2025-08-01T21:44:00.861707600,60
6,EPIC,Отпуск,NEW,Организовать отпуск,,2025-08-01T16:44:00.861707600,
7,SUBTASK,Путёвка,NEW,Выбрать путёвку,6,2025-08-01T16:44:00.861707600,120
8,SUBTASK,Билеты,NEW,Купить билеты,6,2025-08-01T19:44:00.861707600,60
50 changes: 50 additions & 0 deletions src/manager/http/BaseHttpHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package manager.http;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.LocalDateTime;

public abstract class BaseHttpHandler implements HttpHandler {
protected static final Gson gson = new GsonBuilder()
.registerTypeAdapter(LocalDateTime.class, new TimeAdapters.LocalDateTimeAdapter())
.registerTypeAdapter(Duration.class, new TimeAdapters.DurationAdapter())
.create();

protected String readRequest(HttpExchange exchange) throws IOException {
try (InputStream input = exchange.getRequestBody()) {
return new String(input.readAllBytes(), StandardCharsets.UTF_8);
}
}

protected void sendResponse(HttpExchange exchange, String response, int statusCode) throws IOException {
exchange.getResponseHeaders().set("Content-Type", "application/json;charset=utf-8");
byte[] resp = response.getBytes(StandardCharsets.UTF_8);
exchange.sendResponseHeaders(statusCode, resp.length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(resp);
}
}

protected void sendText(HttpExchange exchange, String text) throws IOException {
sendResponse(exchange, text, 200);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Коды ответов лучше вынести в константы

}

protected void sendNotFound(HttpExchange exchange) throws IOException {
sendResponse(exchange, "Задача не найдена", 404);
}

protected void sendHasOverlaps(HttpExchange exchange, String message) throws IOException {
sendResponse(exchange, message, 406);
}

protected void sendBadRequest(HttpExchange exchange, String message) throws IOException {
sendResponse(exchange, message, 400);
}
}
114 changes: 114 additions & 0 deletions src/manager/http/EpicsHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package manager.http;

import com.google.gson.JsonSyntaxException;
import com.sun.net.httpserver.HttpExchange;
import manager.TaskManager;
import tasks.Epic;
import java.io.IOException;

public class EpicsHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public EpicsHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
String method = exchange.getRequestMethod();
String path = exchange.getRequestURI().getPath();

switch (method) {
case "GET":
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Названия методов также можно вынести в константы

if (path.equals("/epics")) {
handleGetAllEpics(exchange);
} else if (path.startsWith("/epics/")) {
if (path.endsWith("/subtasks")) {
handleGetEpicSubtasks(exchange, path);
} else {
handleEpicWithId(exchange, path, "GET");
}
} else {
sendBadRequest(exchange, "Некорректный путь");
}
break;
case "POST":
handleCreateOrUpdateEpic(exchange);
break;
case "DELETE":
if (path.startsWith("/epics/")) {
handleEpicWithId(exchange, path, "DELETE");
} else {
sendBadRequest(exchange, "Некорректный путь");
}
break;
default:
sendBadRequest(exchange, "Неподдерживаемый метод");
}
} catch (Exception e) {
sendResponse(exchange, "Ошибка сервера", 500);
}
}

private void handleEpicWithId(HttpExchange exchange, String path, String method) throws IOException {
String idStr = path.substring("/epics/".length());
try {
int epicId = Integer.parseInt(idStr);
if (method.equals("GET")) {
Epic epic = taskManager.getEpic(epicId);
if (epic != null) {
sendText(exchange, gson.toJson(epic));
} else {
sendNotFound(exchange);
}
} else if (method.equals("DELETE")) {
Epic epic = taskManager.deleteEpic(epicId);
if (epic != null) {
sendText(exchange, "Эпик удален");
} else {
sendNotFound(exchange);
}
}
} catch (NumberFormatException e) {
sendBadRequest(exchange, "Некорректный ID эпика");
}
}

private void handleGetEpicSubtasks(HttpExchange exchange, String path) throws IOException {
String idStr = path.substring("/epics/".length(), path.length() - "/subtasks".length());
try {
int epicId = Integer.parseInt(idStr);
Epic epic = taskManager.getEpic(epicId);
if (epic != null) {
String response = gson.toJson(taskManager.getEpicSubtasks(epicId));
sendText(exchange, response);
} else {
sendNotFound(exchange);
}
} catch (NumberFormatException e) {
sendBadRequest(exchange, "Некорректный ID эпика");
}
}

private void handleGetAllEpics(HttpExchange exchange) throws IOException {
String response = gson.toJson(taskManager.getEpics());
sendText(exchange, response);
}

private void handleCreateOrUpdateEpic(HttpExchange exchange) throws IOException {
String body = readRequest(exchange);
try {
Epic epic = gson.fromJson(body, Epic.class);
if (epic.getId() == null) {
taskManager.createEpic(epic);
sendResponse(exchange, "Эпик создан", 201);
} else {
taskManager.updateEpic(epic);
sendText(exchange, "Эпик обновлен");
}
} catch (JsonSyntaxException e) {
sendBadRequest(exchange, "Неверный формат JSON");
}
}
}
31 changes: 31 additions & 0 deletions src/manager/http/HistoryHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package manager.http;

import com.sun.net.httpserver.HttpExchange;
import manager.TaskManager;
import java.io.IOException;

public class HistoryHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public HistoryHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
if ("GET".equals(exchange.getRequestMethod())) {
handleGetHistory(exchange);
} else {
sendBadRequest(exchange, "Неподдерживаемый метод");
}
} catch (Exception e) {
sendResponse(exchange, "Ошибка сервера", 500);
}
}

private void handleGetHistory(HttpExchange exchange) throws IOException {
String response = gson.toJson(taskManager.getHistory());
sendText(exchange, response);
}
}
43 changes: 43 additions & 0 deletions src/manager/http/HttpTaskServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package manager.http;

import com.sun.net.httpserver.HttpServer;
import manager.Managers;
import manager.TaskManager;
import java.io.IOException;
import java.net.InetSocketAddress;

public class HttpTaskServer {
private final HttpServer server;
private final TaskManager taskManager;
private static final int PORT = 8080;

public HttpTaskServer() throws IOException {
this.taskManager = Managers.getDefault();
this.server = HttpServer.create(new InetSocketAddress(PORT), 0);

server.createContext("/tasks", new TasksHandler(taskManager));
server.createContext("/subtasks", new SubtasksHandler(taskManager));
server.createContext("/epics", new EpicsHandler(taskManager));
server.createContext("/history", new HistoryHandler(taskManager));
server.createContext("/prioritized", new PrioritizedHandler(taskManager));
}

public TaskManager getTaskManager() {
return taskManager;
}

public void start() {
server.start();
System.out.println("Сервер запущен на порту " + PORT);
}

public void stop() {
server.stop(0);
System.out.println("Сервер остановлен");
}

public static void main(String[] args) throws IOException {
HttpTaskServer server = new HttpTaskServer();
server.start();
}
}
31 changes: 31 additions & 0 deletions src/manager/http/PrioritizedHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package manager.http;

import com.sun.net.httpserver.HttpExchange;
import manager.TaskManager;
import java.io.IOException;

public class PrioritizedHandler extends BaseHttpHandler {
private final TaskManager taskManager;

public PrioritizedHandler(TaskManager taskManager) {
this.taskManager = taskManager;
}

@Override
public void handle(HttpExchange exchange) throws IOException {
try {
if ("GET".equals(exchange.getRequestMethod())) {
handleGetPrioritized(exchange);
} else {
sendBadRequest(exchange, "Неподдерживаемый метод");
}
} catch (Exception e) {
sendResponse(exchange, "Ошибка сервера", 500);
}
}

private void handleGetPrioritized(HttpExchange exchange) throws IOException {
String response = gson.toJson(taskManager.getPrioritizedTasks());
sendText(exchange, response);
}
}
Loading