From 32f0331d90d9af8dbd9c0405805fe2b18dc062d3 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Fri, 14 Jun 2024 12:31:25 +0100 Subject: [PATCH] Allow cross-origin requests from spring.io and enterprise.spring.io Closes gh-26 --- .../release/ReleaseEventsController.java | 2 ++ .../release/ReleaseICalController.java | 2 ++ .../release/ReleaseEventsControllerTests.java | 19 +++++++++++++++++++ .../release/ReleaseICalControllerTests.java | 17 +++++++++++++++++ 4 files changed, 40 insertions(+) diff --git a/src/main/java/io/spring/calendar/release/ReleaseEventsController.java b/src/main/java/io/spring/calendar/release/ReleaseEventsController.java index b608fa9..ad97f74 100644 --- a/src/main/java/io/spring/calendar/release/ReleaseEventsController.java +++ b/src/main/java/io/spring/calendar/release/ReleaseEventsController.java @@ -28,6 +28,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -42,6 +43,7 @@ */ @RestController @RequestMapping("/releases") +@CrossOrigin(origins = { "https://spring.io", "https://enterprise.spring.io" }) class ReleaseEventsController { private final ReleaseRepository releaseRepository; diff --git a/src/main/java/io/spring/calendar/release/ReleaseICalController.java b/src/main/java/io/spring/calendar/release/ReleaseICalController.java index dfea376..f82815a 100644 --- a/src/main/java/io/spring/calendar/release/ReleaseICalController.java +++ b/src/main/java/io/spring/calendar/release/ReleaseICalController.java @@ -25,6 +25,7 @@ import biweekly.component.VEvent; import io.spring.calendar.release.Release.Type; +import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -36,6 +37,7 @@ */ @RestController @RequestMapping("/ical") +@CrossOrigin(origins = { "https://spring.io", "https://enterprise.spring.io" }) class ReleaseICalController { private final ReleaseRepository releaseRepository; diff --git a/src/test/java/io/spring/calendar/release/ReleaseEventsControllerTests.java b/src/test/java/io/spring/calendar/release/ReleaseEventsControllerTests.java index 6717250..af8d514 100644 --- a/src/test/java/io/spring/calendar/release/ReleaseEventsControllerTests.java +++ b/src/test/java/io/spring/calendar/release/ReleaseEventsControllerTests.java @@ -22,10 +22,13 @@ import io.spring.calendar.release.Release.Status; import io.spring.calendar.release.Release.Type; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpHeaders; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.result.MockMvcResultMatchers; @@ -82,4 +85,20 @@ void whenReleasesWithTypeIsCalledThenReleasesOfTypeInPeriodAreReturned() throws .json("[{\"allDay\":true,\"backgroundColor\":\"#6db33f\",\"start\":\"2024-06-01\",\"title\":\"Spring Boot 3.3.1\"}]")); } + @ParameterizedTest + @ValueSource(strings = { "https://spring.io", "https://enterprise.spring.io" }) + void releasesAllowsCrossOriginRequestsFromSpringIo(String origin) throws Exception { + this.mvc + .perform(MockMvcRequestBuilders.get("/releases?start=2024-06-01&end=2024-06-02").header("Origin", origin)) + .andExpect(MockMvcResultMatchers.header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin)); + } + + @Test + void releasesDoesNotAllowCrossOriginRequestsFromElsewhere() throws Exception { + this.mvc + .perform(MockMvcRequestBuilders.get("/releases?start=2024-06-01&end=2024-06-02") + .header("Origin", "https://example.com")) + .andExpect(MockMvcResultMatchers.header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + } + } diff --git a/src/test/java/io/spring/calendar/release/ReleaseICalControllerTests.java b/src/test/java/io/spring/calendar/release/ReleaseICalControllerTests.java index 85e2149..4f5c2e9 100644 --- a/src/test/java/io/spring/calendar/release/ReleaseICalControllerTests.java +++ b/src/test/java/io/spring/calendar/release/ReleaseICalControllerTests.java @@ -24,12 +24,16 @@ import io.spring.calendar.release.Release.Status; import io.spring.calendar.release.Release.Type; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.HttpHeaders; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.BDDMockito.given; @@ -98,6 +102,19 @@ void givenSomeReleasesWhenIcalIsCalledWithOssThenSingleCalendarIsReturnedWithOne }); } + @ParameterizedTest + @ValueSource(strings = { "https://spring.io", "https://enterprise.spring.io" }) + void icalAllowsCrossOriginRequestsFromSpringIo(String origin) throws Exception { + this.mvc.perform(MockMvcRequestBuilders.get("/ical").header("Origin", origin)) + .andExpect(MockMvcResultMatchers.header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, origin)); + } + + @Test + void icalDoesNotAllowCrossOriginRequestsFromElsewhere() throws Exception { + this.mvc.perform(MockMvcRequestBuilders.get("/ical").header("Origin", "https://example.com")) + .andExpect(MockMvcResultMatchers.header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); + } + private List calendars(String url) throws Exception { String responseBody = this.mvc.perform(MockMvcRequestBuilders.get(url)) .andReturn()