Skip to content

Commit

Permalink
add sls
Browse files Browse the repository at this point in the history
  • Loading branch information
Freezepop committed Dec 6, 2024
1 parent 44904b6 commit 494d120
Show file tree
Hide file tree
Showing 9 changed files with 494 additions and 0 deletions.
1 change: 1 addition & 0 deletions mifi_dev.iml
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="lib" level="project" />
<orderEntry type="library" name="Python 3.12 (mifi_dev) interpreter library" level="application" />
<orderEntry type="library" name="xerial.sqlite.jdbc" level="application" />
</component>
</module>
53 changes: 53 additions & 0 deletions src/sls/DB_handler.java
Original file line number Diff line number Diff line change
@@ -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());
}


}

}
23 changes: 23 additions & 0 deletions src/sls/Main.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
21 changes: 21 additions & 0 deletions src/sls/README.md
Original file line number Diff line number Diff line change
@@ -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 была удалена."
53 changes: 53 additions & 0 deletions src/sls/delete_link.java
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
}
109 changes: 109 additions & 0 deletions src/sls/follower.java
Original file line number Diff line number Diff line change
@@ -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();
}
}

}
}
84 changes: 84 additions & 0 deletions src/sls/get_url_list.java
Original file line number Diff line number Diff line change
@@ -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<Object[]> results;
try {
results = getLinksData(received_uuid);
} catch (SQLException e) {
throw new RuntimeException(e);
}

if (results != null) {
StringBuilder responseBuilder = new StringBuilder();
for (Object[] result : results) {
String link_short = (String) result[0];
String link_original = (String) result[1];
long link_created = (long) result[2];
int following_limit = (int) result[3];

responseBuilder.append(String.format(
"Short Link: %s, Original Link: %s, Created time: %d, Limit: %d\n",
link_short, link_original, link_created, following_limit
));
}

String response = responseBuilder.toString();

exchange.sendResponseHeaders(200, response.getBytes().length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(response.getBytes());
}
} else {
String response = String.format("Извините, но для UUID: %s не было найдено ни одной ссылки. Попробуйте их создать методом reg_short_link", received_uuid);
exchange.sendResponseHeaders(404, response.getBytes().length);
try (OutputStream os = exchange.getResponseBody()) {
os.write(response.getBytes());
}
}
}

private List<Object[]> getLinksData(String received_uuid) throws SQLException {
String query = "SELECT * FROM links WHERE uuid = ?";
List<Object[]> result = new ArrayList<>();
try (PreparedStatement pstmt = cursor.prepareStatement(query)) {
pstmt.setString(1, received_uuid);
try (ResultSet rs = pstmt.executeQuery()) {
while (rs.next()) {
result.add(new Object[]{
rs.getString("link_short"),
rs.getString("link_original"),
rs.getLong("time_created"),
rs.getInt("following_limit")});
}
}
}
if (!result.isEmpty()) {
return result;
}
else {
return null;
}
}
}
}
Loading

0 comments on commit 494d120

Please sign in to comment.