All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.xlrit.gears.server.rest.ContentController Maven / Gradle / Ivy

The newest version!
package com.xlrit.gears.server.rest;

import com.google.common.base.Strings;
import com.xlrit.gears.base.content.Content;
import com.xlrit.gears.base.content.ContentStore;
import com.xlrit.gears.base.exception.NotFoundException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.UrlPathHelper;

@Controller
@RequiredArgsConstructor
public class ContentController {
	private static final Logger LOG = LoggerFactory.getLogger(ContentController.class);
	private static final String CONTENT_PREFIX = "/content/";
	private static final String CONTENT_PATH = CONTENT_PREFIX + "**";

	private final ContentStore contentStore;
	private final UrlPathHelper urlPathHelper;

	@GetMapping(CONTENT_PATH)
	@ResponseBody
	@Transactional
	@PreAuthorize("isAuthenticated()")
	public ResponseEntity getContent(HttpServletRequest request, @RequestParam(required = false, defaultValue = "false") boolean open) {
		String decodedRequestUri = urlPathHelper.getRequestUri(request);
		LOG.debug("getContent: decodedRequestUri={}, open={}", decodedRequestUri, open);
		String path = extractContentPath(decodedRequestUri);
		return getContentResponse(path, open);
	}

	private ResponseEntity getContentResponse(String path, boolean open) {
		LOG.debug("getContentResponse: path={}", path);
		if (Strings.isNullOrEmpty(path)) throw new IllegalArgumentException("Parameter 'path' is required");

		Content content = contentStore.findContent(path);
		if (content == null) {
			LOG.error("getContentResponse: content with path '{}' not found", path);
			throw new NotFoundException("content", "path", path);
		}

		String filename = content.getFilename();
		String disposition = (open ? "inline" : "attachment") + "; filename=\"" + filename + "\"";
		String contentType = refineContentType(content.getContentType(), filename);

		LOG.info("getContentResponse: returning content with path '{}', filename '{}', contentType '{}'", path, filename, contentType);
		return ResponseEntity.ok()
			.header(HttpHeaders.CONTENT_TYPE, contentType)
			.header(HttpHeaders.CONTENT_DISPOSITION, disposition)
			.body(content.getData());
	}

	private static String refineContentType(String contentType, String filename) {
		if (!Strings.isNullOrEmpty(contentType) && !"application/octet-stream".equals(contentType) || filename == null)
			return contentType;
		if (filename.endsWith(".msg"))
			return "application/vnd.ms-outlook";
		return contentType;
	}

	static String extractContentPath(String requestUri) {
		int index = requestUri.indexOf(CONTENT_PREFIX);
		if (index == -1) throw new IllegalArgumentException("Invalid content URI: " + requestUri);
		return requestUri.substring(index + CONTENT_PREFIX.length());
	}

/*
	// This approach doesn't work, because `path` cannot contain slashes, even if encoded as %2F.
	// See https://stackoverflow.com/questions/13482020/encoded-slash-2f-with-spring-requestmapping-path-param-gives-http-400
	@GetMapping("/content/{path}")
	@ResponseBody
	@Transactional
	@PreAuthorize("isAuthenticated()")
	public ResponseEntity getContent(@PathVariable String path, @RequestParam(required = false, defaultValue = "false") boolean open) {
		LOG.info("getContent: path={}, open={}", path, open);
		return getContentResponse(path, open);
	}
*/
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy