Skip to content

Commit

Permalink
Feature - Added support for HTTP DELETE method (#12)
Browse files Browse the repository at this point in the history
  • Loading branch information
g1izzyw authored and davidgamez committed Jan 5, 2019
1 parent 42b90f6 commit 095cd66
Show file tree
Hide file tree
Showing 24 changed files with 592 additions and 226 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,6 @@ nbdist/
.DS_Store
**.swap
~

# Eclipse #
/bin/
184 changes: 149 additions & 35 deletions docs/release/api-guide.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<junit.version>4.12</junit.version>
<start-class>parrot.rest.ParrotRestApplication</start-class>
<docker.image.name>parrot-rest</docker.image.name>
<asciidoctor-plugin.version>1.5.3</asciidoctor-plugin.version>
<asciidoctor-plugin.version>1.5.6</asciidoctor-plugin.version>
<snippetsDirectory>${project.build.directory}/snippets</snippetsDirectory>
<asciidoc.source.dir>src/main/asciidocs</asciidoc.source.dir>
<asciidoc.output.dir>docs/release</asciidoc.output.dir>
Expand Down
48 changes: 47 additions & 1 deletion src/main/asciidocs/api-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Parrot-REST application is a simple application that exposes to RESTs endpoints.

| `POST`
| Used to create a new resource

|`DELETE`
| Used to delete a resource
|===

Parrot-REST tries to adhere as closely as possible to standard HTTP and REST conventions in its
Expand Down Expand Up @@ -116,4 +119,47 @@ include::{snippets}/talk-example/http-request.adoc[]

=== CURL request

include::{snippets}/talk-example/curl-request.adoc[]
include::{snippets}/talk-example/curl-request.adoc[]

[[resources-forget]]
== Forget

The forget provides the ability to remove existing responses which were posted by the listen resource.

[[resources-forget-access]]
== Accessing the forget

A `DLETE` request is used to access the forget

[[forget-existing-resource]]
=== Forget an existing resource

==== Example response

include::{snippets}/forget-example/http-response.adoc[]

==== Example request

include::{snippets}/forget-example/http-request.adoc[]

==== CURL request

include::{snippets}/forget-example/curl-request.adoc[]

[[forget-non-existing-resource]]
=== Forget a non-existing resource

==== Example response

include::{snippets}/forget-non-existing-resource-example/http-response.adoc[]

==== Example request

include::{snippets}/forget-non-existing-resource-example/http-request.adoc[]

==== CURL request

include::{snippets}/forget-non-existing-resource-example/curl-request.adoc[]



44 changes: 44 additions & 0 deletions src/main/java/parrot/rest/common/PhraseUtility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package parrot.rest.common;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerMapping;

/**
*
* @author Isuru Weerasooriya
*
*/
public class PhraseUtility {

private PhraseUtility() {
}

public static String getFullUrl(HttpServletRequest request, Pattern urlPattern) {
StringBuilder builder = new StringBuilder();
String fullUrl = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String url = getAppContextUrl(fullUrl, urlPattern);
if (url == null) {
return null;
}
builder.append(url);
if (StringUtils.isNotEmpty(request.getQueryString())) {
builder.append("?");
builder.append(request.getQueryString());
}
return builder.toString();
}

public static String getAppContextUrl(String fullUrl, Pattern urlPattern) {
Matcher matcher = urlPattern.matcher(fullUrl);
if (matcher.matches() && matcher.groupCount() > 0) {
return matcher.group(1);
}
return null;
}

}
50 changes: 50 additions & 0 deletions src/main/java/parrot/rest/controller/ForgetController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package parrot.rest.controller;

import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;

import parrot.rest.common.PhraseUtility;
import parrot.rest.exception.UrlNotFoundException;
import parrot.rest.service.PhraseService;

/**
*
* @author Isuru Weerasooriya
*
*/
@Controller(ForgetController.PATH)
public class ForgetController {

public static final String PATH = "forget";

private static final Logger logger = LoggerFactory.getLogger(ForgetController.class);
private static final Pattern URL_PATTERN = Pattern.compile("\\/{0,1}forget\\/(.*)");

@Autowired
private PhraseService phraseService;

@DeleteMapping("forget/**")
public ResponseEntity<String> forget(HttpServletRequest request) {
ResponseEntity<String> result = null;
String url = PhraseUtility.getFullUrl(request, URL_PATTERN);

logger.debug("Forgetting URL: {}", url);
try {
phraseService.remove(url);
result = new ResponseEntity<>("OK", HttpStatus.OK);
} catch (UrlNotFoundException e) {
result = new ResponseEntity<>("NO_CONTENT", HttpStatus.NO_CONTENT);
}
return result;
}

}
4 changes: 0 additions & 4 deletions src/main/java/parrot/rest/controller/HealthController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/**
*
*/
package parrot.rest.controller;

import org.springframework.http.HttpStatus;
Expand All @@ -16,7 +13,6 @@
@Controller("health")
public class HealthController {


@GetMapping
public ResponseEntity<String> listen() {
return new ResponseEntity<>("I'm a healthy parrot, do you have sunflower seeds for me?", HttpStatus.OK);
Expand Down
3 changes: 0 additions & 3 deletions src/main/java/parrot/rest/controller/ListenController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/**
*
*/
package parrot.rest.controller;

import org.slf4j.Logger;
Expand Down
36 changes: 6 additions & 30 deletions src/main/java/parrot/rest/controller/TalkController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package parrot.rest.controller;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
Expand All @@ -14,8 +13,8 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.HandlerMapping;

import parrot.rest.common.PhraseUtility;
import parrot.rest.exception.UrlNotFoundException;
import parrot.rest.service.PhraseService;

Expand All @@ -28,45 +27,22 @@
public class TalkController {

public static final String PATH = "talk";

private static final Logger logger = LoggerFactory.getLogger(TalkController.class);
private static final Pattern URL_PATTERN = Pattern.compile("\\/{0,1}talk\\/(.*)");

@Autowired
private PhraseService phraseService;

@GetMapping("talk/**")
@ResponseBody
public ResponseEntity<String> talk(HttpServletRequest request) throws UrlNotFoundException {
String url = getFullUrl(request);
String url = PhraseUtility.getFullUrl(request, URL_PATTERN);

logger.debug("Talking URL: {}", url);
if (StringUtils.isEmpty(url)) {
throw new UrlNotFoundException(url);
}
return new ResponseEntity<>(phraseService.getResponse(url), HttpStatus.OK);
}

private String getFullUrl(HttpServletRequest request) {
StringBuilder builder = new StringBuilder();
String fullUrl = (String)request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
String url = getAppContextUrl(fullUrl);
if (url == null) {
return null;
}
builder.append(url);
if (StringUtils.isNotEmpty(request.getQueryString())) {
builder.append("?");
builder.append(request.getQueryString());
}
return builder.toString();
}

private String getAppContextUrl(String fullUrl) {
Matcher matcher = URL_PATTERN.matcher(fullUrl);
if (matcher.matches() && matcher.groupCount() > 0) {
return matcher.group(1);
}
return null;
}
}
4 changes: 3 additions & 1 deletion src/main/java/parrot/rest/repository/PhraseRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import parrot.rest.common.Phrase;

/**
* @author gamezd
* @author David Gamez, Isuru Weerasooriya
*
*/
public interface PhraseRepository {
Expand All @@ -15,4 +15,6 @@ public interface PhraseRepository {

Phrase load(String fullUrl);

Phrase delete(String fullUrl);

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import parrot.rest.common.Phrase;

/**
* @author David Gamez
*
*/
public abstract class PhraseRepositoryBase implements PhraseRepository {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import parrot.rest.common.Phrase;

/**
* @author David Gamez, Isuru Weerasooriya
*
*/
@Component
Expand All @@ -30,4 +31,9 @@ public Phrase load(String fullUrl) {
return map.get(getIdFromUrl(fullUrl));
}

@Override
public Phrase delete(String fullUrl) {
return map.remove(getIdFromUrl(fullUrl));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import parrot.rest.common.Phrase;

/**
* @author David Gamez
* @author David Gamez, Isuru Weerasooriya
*
*/
@Component
Expand All @@ -37,5 +37,13 @@ public Phrase load(String url) {
return (Phrase) getHashOps().get(Phrase.class.getName(), getIdFromUrl(url));
}


@Override
public Phrase delete(String url) {
Phrase result = load(url);
if (result != null) {
getHashOps().delete(Phrase.class.getName(), getIdFromUrl(url));
}
return result;
}

}
2 changes: 2 additions & 0 deletions src/main/java/parrot/rest/service/PhraseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ public interface PhraseService {
Phrase save(Phrase phrase);

String getResponse(String url) throws UrlNotFoundException;

Phrase remove(String url) throws UrlNotFoundException;
}
14 changes: 11 additions & 3 deletions src/main/java/parrot/rest/service/PhraseServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/**
*
*/
package parrot.rest.service;

import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -28,6 +25,7 @@ public Phrase save(Phrase phrase) {
return phraseRepository.save(phrase);
}


/* (non-Javadoc)
* @see parrot.rest.repository.PhraseService#get(java.lang.String, java.lang.String)
*/
Expand All @@ -40,4 +38,14 @@ public String getResponse(String url) throws UrlNotFoundException {

return result.getResponse();
}


@Override
public Phrase remove(String url) throws UrlNotFoundException {
Phrase result = phraseRepository.delete(url);
if (result == null) {
throw new UrlNotFoundException(url);
}
return result;
}
}
7 changes: 6 additions & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ server.contextPath=/api
persistent.type=MAP

#REDIS
spring.redis.url=http://localhost:6379
spring.redis.url=http://localhost:6379

---
# local profile
spring.profiles=local
server.port=10010
Loading

0 comments on commit 095cd66

Please sign in to comment.