openvidu-server: new request mapping paths

pull/550/head
pabloFuente 2020-10-01 13:35:05 +02:00
parent 04c012a327
commit bdd54e01e5
14 changed files with 214 additions and 47 deletions

View File

@ -35,6 +35,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.DependsOn;
@ -66,6 +67,7 @@ import io.openvidu.server.recording.RecordingUploader;
import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.recording.service.RecordingManagerUtils;
import io.openvidu.server.recording.service.RecordingManagerUtilsLocalStorage;
import io.openvidu.server.rest.ApiRestPathRewriteFilter;
import io.openvidu.server.rpc.RpcHandler;
import io.openvidu.server.rpc.RpcNotificationService;
import io.openvidu.server.utils.CommandExecutor;
@ -225,6 +227,15 @@ public class OpenViduServer implements JsonRpcConfigurer {
return new MediaNodeStatusManagerDummy();
}
@Bean
@ConditionalOnMissingBean
public FilterRegistrationBean<ApiRestPathRewriteFilter> filterRegistrationBean() {
FilterRegistrationBean<ApiRestPathRewriteFilter> registrationBean = new FilterRegistrationBean<ApiRestPathRewriteFilter>();
ApiRestPathRewriteFilter apiRestPathRewriteFilter = new ApiRestPathRewriteFilter();
registrationBean.setFilter(apiRestPathRewriteFilter);
return registrationBean;
}
@Override
public void registerJsonRpcHandlers(JsonRpcHandlerRegistry registry) {
registry.addHandler(rpcHandler().withPingWatchdog(true).withInterceptors(new HttpHandshakeInterceptor()),

View File

@ -57,6 +57,7 @@ import io.openvidu.server.OpenViduServer;
import io.openvidu.server.cdr.CDREventName;
import io.openvidu.server.config.Dotenv.DotenvFormatException;
import io.openvidu.server.recording.RecordingNotification;
import io.openvidu.server.rest.RequestMappings;
@Component
public class OpenviduConfig {
@ -373,7 +374,7 @@ public class OpenviduConfig {
}
public String getOpenViduFrontendDefaultPath() {
return "dashboard";
return RequestMappings.FRONTEND_CE;
}
// Properties management methods

View File

@ -551,7 +551,7 @@ public class ComposedRecordingService extends RecordingService {
log.error(e.getMessage());
}
String defaultPathForDefaultLayout = recordingComposedUrlDefined ? ""
: ("/" + openviduConfig.getOpenViduFrontendDefaultPath());
: (openviduConfig.getOpenViduFrontendDefaultPath());
finalUrl = (startsWithHttp ? "http" : "https") + "://" + basicauth + recordingUrl
+ defaultPathForDefaultLayout + "/#/layout-" + layout + "/" + recording.getSessionId() + "/"
+ secret + "/" + port + "/" + !recording.hasAudio();

View File

@ -23,6 +23,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.rest.RequestMappings;
@Configuration
public class CDRHttpHandler implements WebMvcConfigurer {
@ -33,7 +34,7 @@ public class CDRHttpHandler implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String cdrPath = openviduConfig.getOpenviduCdrPath();
registry.addResourceHandler("/cdr/**.log").addResourceLocations("file:" + cdrPath);
registry.addResourceHandler(RequestMappings.CDR + "/**.log").addResourceLocations("file:" + cdrPath);
}
}

View File

@ -29,7 +29,7 @@ import io.openvidu.server.config.OpenviduConfig;
* /NEW_FRONTEND_PATH. Entrypoint file index.html must have tag
* <base href="/NEW_FRONTEND_PATH/">
*
* By default in OpenVidu CE this path is /dashbaord and in OpenVidu PRO is
* By default in OpenVidu CE this path is /dashboard and in OpenVidu PRO is
* /inspector
*
* @author Pablo Fuente (pablofuenteperez@gmail.com)
@ -42,10 +42,10 @@ public class FrontendResourceHandler extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/" + openviduConfig.getOpenViduFrontendDefaultPath())
.setViewName("redirect:/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/");
registry.addViewController("/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/")
.setViewName("forward:/" + openviduConfig.getOpenViduFrontendDefaultPath() + "/index.html");
registry.addViewController(openviduConfig.getOpenViduFrontendDefaultPath())
.setViewName("redirect:" + openviduConfig.getOpenViduFrontendDefaultPath() + "/");
registry.addViewController(openviduConfig.getOpenViduFrontendDefaultPath() + "/")
.setViewName("forward:" + openviduConfig.getOpenViduFrontendDefaultPath() + "/index.html");
super.addViewControllers(registry);
}

View File

@ -24,6 +24,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.rest.RequestMappings;
/**
* This class serves custom recording layouts from host folder indicated in
@ -41,7 +42,8 @@ public class RecordingCustomLayoutsResourceHandler implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String customLayoutsPath = openviduConfig.getOpenviduRecordingCustomLayout();
registry.addResourceHandler("/layouts/custom/**").addResourceLocations("file:" + customLayoutsPath);
registry.addResourceHandler(RequestMappings.CUSTOM_LAYOUTS + "/**")
.addResourceLocations("file:" + customLayoutsPath);
}
}

View File

@ -23,6 +23,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.rest.RequestMappings;
/**
* This class serves recording files from host folder indicated in configuration
@ -39,7 +40,7 @@ public class RecordingsResourceHandler implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
String recordingsPath = openviduConfig.getOpenViduRecordingPath();
registry.addResourceHandler("/recordings/**").addResourceLocations("file:" + recordingsPath);
registry.addResourceHandler(RequestMappings.RECORDINGS + "/**").addResourceLocations("file:" + recordingsPath);
}
}

View File

@ -0,0 +1,110 @@
package io.openvidu.server.rest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.util.WebUtils;
public class ApiRestPathRewriteFilter implements Filter {
protected static final Logger log = LoggerFactory.getLogger(ApiRestPathRewriteFilter.class);
protected Map<String, String> PATH_REDIRECTIONS_MAP = new HashMap<String, String>() {
{
// APIs
put("/api/", RequestMappings.API + "/");
put("/config", RequestMappings.API + "/config");
put("/config/", RequestMappings.API + "/config/");
put("/cdr", RequestMappings.CDR);
// Static resources
put("/cdr/", RequestMappings.CDR + "/");
put("/recordings/", RequestMappings.RECORDINGS + "/");
put("/layouts/custom/", RequestMappings.CUSTOM_LAYOUTS + "/");
put("/accept-certificate", RequestMappings.ACCEPT_CERTIFICATE); // ??
}
};
protected String[] PATH_REDIRECTIONS_ARRAY;
public ApiRestPathRewriteFilter() {
PATH_REDIRECTIONS_ARRAY = PATH_REDIRECTIONS_MAP.keySet().toArray(new String[PATH_REDIRECTIONS_MAP.size()]);
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("Initializing API REST path rewrite filter");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String requestPath = req.getRequestURI();
String oldBasePath = null;
String newBasePath = null;
for (final String path : PATH_REDIRECTIONS_ARRAY) {
if (requestPath.startsWith(path)) {
oldBasePath = path;
break;
}
}
if (oldBasePath != null) {
newBasePath = PATH_REDIRECTIONS_MAP.get(oldBasePath);
String redirectURI = newBasePath + requestPath.substring(oldBasePath.length());
StringBuffer redirectURL = new StringBuffer(
((HttpServletRequest) request).getRequestURL().toString().replaceFirst(oldBasePath, newBasePath));
log.warn(
"Path {} is deprecated. Use path {} instead. Deprecated path will be removed in a major release in the future",
oldBasePath, newBasePath);
chain.doFilter(new HttpServletRequestWrapper((HttpServletRequest) request) {
@Override
public String getRequestURI() {
return redirectURI;
}
@Override
public StringBuffer getRequestURL() {
return redirectURL;
}
@Override
public Object getAttribute(String name) {
if (WebUtils.INCLUDE_SERVLET_PATH_ATTRIBUTE.equals(name))
return redirectURI;
return super.getAttribute(name);
}
}, response);
} else {
chain.doFilter(req, res);
}
}
@Override
public void destroy() {
// Nothing to free up...
}
}

View File

@ -47,7 +47,7 @@ import io.openvidu.server.config.OpenviduConfig;
*/
@RestController
@CrossOrigin
@RequestMapping("/cdr")
@RequestMapping(RequestMappings.CDR)
public class CDRRestController {
private static final Logger log = LoggerFactory.getLogger(CDRRestController.class);

View File

@ -24,7 +24,7 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin
@RequestMapping("/accept-certificate")
@RequestMapping(RequestMappings.ACCEPT_CERTIFICATE)
public class CertificateRestController {
@RequestMapping(method = RequestMethod.GET)

View File

@ -21,9 +21,8 @@ import org.apache.http.Header;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
@ -36,6 +35,7 @@ import com.google.gson.JsonObject;
import io.openvidu.server.cdr.CDREventName;
import io.openvidu.server.config.OpenviduBuildInfo;
import io.openvidu.server.config.OpenviduConfig;
import io.openvidu.server.utils.RestUtils;
/**
*
@ -43,7 +43,8 @@ import io.openvidu.server.config.OpenviduConfig;
*/
@RestController
@CrossOrigin
@RequestMapping("/config")
@ConditionalOnMissingBean(name = "configRestControllerPro")
@RequestMapping(RequestMappings.API + "/config")
public class ConfigRestController {
private static final Logger log = LoggerFactory.getLogger(ConfigRestController.class);
@ -54,6 +55,14 @@ public class ConfigRestController {
@Autowired
private OpenviduBuildInfo openviduBuildInfo;
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<String> getOpenViduConfiguration() {
log.info("REST API: GET /config");
return this.getConfig();
}
@RequestMapping(value = "/openvidu-version", method = RequestMethod.GET)
public String getOpenViduServerVersion() {
@ -94,11 +103,7 @@ public class ConfigRestController {
return openviduConfig.isCdrEnabled();
}
@RequestMapping(method = RequestMethod.GET)
public ResponseEntity<String> getOpenViduConfiguration() {
log.info("REST API: GET /config");
protected ResponseEntity<String> getConfig() {
JsonObject json = new JsonObject();
json.addProperty("VERSION", openviduBuildInfo.getVersion());
json.addProperty("DOMAIN_OR_PUBLIC_IP", openviduConfig.getDomainOrPublicIp());
@ -141,13 +146,7 @@ public class ConfigRestController {
json.add("OPENVIDU_WEBHOOK_EVENTS", webhookEvents);
}
return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
}
protected HttpHeaders getResponseHeaders() {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
return responseHeaders;
return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
}
}

View File

@ -0,0 +1,16 @@
package io.openvidu.server.rest;
public class RequestMappings {
final public static String API = "/openvidu/api";
final public static String CDR = "/openvidu/cdr";
final public static String API_ELK = "/openvidu/elasticsearch";
final public static String API_INSPECTOR = "/openvidu/inspector-api";
final public static String RECORDINGS = "/openvidu/recordings";
final public static String CUSTOM_LAYOUTS = "/openvidu/layouts";
final public static String FRONTEND_CE = "/dashboard";
final public static String FRONTEND_PRO = "/inspector";
final public static String ACCEPT_CERTIFICATE = "/openvidu/accept-certificate"; // ????
}

View File

@ -28,9 +28,7 @@ import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PathVariable;
@ -67,6 +65,7 @@ import io.openvidu.server.kurento.core.KurentoTokenOptions;
import io.openvidu.server.recording.Recording;
import io.openvidu.server.recording.service.RecordingManager;
import io.openvidu.server.utils.RecordingUtils;
import io.openvidu.server.utils.RestUtils;
/**
*
@ -74,7 +73,7 @@ import io.openvidu.server.utils.RecordingUtils;
*/
@RestController
@CrossOrigin
@RequestMapping("/api")
@RequestMapping(RequestMappings.API)
public class SessionRestController {
private static final Logger log = LoggerFactory.getLogger(SessionRestController.class);
@ -180,7 +179,7 @@ public class SessionRestController {
responseJson.addProperty("id", sessionNotActive.getSessionId());
responseJson.addProperty("createdAt", sessionNotActive.getStartTime());
return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
}
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.GET)
@ -192,13 +191,13 @@ public class SessionRestController {
Session session = this.sessionManager.getSession(sessionId);
if (session != null) {
JsonObject response = (webRtcStats == true) ? session.withStatsToJson() : session.toJson();
return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else {
Session sessionNotActive = this.sessionManager.getSessionNotActive(sessionId);
if (sessionNotActive != null) {
JsonObject response = (webRtcStats == true) ? sessionNotActive.withStatsToJson()
: sessionNotActive.toJson();
return new ResponseEntity<>(response.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(response.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@ -220,7 +219,7 @@ public class SessionRestController {
});
json.addProperty("numberOfElements", sessions.size());
json.add("content", jsonArray);
return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
}
@RequestMapping(value = "/sessions/{sessionId}", method = RequestMethod.DELETE)
@ -430,7 +429,7 @@ public class SessionRestController {
}
responseJson.add("kurentoOptions", kurentoOptsResponse);
}
return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} catch (Exception e) {
return this.generateErrorResponse(
"Error generating token for session " + sessionId + ": " + e.getMessage(), "/api/tokens",
@ -593,9 +592,10 @@ public class SessionRestController {
try {
Recording startedRecording = this.recordingManager.startRecording(session, builder.build());
return new ResponseEntity<>(startedRecording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(startedRecording.toJson().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (OpenViduException e) {
return new ResponseEntity<>("Error starting recording: " + e.getMessage(), getResponseHeaders(),
return new ResponseEntity<>("Error starting recording: " + e.getMessage(), RestUtils.getResponseHeaders(),
HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@ -638,7 +638,8 @@ public class SessionRestController {
session.getParticipantByPublicId(ProtocolElements.RECORDER_PARTICIPANT_PUBLICID), null, null, null);
}
return new ResponseEntity<>(stoppedRecording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(stoppedRecording.toJson().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
}
@RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.GET)
@ -657,7 +658,7 @@ public class SessionRestController {
&& recordingManager.getStartingRecording(recording.getId()) != null) {
recording.setStatus(io.openvidu.java.client.Recording.Status.starting);
}
return new ResponseEntity<>(recording.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(recording.toJson().toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
@ -685,7 +686,7 @@ public class SessionRestController {
});
json.addProperty("count", recordings.size());
json.add("items", jsonArray);
return new ResponseEntity<>(json.toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(json.toString(), RestUtils.getResponseHeaders(), HttpStatus.OK);
}
@RequestMapping(value = "/recordings/{recordingId}", method = RequestMethod.DELETE)
@ -832,7 +833,8 @@ public class SessionRestController {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
Participant ipcamParticipant = this.sessionManager.publishIpcam(session, mediaOptions, data);
return new ResponseEntity<>(ipcamParticipant.toJson().toString(), getResponseHeaders(), HttpStatus.OK);
return new ResponseEntity<>(ipcamParticipant.toJson().toString(), RestUtils.getResponseHeaders(),
HttpStatus.OK);
} catch (MalformedURLException e) {
return this.generateErrorResponse("\"rtspUri\" parameter is not a valid rtsp uri",
"/api/sessions/" + sessionId + "/connection", HttpStatus.BAD_REQUEST);
@ -854,12 +856,7 @@ public class SessionRestController {
responseJson.addProperty("error", status.getReasonPhrase());
responseJson.addProperty("message", errorMessage);
responseJson.addProperty("path", path);
return new ResponseEntity<>(responseJson.toString(), getResponseHeaders(), status);
return new ResponseEntity<>(responseJson.toString(), RestUtils.getResponseHeaders(), status);
}
private HttpHeaders getResponseHeaders() {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
return responseHeaders;
}
}

View File

@ -0,0 +1,29 @@
package io.openvidu.server.utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
public class RestUtils {
private static final Logger log = LoggerFactory.getLogger(RestUtils.class);
public static HttpHeaders getResponseHeaders() {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.APPLICATION_JSON);
return responseHeaders;
}
public static ResponseEntity<String> getErrorResponse(String message, HttpStatus status) {
if (!status.is2xxSuccessful()) {
log.error(message);
}
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.setContentType(MediaType.TEXT_PLAIN);
return new ResponseEntity<>(message, responseHeaders, status);
}
}