Base api works

This commit is contained in:
Przemek Dragańczuk 2020-02-13 23:52:33 +01:00
commit d80024c494
21 changed files with 571 additions and 0 deletions

32
.classpath Normal file
View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

6
.gitattributes vendored Normal file
View File

@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build

23
.project Normal file
View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>url</name>
<comment>Project url created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=
eclipse.preferences.version=1

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

20
build.gradle Normal file
View File

@ -0,0 +1,20 @@
plugins {
// Apply the java plugin to add support for Java
id 'java'
// Apply the application plugin to add support for building a CLI application.
id 'application'
}
repositories {
jcenter()
}
dependencies {
compile "com.sparkjava:spark-core:2.8.0"
}
application {
mainClassName = 'tk.draganczuk.url.App'
}

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

183
gradlew vendored Executable file

File diff suppressed because it is too large Load Diff

100
gradlew.bat vendored Normal file

File diff suppressed because it is too large Load Diff

10
settings.gradle Normal file
View File

@ -0,0 +1,10 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/6.1.1/userguide/multi_project_builds.html
*/
rootProject.name = 'url'

View File

@ -0,0 +1,12 @@
package tk.draganczuk.url;
import static spark.Spark.*;
public class App {
public static void main(String[] args) {
get("/all", Routes::getAll);
post("/new", Routes::addUrl);
get("/:shortUrl", Routes::goToLongUrl);
}
}

View File

@ -0,0 +1,36 @@
package tk.draganczuk.url;
/**
* Pair
*/
public class Pair<T, U> {
private T left;
private U right;
public Pair(T left, U right) {
this.left = left;
this.right = right;
}
public static <T, U> Pair<T, U> of(T left, U right){
return new Pair<T,U>(left, right);
}
public T getLeft() {
return left;
}
public void setLeft(T left) {
this.left = left;
}
public U getRight() {
return right;
}
public void setRight(U right) {
this.right = right;
}
}

View File

@ -0,0 +1,54 @@
package tk.draganczuk.url;
import java.io.IOException;
import java.util.List;
import java.util.UUID;
import org.eclipse.jetty.util.log.Log;
import spark.Request;
import spark.Response;
public class Routes {
private static UrlFile urlFile;
static{
try {
urlFile = new UrlFile();
} catch (IOException e) {
e.printStackTrace();
}
}
public static List<String> getAll(Request req, Response res) throws IOException{
return urlFile.getAll();
}
public static String addUrl(Request req, Response res) {
String longUrl = req.queryParams("long");
String shortUrl = req.queryParams("short");
if (shortUrl == null) {
shortUrl = Utils.randomString();
}
return urlFile.addUrl(longUrl, shortUrl);
}
public static String goToLongUrl(Request req, Response res){
String shortUrl = req.params("shortUrl");
var longUrlOpt = urlFile
.findForShortUrl(shortUrl);
if(longUrlOpt.isEmpty()){
res.status(404);
return "";
}
res.redirect(longUrlOpt.get());
return "";
}
}

View File

@ -0,0 +1,60 @@
package tk.draganczuk.url;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.List;
import java.util.Optional;
import org.eclipse.jetty.util.log.Log;
public class UrlFile {
private File file;
public UrlFile() throws IOException{
String path = System.getProperty("file.location", "./urls.csv");
this.file = new File(path);
if(! file.exists()){
file.createNewFile();
}
}
public List<String> getAll() throws IOException{
return Files.readAllLines(file.toPath());
}
public String addUrl(String longURL, String shortUrl){
String entry = String.format("%s,%s",shortUrl,longURL);
try {
var lineOpt = Files.lines(file.toPath())
.filter(line -> line.equals(entry))
.findAny();
if(lineOpt.isEmpty()){
Files.writeString(file.toPath(), entry + System.lineSeparator(), StandardOpenOption.APPEND);
}
} catch (IOException e) {
e.printStackTrace();
}
return entry;
}
public Optional<String> findForShortUrl(String shortUrl){
try {
return Files.lines(file.toPath())
.map(this::splitLine)
.filter(pair -> pair.getLeft().equals(shortUrl))
.map(Pair::getRight)
.findAny();
} catch (IOException e) {
return Optional.empty();
}
}
public Pair<String, String> splitLine(String line){
var split = line.split(",");
return new Pair<>(split[0], split[1]);
}
}

View File

@ -0,0 +1,23 @@
package tk.draganczuk.url;
import java.util.Random;
public class Utils {
private static final Random random = new Random(System.currentTimeMillis());
public static String randomString() {
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
int targetStringLength = 10;
String generatedString = random.ints(leftLimit, rightLimit + 1)
.filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
.limit(targetStringLength)
.collect(StringBuilder::new,
StringBuilder::appendCodePoint,
StringBuilder::append)
.toString();
return generatedString;
}
}