Commit 018c3c09 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added capabilities controller

parent b58a6eac
Loading
Loading
Loading
Loading
+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();
    }
}
+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
+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"));
    }
}