Loading src/main/java/it/inaf/oats/vospace/CapabilitiesController.java 0 → 100644 +56 −0 Original line number Diff line number Diff line package it.inaf.oats.vospace; import java.io.IOException; import java.io.InputStream; import java.util.Scanner; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; @RestController public class CapabilitiesController { @Autowired private HttpServletRequest request; @GetMapping(value = "/capabilities", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE}) public String getCapabilities() throws IOException { String xml = loadCapabilitiesXmlTemplate(); return xml.replace("{{ base_url }}", getBaseUrl()); } private String loadCapabilitiesXmlTemplate() throws IOException { try ( InputStream in = CapabilitiesController.class.getClassLoader().getResourceAsStream("capabilities.xml")) { Scanner s = new Scanner(in).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } } /** * Generate base URL considering also proxied requests. */ private String getBaseUrl() { String forwaredProtocol = request.getHeader("X-Forwarded-Proto"); String scheme = forwaredProtocol != null ? forwaredProtocol : request.getScheme(); String forwardedHost = request.getHeader("X-Forwarded-Host"); if (forwardedHost != null && forwardedHost.contains(",")) { // X-Forwarded-Host can be a list of comma separated values forwardedHost = forwardedHost.split(",")[0]; } String host = forwardedHost != null ? forwardedHost : request.getServerName(); UriComponentsBuilder builder = UriComponentsBuilder.newInstance() .scheme(scheme).host(host).path(request.getContextPath()); if (forwardedHost == null) { builder.port(request.getServerPort()); } return builder.toUriString(); } } src/main/resources/capabilities.xml 0 → 100644 +54 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="UTF-8"?> <vosi:capabilities xmlns:vosi="http://www.ivoa.net/xml/VOSICapabilities/v1.0" xmlns:vs="http://www.ivoa.net/xml/VODataService/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <capability standardID="ivo://ivoa.net/std/VOSI#capabilities"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/capabilities</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSI#availability"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/availability</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#views"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/views</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#nodes"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="base">{{ base_url }}/nodes</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="base">{{ base_url }}/nodes</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#transfers"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/transfers</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/transfers</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#sync"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace#sync-2.1"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> </vosi:capabilities> No newline at end of file src/test/java/it/inaf/oats/vospace/CapabilitiesControllerTest.java 0 → 100644 +62 −0 Original line number Diff line number Diff line package it.inaf.oats.vospace; import javax.servlet.http.HttpServletRequest; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import static org.mockito.Mockito.when; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @ExtendWith(MockitoExtension.class) public class CapabilitiesControllerTest { private MockMvc mockMvc; @Mock private HttpServletRequest request; @InjectMocks private CapabilitiesController controller; @BeforeEach public void init() { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void testGetCapabilitiesBase() throws Exception { when(request.getServerName()).thenReturn("ia2.inaf.it"); when(request.getServerPort()).thenReturn(8080); when(request.getContextPath()).thenReturn("/vospace"); when(request.getScheme()).thenReturn("http"); String xml = mockMvc.perform(get("/capabilities")) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); assertTrue(xml.contains("http://ia2.inaf.it:8080/vospace/nodes")); } @Test public void testGetCapabilitiesProxied() throws Exception { when(request.getHeader("X-Forwarded-Proto")).thenReturn("https"); when(request.getHeader("X-Forwarded-Host")).thenReturn("ia2.inaf.it,server2.ia2.inaf.it"); when(request.getContextPath()).thenReturn("/vospace"); String xml = mockMvc.perform(get("/capabilities")) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); assertTrue(xml.contains("https://ia2.inaf.it/vospace/nodes")); } } Loading
src/main/java/it/inaf/oats/vospace/CapabilitiesController.java 0 → 100644 +56 −0 Original line number Diff line number Diff line package it.inaf.oats.vospace; import java.io.IOException; import java.io.InputStream; import java.util.Scanner; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.util.UriComponentsBuilder; @RestController public class CapabilitiesController { @Autowired private HttpServletRequest request; @GetMapping(value = "/capabilities", produces = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE}) public String getCapabilities() throws IOException { String xml = loadCapabilitiesXmlTemplate(); return xml.replace("{{ base_url }}", getBaseUrl()); } private String loadCapabilitiesXmlTemplate() throws IOException { try ( InputStream in = CapabilitiesController.class.getClassLoader().getResourceAsStream("capabilities.xml")) { Scanner s = new Scanner(in).useDelimiter("\\A"); return s.hasNext() ? s.next() : ""; } } /** * Generate base URL considering also proxied requests. */ private String getBaseUrl() { String forwaredProtocol = request.getHeader("X-Forwarded-Proto"); String scheme = forwaredProtocol != null ? forwaredProtocol : request.getScheme(); String forwardedHost = request.getHeader("X-Forwarded-Host"); if (forwardedHost != null && forwardedHost.contains(",")) { // X-Forwarded-Host can be a list of comma separated values forwardedHost = forwardedHost.split(",")[0]; } String host = forwardedHost != null ? forwardedHost : request.getServerName(); UriComponentsBuilder builder = UriComponentsBuilder.newInstance() .scheme(scheme).host(host).path(request.getContextPath()); if (forwardedHost == null) { builder.port(request.getServerPort()); } return builder.toUriString(); } }
src/main/resources/capabilities.xml 0 → 100644 +54 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="UTF-8"?> <vosi:capabilities xmlns:vosi="http://www.ivoa.net/xml/VOSICapabilities/v1.0" xmlns:vs="http://www.ivoa.net/xml/VODataService/v1.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <capability standardID="ivo://ivoa.net/std/VOSI#capabilities"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/capabilities</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSI#availability"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/availability</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#views"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/views</accessURL> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#nodes"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="base">{{ base_url }}/nodes</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="base">{{ base_url }}/nodes</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#transfers"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/transfers</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/transfers</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace/v2.0#sync"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> <capability standardID="ivo://ivoa.net/std/VOSpace#sync-2.1"> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> </interface> <interface xsi:type="vs:ParamHTTP" role="std"> <accessURL use="full">{{ base_url }}/synctrans</accessURL> <securityMethod standardID="vos://cadc.nrc.ca~vospace/CADC/std/Auth#token-1.0"/> </interface> </capability> </vosi:capabilities> No newline at end of file
src/test/java/it/inaf/oats/vospace/CapabilitiesControllerTest.java 0 → 100644 +62 −0 Original line number Diff line number Diff line package it.inaf.oats.vospace; import javax.servlet.http.HttpServletRequest; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import static org.mockito.Mockito.when; import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import org.springframework.test.web.servlet.setup.MockMvcBuilders; @ExtendWith(MockitoExtension.class) public class CapabilitiesControllerTest { private MockMvc mockMvc; @Mock private HttpServletRequest request; @InjectMocks private CapabilitiesController controller; @BeforeEach public void init() { mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); } @Test public void testGetCapabilitiesBase() throws Exception { when(request.getServerName()).thenReturn("ia2.inaf.it"); when(request.getServerPort()).thenReturn(8080); when(request.getContextPath()).thenReturn("/vospace"); when(request.getScheme()).thenReturn("http"); String xml = mockMvc.perform(get("/capabilities")) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); assertTrue(xml.contains("http://ia2.inaf.it:8080/vospace/nodes")); } @Test public void testGetCapabilitiesProxied() throws Exception { when(request.getHeader("X-Forwarded-Proto")).thenReturn("https"); when(request.getHeader("X-Forwarded-Host")).thenReturn("ia2.inaf.it,server2.ia2.inaf.it"); when(request.getContextPath()).thenReturn("/vospace"); String xml = mockMvc.perform(get("/capabilities")) .andExpect(status().isOk()) .andReturn().getResponse().getContentAsString(); assertTrue(xml.contains("https://ia2.inaf.it/vospace/nodes")); } }