diff --git a/mifi_dev.iml b/mifi_dev.iml
index 3e2ed1c..0c880fb 100644
--- a/mifi_dev.iml
+++ b/mifi_dev.iml
@@ -15,5 +15,6 @@
+
\ No newline at end of file
diff --git a/src/sls/DB_handler.java b/src/sls/DB_handler.java
new file mode 100644
index 0000000..664d601
--- /dev/null
+++ b/src/sls/DB_handler.java
@@ -0,0 +1,53 @@
+package sls;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+public class DB_handler {
+
+ private static final String DATABASE_PATH = "jdbc:sqlite:short_links.db";
+
+ public static Connection connect() {
+ Connection cursor;
+ try {
+ cursor = DriverManager.getConnection(DATABASE_PATH);
+ } catch (SQLException error) {
+ throw new RuntimeException(error);
+ }
+ createTables(cursor);
+ return cursor;
+ }
+
+ private static void createTables(Connection cursor) {
+ String sql_links = """
+ CREATE TABLE links (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ uuid TEXT NOT NULL,
+ link_original TEXT NOT NULL,
+ link_short TEXT NOT NULL,
+ following_limit INTEGER NOT NULL,
+ time_created INTEGER NOT NULL,
+ FOREIGN KEY (uuid) REFERENCES users (uuid)
+ );
+ """;
+
+ String sql_users = """
+ CREATE TABLE users (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ uuid TEXT NOT NULL DEFAULT (lower(hex(randomblob(16)))),
+ name TEXT NOT NULL UNIQUE
+ );
+ """;
+
+ try (Statement stmt = cursor.createStatement()) {
+ stmt.execute(sql_users);
+ stmt.execute(sql_links);
+ } catch (SQLException e) {
+ System.out.println(e.getMessage());
+ }
+
+
+ }
+
+}
diff --git a/src/sls/Main.java b/src/sls/Main.java
new file mode 100644
index 0000000..2bb479c
--- /dev/null
+++ b/src/sls/Main.java
@@ -0,0 +1,23 @@
+package sls;
+
+import com.sun.net.httpserver.HttpServer;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.sql.Connection;
+
+public class Main {
+ public static void main(String[] args) throws IOException {
+
+ Connection cursor = DB_handler.connect();
+
+ HttpServer server = HttpServer.create(new InetSocketAddress(10070), 0);
+
+ server.createContext("/reg_short_link/", new reg_handler.GetShortLink(cursor));
+ server.createContext("/goto/", new follower.GoToResource(cursor));
+ server.createContext("/links_list/", new get_url_list.GetUrlList(cursor));
+ server.createContext("/delete_link/", new delete_link.DeleteLink(cursor));
+
+ server.setExecutor(null);
+ server.start();
+ }
+}
diff --git a/src/sls/README.md b/src/sls/README.md
new file mode 100644
index 0000000..fc08244
--- /dev/null
+++ b/src/sls/README.md
@@ -0,0 +1,21 @@
+Сервис работает, например, через curl или другой http клиент. Данные хранятся в СУБД sqlite.
+Время жизни ссылки 24 часа. Удаляется при попытке редиректа методом goto с условием, что время создания истекло относительно текущего.
+
+У сервиса есть 4 метода для взаимодействия:
+1) reg_short_link - регистрация пользователя и получения uuid или напоминания.
+ Пример использования: curl http://127.0.0.1:10070/reg_short_link/artem/5?https://music.yandex.ru/home
+ Пример ответа: "Пользователь с таким именем уже существует. uuid: **ac4afb9df4297ec9bbae3d6c10d97533**. Используйте uuid вместе с укороченной ссылкой **VDvxIBIN** в методе goto (http://127.0.0.1:10070/goto/VDvxIBIN?ac4afb9df4297ec9bbae3d6c10d97533) для редиректа на нужны ресурс: https://music.yandex.ru/home"
+
+2) goto - метод редиректа на оригинальный линк.
+ Пример использования: curl http://127.0.0.1:10070/goto/VDvxIBIN?ac4afb9df4297ec9bbae3d6c10d97533
+ Пример ответа: "Переход на оригинальную ссылку https://music.yandex.ru/home успешно выполнен. Осталось 4 переходов"
+
+3) links_list - позволяет получить актуальный лист созданных пользователем ссылок, их временем создания, количеством оставшихся лимитов редиректов.
+ Пример использования: curl http://127.0.0.1:10070/links_list/ac4afb9df4297ec9bbae3d6c10d97533
+ Пример ответа:
+ Short Link: ZyK5emzk, Original Link: https://stackoverflow.com, Created time: 1733437935, Limit: 0
+ Short Link: VDvxIBIN, Original Link: https://music.yandex.ru/home, Created time: 1733518356, Limit: 5
+
+4) delete_link - позволяет удалить любую ссылку пользователя, например, когда лимит редиректов исчерпан, а время истечения наступит еще не скоро.
+ Пример использования: http://127.0.0.1:10070/delete_link/VDvxIBIN
+ Пример ответа: "Короткая ссылка VDvxIBIN была удалена."
\ No newline at end of file
diff --git a/src/sls/delete_link.java b/src/sls/delete_link.java
new file mode 100644
index 0000000..4a984a1
--- /dev/null
+++ b/src/sls/delete_link.java
@@ -0,0 +1,53 @@
+package sls;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+
+
+public class delete_link {
+ static class DeleteLink implements HttpHandler {
+ private final Connection cursor;
+
+ public DeleteLink(Connection cursor) {
+ this.cursor = cursor;
+ }
+
+ public void handle(HttpExchange exchange) throws IOException {
+ String received_link_short = exchange.getRequestURI().getPath().split("/")[2];
+ String response;
+
+ try {
+ boolean check_delete = deleteLink(received_link_short);
+ if (check_delete) {
+ response = String.format("Короткая ссылка %s была удалена.", received_link_short);
+ }
+ else {
+ response = String.format("Короткая ссылка не была найдена, удалять нечего.", received_link_short);
+ }
+ } catch (SQLException e) {
+ response = String.format("Удаление ссылки %s завершилось неудачно.", received_link_short);
+ }
+
+ exchange.sendResponseHeaders(200, response.getBytes().length);
+ OutputStream os = exchange.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ }
+
+ private boolean deleteLink(String link_short) throws SQLException {
+ String deleteSQL = "DELETE FROM links WHERE link_short = ?";
+
+ try (PreparedStatement pstmt = cursor.prepareStatement(deleteSQL)) {
+ pstmt.setString(1, link_short);
+ int rows = pstmt.executeUpdate();
+ return rows > 0;
+ }
+ }
+ }
+}
diff --git a/src/sls/follower.java b/src/sls/follower.java
new file mode 100644
index 0000000..c12df6d
--- /dev/null
+++ b/src/sls/follower.java
@@ -0,0 +1,109 @@
+package sls;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+import java.awt.*;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.Instant;
+import java.util.Objects;
+
+public class follower {
+ static class GoToResource implements HttpHandler {
+ private final Connection cursor;
+
+ public GoToResource(Connection cursor) {
+ this.cursor = cursor;
+ }
+
+ public void handle(HttpExchange exchange) throws IOException {
+ Instant now = Instant.now();
+ long current_ts = now.getEpochSecond();
+
+ String received_short_url = exchange.getRequestURI().getPath().split("/")[2];
+ String uuid_query = exchange.getRequestURI().getQuery();
+ String response;
+
+ try {
+ Object[] result = getShortLink(received_short_url);
+ if (result != null) {
+ String link_short = (String) result[0];
+ String link_original = (String) result[1];
+ long link_created = (long) result[2];
+ int following_limit = (int) result[3];
+ String uuid = (String) result[4];
+
+ if (Objects.equals(uuid_query, uuid)) {
+ if (current_ts - link_created >= 86400) {
+ deleteExpiredLink(link_short);
+ response = String.format("Извините, но ваша ссылка %s -> %s просрочилась и была удалена (срок хранения 24 часа). Создайте новую методом reg_short_link", link_short, link_original);
+ } else if (following_limit < 1) {
+ response = String.format("Извините, но ваша ссылка %s -> %s исчерпала лимит переходов. Она будет удалена в течение 24 часов. Удалите текущую ссылку методом delete_link и создайте новую методом reg_short_link\nПосмотреть текущий список ссылок можно методом links_list", link_short, link_original);
+ } else {
+ updateCountFollowing(link_short, following_limit - 1);
+ Desktop.getDesktop().browse(new URI(link_original));
+ response = String.format("Переход на оригинальную ссылку %s успешно выполнен. Осталось %d переходов", link_original, following_limit - 1);
+ }
+ } else {
+ response = "Извините, но пользователя с таким uuid нет. Зарегистрируйтесь методом reg_short_link";
+ }
+ } else {
+ response = "Извините, но такой ссылки нет. Сделайте новую методом reg_short_link";
+ }
+ } catch (SQLException | URISyntaxException e) {
+ response = "Произошла ошибка обработки запроса. Попробуйте позже.";
+ }
+
+ exchange.sendResponseHeaders(200, response.getBytes().length);
+ try (OutputStream os = exchange.getResponseBody()) {
+ os.write(response.getBytes());
+ }
+ }
+
+ private Object[] getShortLink(String link_short) throws SQLException {
+ String query = "SELECT link_short, link_original, time_created, following_limit, uuid FROM links WHERE link_short = ?";
+ try (PreparedStatement pstmt = cursor.prepareStatement(query)) {
+ pstmt.setString(1, link_short);
+ try (ResultSet rs = pstmt.executeQuery()) {
+ if (rs.next()) {
+ return new Object[]{rs.getString("link_short"),
+ rs.getString("link_original"),
+ rs.getLong("time_created"),
+ rs.getInt("following_limit"),
+ rs.getString("uuid")};
+ }
+ else {
+ return null;
+ }
+ }
+ }
+ }
+
+ private void deleteExpiredLink(String link_short) throws SQLException {
+ String deleteSQL = "DELETE FROM links WHERE link_short = ?";
+
+ try (PreparedStatement pstmt = cursor.prepareStatement(deleteSQL)) {
+ pstmt.setString(1, link_short);
+ pstmt.executeUpdate();
+ }
+ }
+
+ private void updateCountFollowing(String link_short, int following_limit) throws SQLException {
+ String updateSQL = "UPDATE links SET following_limit = ? WHERE link_short = ?";
+
+ try (PreparedStatement pstmt = cursor.prepareStatement(updateSQL)) {
+ pstmt.setInt(1, following_limit);
+ pstmt.setString(2, link_short);
+ pstmt.executeUpdate();
+ }
+ }
+
+ }
+}
diff --git a/src/sls/get_url_list.java b/src/sls/get_url_list.java
new file mode 100644
index 0000000..1957ab4
--- /dev/null
+++ b/src/sls/get_url_list.java
@@ -0,0 +1,84 @@
+package sls;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class get_url_list {
+ static class GetUrlList implements HttpHandler {
+ private final Connection cursor;
+
+ public GetUrlList(Connection cursor) {
+ this.cursor = cursor;
+ }
+
+ public void handle(HttpExchange exchange) throws IOException {
+ String received_uuid = exchange.getRequestURI().getPath().split("/")[2];
+
+ List