Skip to content
Snippets Groups Projects
Commit 305d2e29 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Implemented download

parent cb271a5e
No related branches found
No related tags found
No related merge requests found
...@@ -14,6 +14,7 @@ import java.net.http.HttpClient; ...@@ -14,6 +14,7 @@ import java.net.http.HttpClient;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
import java.net.http.HttpResponse; import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandlers; import java.net.http.HttpResponse.BodyHandlers;
import java.util.List;
import java.util.Scanner; import java.util.Scanner;
import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionException;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinPool;
...@@ -23,6 +24,7 @@ import javax.servlet.http.HttpSession; ...@@ -23,6 +24,7 @@ import javax.servlet.http.HttpSession;
import javax.xml.bind.JAXB; import javax.xml.bind.JAXB;
import net.ivoa.xml.uws.v1.JobSummary; import net.ivoa.xml.uws.v1.JobSummary;
import net.ivoa.xml.vospace.v2.Node; import net.ivoa.xml.vospace.v2.Node;
import net.ivoa.xml.vospace.v2.Protocol;
import net.ivoa.xml.vospace.v2.Transfer; import net.ivoa.xml.vospace.v2.Transfer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -82,6 +84,17 @@ public class VOSpaceClient { ...@@ -82,6 +84,17 @@ public class VOSpaceClient {
return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class)); return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, JobSummary.class));
} }
public List<Protocol> getDownloadEndpoints(Transfer transfer) {
HttpRequest request = getRequest("/synctrans")
.header("Accept", useJson ? "application/json" : "text/xml")
.header("Content-Type", useJson ? "application/json" : "text/xml")
.POST(HttpRequest.BodyPublishers.ofString(marshal(transfer)))
.build();
return call(request, BodyHandlers.ofInputStream(), 200, res -> unmarshal(res, Transfer.class)).getProtocols();
}
private <T, U> U call(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, int expectedStatusCode, Function<T, U> responseHandler) { private <T, U> U call(HttpRequest request, HttpResponse.BodyHandler<T> responseBodyHandler, int expectedStatusCode, Function<T, U> responseHandler) {
try { try {
return httpClient.sendAsync(request, responseBodyHandler) return httpClient.sendAsync(request, responseBodyHandler)
......
...@@ -38,7 +38,7 @@ public class JobController { ...@@ -38,7 +38,7 @@ public class JobController {
transfer.setTarget("vos://" + authority + paths.get(0)); transfer.setTarget("vos://" + authority + paths.get(0));
Protocol protocol = new Protocol(); Protocol protocol = new Protocol();
protocol.setUri("ia2:tape-recall"); protocol.setUri("ia2:tape-recall");
transfer.getProtocol().add(protocol); transfer.getProtocols().add(protocol);
JobSummary job = client.startTransferJob(transfer); JobSummary job = client.startTransferJob(transfer);
......
package it.inaf.ia2.vospace.ui.controller; package it.inaf.ia2.vospace.ui.controller;
import it.inaf.ia2.vospace.ui.client.VOSpaceClient;
import it.inaf.ia2.vospace.ui.service.NodesService; import it.inaf.ia2.vospace.ui.service.NodesService;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import net.ivoa.xml.vospace.v2.Transfer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
@RestController @RestController
public class NodesController { public class NodesController {
@Value("${vospace-authority}")
private String authority;
@Autowired @Autowired
private NodesService nodesService; private NodesService nodesService;
@Autowired
private VOSpaceClient client;
@Autowired
private HttpServletRequest servletRequest;
/** /**
* This is the only API endpoint that returns HTML code instead of JSON. The * This is the only API endpoint that returns HTML code instead of JSON. The
* reason is that JavaScript frameworks are not very efficient in handling * reason is that JavaScript frameworks are not very efficient in handling
...@@ -23,21 +37,42 @@ public class NodesController { ...@@ -23,21 +37,42 @@ public class NodesController {
* document. * document.
*/ */
@GetMapping(value = {"/nodes", "/nodes/**"}, produces = MediaType.TEXT_PLAIN_VALUE) @GetMapping(value = {"/nodes", "/nodes/**"}, produces = MediaType.TEXT_PLAIN_VALUE)
public String listNodes(HttpServletRequest request) throws Exception { public String listNodes() throws Exception {
String requestURL = request.getRequestURL().toString(); String path = getPath("/nodes/");
String[] split = requestURL.split("/nodes/");
String path = "/"; return nodesService.generateNodesHtml(path);
if (split.length == 2) {
path += split[1];
} }
return nodesService.generateNodesHtml(path); @GetMapping(value = "/download/**")
public ResponseEntity<?> directDownload() {
String path = getPath("/download/");
Transfer transfer = new Transfer();
transfer.setDirection("pullFromVoSpace");
transfer.setTarget("vos://" + authority + path);
String url = client.getDownloadEndpoints(transfer).get(0).getEndpoint();
HttpHeaders headers = new HttpHeaders();
headers.set("Location", url);
return new ResponseEntity<>(headers, HttpStatus.SEE_OTHER);
} }
@GetMapping(value = "/download/{path}") /**
public void directDownload(@PathVariable("path") String path) { * Slash is a special character in defining REST endpoints and trying to
// TODO: call pullFromVoSpace sync transfer * define a PathVariable containing slashes doesn't work, so the endpoint
* has been defined using "/nodes/**" instead of "/nodes/{path}" and the
* path is extracted manually parsing the request URL.
*/
protected String getPath(String prefix) {
String requestURL = servletRequest.getRequestURL().toString();
String[] split = requestURL.split(prefix);
String path = "/";
if (split.length == 2) {
path += split[1];
}
return path;
} }
} }
...@@ -3,26 +3,28 @@ package it.inaf.ia2.vospace.ui.controller; ...@@ -3,26 +3,28 @@ package it.inaf.ia2.vospace.ui.controller;
import it.inaf.ia2.vospace.ui.service.NodesService; import it.inaf.ia2.vospace.ui.service.NodesService;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@ExtendWith(MockitoExtension.class) @SpringBootTest
@AutoConfigureMockMvc
public class NodesControllerTest { public class NodesControllerTest {
@Mock @MockBean
private NodesService nodesService; private NodesService nodesService;
@InjectMocks @Autowired
private NodesController controller; private NodesController controller;
@Autowired
private MockMvc mockMvc; private MockMvc mockMvc;
@BeforeEach @BeforeEach
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment