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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.List;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.servlet.HandlerInterceptor;

Expand All @@ -17,7 +16,7 @@
*/
public abstract class RestInterceptor implements HandlerInterceptor {

protected List<RestfulPattern> restfulPatterns = List.of();
protected RestfulPatterns restfulPatterns = RestfulPatterns.empty();

@Override
public final boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
Expand All @@ -39,8 +38,7 @@ private boolean isPreFlightRequest(final HttpServletRequest request) {
* <p> If request path is not matched with any of the restfulPatterns, it should be skipped.
*/
private boolean shouldSkip(final HttpServletRequest request) {
return this.restfulPatterns.stream()
.noneMatch(pattern -> pattern.matches(request));
return restfulPatterns.noneMatches(request);
}

/**
Expand All @@ -50,4 +48,16 @@ private boolean shouldSkip(final HttpServletRequest request) {
protected boolean doInternal(HttpServletRequest request, HttpServletResponse response, Object handler) {
return true;
}

/**
* Adds all RestfulPatterns from the given RestfulPatterns instance.
* <p>
* This method merges the provided RestfulPatterns into the existing collection.
*
* @param restfulPatterns the RestfulPatterns to be added
* @since Upcoming
*/
void addRestfulPatterns(final RestfulPatterns restfulPatterns) {
this.restfulPatterns.addAll(restfulPatterns);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.restful_spring.rest_interceptor;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
Expand Down Expand Up @@ -34,14 +33,24 @@ public RestInterceptorRegistration addRestfulPatterns(RestfulPattern... restfulP

/**
* Collection-based variant of {@link #addRestfulPatterns(RestfulPattern...)}.
* <p> Call InterceptorRegistration's addPathPatterns method with the paths of the RestfulPatterns.
*/
public RestInterceptorRegistration addRestfulPatterns(Collection<RestfulPattern> restfulPatterns) {
restInterceptor.restfulPatterns = new ArrayList<>(restfulPatterns);
registration.addPathPatterns(restfulPatterns.stream()
.map(RestfulPattern::getPath)
.toList()
);
return addRestfulPatterns(RestfulPatterns.from(restfulPatterns));
}

/**
* Adds the given RestfulPatterns to the RestInterceptor and updates path patterns.
* <p>
* This method registers the provided RestfulPatterns with the RestInterceptor and ensures that the corresponding
* paths are added to the interceptor registration.
*
* @param restfulPatterns the RestfulPatterns to be registered
* @return this RestInterceptorRegistration instance for method chaining
* @since Upcoming
*/
public RestInterceptorRegistration addRestfulPatterns(RestfulPatterns restfulPatterns) {
restInterceptor.addRestfulPatterns(restfulPatterns);
registration.addPathPatterns(restfulPatterns.getPaths());
return this;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.restful_spring.rest_interceptor;

import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
* First-class collection of RestfulPattern.
* <p>
* Encapsulates a Collection of RestfulPattern and provides apis.
*
* @author Dh3356
* @since Upcoming
*/
public final class RestfulPatterns {

private final List<RestfulPattern> values;

private RestfulPatterns(List<RestfulPattern> values) {
this.values = values;
}

/**
* Create an empty RestfulPatterns.
* <p>
* Static factory method for creating a RestfulPatterns.
*
* @return an empty RestfulPatterns
*/
static RestfulPatterns empty() {
return new RestfulPatterns(new ArrayList<>());
}

/**
* Create a RestfulPatterns from a Collection of RestfulPattern.
* <p>
* Static factory method for creating a RestfulPatterns.
*
* @param values a Collection of RestfulPattern
* @return a RestfulPatterns
*/
static RestfulPatterns from(final Collection<RestfulPattern> values) {
return new RestfulPatterns(new ArrayList<>(values));
}

/**
* Determines whether the given request does not match any RestfulPatterns.
*
* @param request the HttpServletRequest to be checked against the patterns
* @return {@code true} if no patterns match the request, otherwise {@code false}
*/
boolean noneMatches(final HttpServletRequest request) {
return values.stream()
.noneMatch(pattern -> pattern.matches(request));
}

/**
* Add all RestfulPatterns from another RestfulPatterns.
*
* @param restfulPatterns another RestfulPatterns
*/
void addAll(final RestfulPatterns restfulPatterns) {
values.addAll(List.copyOf(restfulPatterns.values));
}

/**
* Get the paths of the RestfulPatterns.
*
* @return a List of paths
*/
List<String> getPaths() {
return values.stream()
.map(RestfulPattern::getPath)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void preFlightRequest() {
@Test
void pathMatchingWithRestfulPattern() {
// Given
interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN);
interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN));

// When
request.setRequestURI(FOO);
Expand All @@ -63,7 +63,7 @@ void pathMatchingWithRestfulPattern() {
@Test
void skipWithNonMatchingPath() {
// Given
interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN);
interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN));

// When
request.setRequestURI(BAR);
Expand All @@ -77,7 +77,7 @@ void skipWithNonMatchingPath() {
@Test
void shouldSkipWhenNoPatterns() {
// Given
interceptor.restfulPatterns = List.of();
interceptor.restfulPatterns = RestfulPatterns.empty();

// When
request.setRequestURI(FOO);
Expand All @@ -90,7 +90,7 @@ void shouldSkipWhenNoPatterns() {
@Test
void doInternalCalledForMatchingRequest() {
// Given
interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN);
interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN));

// When
request.setRequestURI(FOO);
Expand All @@ -104,7 +104,7 @@ void doInternalCalledForMatchingRequest() {
@Test
void doInternalNotCalledForNonMatchingRequest() {
// Given
interceptor.restfulPatterns = List.of(REGISTRATION_PATTERN);
interceptor.restfulPatterns = RestfulPatterns.from(List.of(REGISTRATION_PATTERN));

// When
request.setRequestURI(BAR);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.restful_spring.rest_interceptor;

import static org.assertj.core.api.Assertions.assertThat;

import java.lang.reflect.Field;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpMethod;
import org.springframework.mock.web.MockHttpServletRequest;

class RestfulPatternsTest {

private static List<RestfulPattern> parseValues(RestfulPatterns patterns) {
try {
Field valuesField = RestfulPatterns.class.getDeclaredField("values");
valuesField.setAccessible(true);
return (List<RestfulPattern>) valuesField.get(patterns);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}

@Test
void emptyCreation() {

// Given
RestfulPatterns patterns = RestfulPatterns.empty();

// When
List<RestfulPattern> values = parseValues(patterns);
int actual = values.size();

// Then
assertThat(actual).isEqualTo(0);
}

@Test
void noneMatches() {

// Given
RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET);
RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST);
RestfulPatterns patterns = RestfulPatterns.from(List.of(pattern1, pattern2));

// When
MockHttpServletRequest request1 = new MockHttpServletRequest(HttpMethod.GET.name(), "/bar");
MockHttpServletRequest request2 = new MockHttpServletRequest(HttpMethod.GET.name(), "/foo");
MockHttpServletRequest request3 = new MockHttpServletRequest(HttpMethod.PATCH.name(), "/baz");

// Then
assertThat(patterns.noneMatches(request1)).isTrue();
assertThat(patterns.noneMatches(request2)).isFalse();
assertThat(patterns.noneMatches(request3)).isTrue();
}

@Test
void addAll() {

// Given
RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET);
RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST);
RestfulPatterns patterns = RestfulPatterns.empty();

// When
patterns.addAll(RestfulPatterns.from(List.of(pattern1, pattern2)));
int actual = parseValues(patterns).size();

// Then
assertThat(actual).isEqualTo(2);
}

@Test
void getPaths() {

// Given
RestfulPattern pattern1 = RestfulPattern.of("/foo", HttpMethod.GET);
RestfulPattern pattern2 = RestfulPattern.of("/bar", HttpMethod.POST);
RestfulPatterns patterns = RestfulPatterns.from(List.of(pattern1, pattern2));

// When
List<String> actual = patterns.getPaths();

// Then
assertThat(actual).containsExactlyInAnyOrder("/foo", "/bar");
}
}
Loading