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
24 changes: 14 additions & 10 deletions src/main/java/urlshortener/database/Database.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
package urlshortener.database;

import lombok.Setter;
import urlshortener.config.AppConfig;

import java.sql.*;

public class Database {
@Setter
private static String jdbcUrl = "jdbc:h2:./shorten-db"; // default
private static String jdbcUrl = AppConfig.DB_URL; // default

public static void initSchema() {
try (Connection conn = getConnection(); Statement stmt = conn.createStatement()) {
stmt.executeUpdate("CREATE TABLE IF NOT EXISTS urls (" +
stmt.executeUpdate("CREATE TABLE if not exists urls (" +
"id IDENTITY PRIMARY KEY, " +
"short_code VARCHAR(20) UNIQUE, " +
"username VARCHAR(255),"+
"short_code VARCHAR(50) UNIQUE, " +
"long_url TEXT NOT NULL)");
} catch (SQLException e) {
e.printStackTrace();
Expand All @@ -23,19 +25,21 @@ public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(jdbcUrl, "sa", "");
}

public static void insertUrl(String shortCode, String longUrl) throws SQLException {
String sql = "INSERT INTO urls (short_code, long_url) VALUES (?, ?)";
public static void insertUrl(String username, String shortCode, String longUrl) throws SQLException {
String sql = "INSERT INTO urls (username, short_code, long_url) VALUES (?, ?, ?)";
try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, shortCode);
stmt.setString(2, longUrl);
stmt.setString(1, username);
stmt.setString(2, shortCode);
stmt.setString(3, longUrl);
stmt.executeUpdate();
}
}

public static String getLongUrl(String shortCode) throws SQLException {
String sql = "SELECT long_url FROM urls WHERE short_code = ?";
public static String getLongUrl(String username, String shortCode) throws SQLException {
String sql = "SELECT long_url FROM urls WHERE username = ? AND short_code = ?";
try (Connection conn = getConnection(); PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, shortCode);
stmt.setString(1, username);
stmt.setString(2, shortCode);
ResultSet rs = stmt.executeQuery();
return rs.next() ? rs.getString("long_url") : null;
}
Expand Down
28 changes: 0 additions & 28 deletions src/main/java/urlshortener/service/RedirectHandler.java

This file was deleted.

28 changes: 20 additions & 8 deletions src/main/java/urlshortener/service/UrlHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import urlshortener.config.AppConfig;
import urlshortener.database.Database;
import urlshortener.utils.HashGenerator;
import urlshortener.utils.HelperMethods;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.SQLException;
import java.util.Map;
import java.util.stream.Collectors;

public class UrlHandler implements HttpHandler {
Expand All @@ -20,18 +22,28 @@ public void handle(HttpExchange exchange) throws IOException {
return;
}

String body = new BufferedReader(new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8))
String requestBody = new BufferedReader(new InputStreamReader(exchange.getRequestBody(), StandardCharsets.UTF_8))
.lines().collect(Collectors.joining());

String longUrl = body.replace("url=", "").trim();
if (longUrl.isEmpty()) {
Map<String, String> formMap = HelperMethods.parseFormData(requestBody);

String longUrl = formMap.get("longUrl");
String username = formMap.get("username");
boolean isGuest = (username == null || username.isEmpty());

String prefix = isGuest ? "" : (username.length() > 8 ? username.substring(0, 8) : username);
String shortCode = (isGuest ? "" : prefix + "_") + HashGenerator.generateShortCode();


if (longUrl == null || longUrl.isEmpty()) {
exchange.sendResponseHeaders(400, -1);
return;
}

String shortCode = HashGenerator.generateShortCode();

try {
Database.insertUrl(shortCode, longUrl);
Database.initSchema();
Database.insertUrl(username, longUrl, shortCode);
} catch (SQLException e) {
exchange.sendResponseHeaders(500, -1);
return;
Expand All @@ -40,8 +52,8 @@ public void handle(HttpExchange exchange) throws IOException {
String shortUrl = AppConfig.BASE_URL + shortCode;
byte[] response = shortUrl.getBytes(StandardCharsets.UTF_8);
exchange.sendResponseHeaders(200, response.length);
OutputStream os = exchange.getResponseBody();
os.write(response);
os.close();
try (OutputStream os = exchange.getResponseBody(); os) {
os.write(response);
}
}
}
22 changes: 22 additions & 0 deletions src/main/java/urlshortener/utils/HelperMethods.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
import com.sun.net.httpserver.HttpExchange;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class HelperMethods {
public static String readRequestBody(HttpExchange exchange) throws IOException {
Expand All @@ -18,4 +22,22 @@ public static void respond(HttpExchange exchange, int statusCode, String respons
os.write(bytes);
os.close();
}

public static Map<String, String> parseFormData(String body) {
Map<String, String> data = new HashMap<>();

if (body == null || body.trim().isEmpty()) return data;

String[] pairs = body.split("&");
for (String pair : pairs) {
String[] kv = pair.split("=", 2);
if (kv.length == 2) {
String key = URLDecoder.decode(kv[0], StandardCharsets.UTF_8);
String value = URLDecoder.decode(kv[1], StandardCharsets.UTF_8);
data.put(key, value);
}
}

return data;
}
}
9 changes: 5 additions & 4 deletions src/test/java/urlshortener/service/UrlHandlerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ public class UrlHandlerTest {
static void setupDatabase() {
// Use in-memory DB for isolated testing
Database.setJdbcUrl("jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1");
Database.initSchema(); // Create `urls` table
Database.initSchema(); // Should now create the `username` column too
}

@Test
void testInsertAndRetrieveUrl() throws Exception {
void testInsertAndRetrieveUrlWithUsername() throws Exception {
String username = "testuser";
String shortCode = "abc123";
String longUrl = "https://example.com";

Database.insertUrl(shortCode, longUrl);
String fetched = Database.getLongUrl(shortCode);
Database.insertUrl(username, shortCode, longUrl);
String fetched = Database.getLongUrl(username, shortCode);

assertEquals(longUrl, fetched);
}
Expand Down