Add processing of Accept header to AudioServlet (#2960)

Signed-off-by: Jan N. Klug <github@klug.nrw>
pull/2968/head
J-N-K 2022-05-16 22:31:36 +02:00 committed by GitHub
parent b11086ef45
commit d4a68c83fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 29 additions and 5 deletions

View File

@ -18,10 +18,12 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -53,6 +55,8 @@ public class AudioServlet extends OpenHABServlet implements AudioHTTPServer {
private static final long serialVersionUID = -3364664035854567854L; private static final long serialVersionUID = -3364664035854567854L;
private static final List<String> WAV_MIME_TYPES = List.of("audio/wav", "audio/x-wav", "audio/vnd.wave");
private static final String SERVLET_NAME = "/audio"; private static final String SERVLET_NAME = "/audio";
private final Map<String, AudioStream> oneTimeStreams = new ConcurrentHashMap<>(); private final Map<String, AudioStream> oneTimeStreams = new ConcurrentHashMap<>();
@ -90,8 +94,8 @@ public class AudioServlet extends OpenHABServlet implements AudioHTTPServer {
} }
} }
private @Nullable InputStream prepareInputStream(final String streamId, final HttpServletResponse resp) private @Nullable InputStream prepareInputStream(final String streamId, final HttpServletResponse resp,
throws AudioException { List<String> acceptedMimeTypes) throws AudioException {
final AudioStream stream; final AudioStream stream;
final boolean multiAccess; final boolean multiAccess;
if (oneTimeStreams.containsKey(streamId)) { if (oneTimeStreams.containsKey(streamId)) {
@ -111,7 +115,7 @@ public class AudioServlet extends OpenHABServlet implements AudioHTTPServer {
if (AudioFormat.CODEC_MP3.equals(stream.getFormat().getCodec())) { if (AudioFormat.CODEC_MP3.equals(stream.getFormat().getCodec())) {
mimeType = "audio/mpeg"; mimeType = "audio/mpeg";
} else if (AudioFormat.CONTAINER_WAVE.equals(stream.getFormat().getContainer())) { } else if (AudioFormat.CONTAINER_WAVE.equals(stream.getFormat().getContainer())) {
mimeType = "audio/wav"; mimeType = WAV_MIME_TYPES.stream().filter(acceptedMimeTypes::contains).findFirst().orElse("audio/wav");
} else if (AudioFormat.CONTAINER_OGG.equals(stream.getFormat().getContainer())) { } else if (AudioFormat.CONTAINER_OGG.equals(stream.getFormat().getContainer())) {
mimeType = "audio/ogg"; mimeType = "audio/ogg";
} else { } else {
@ -158,7 +162,10 @@ public class AudioServlet extends OpenHABServlet implements AudioHTTPServer {
final String streamId = substringBefore(substringAfterLast(requestURI, "/"), "."); final String streamId = substringBefore(substringAfterLast(requestURI, "/"), ".");
try (final InputStream stream = prepareInputStream(streamId, resp)) { List<String> acceptedMimeTypes = Stream.of(Objects.requireNonNullElse(req.getHeader("Accept"), "").split(","))
.map(String::trim).collect(Collectors.toList());
try (final InputStream stream = prepareInputStream(streamId, resp, acceptedMimeTypes)) {
if (stream == null) { if (stream == null) {
logger.debug("Received request for invalid stream id at {}", requestURI); logger.debug("Received request for invalid stream id at {}", requestURI);
resp.sendError(HttpServletResponse.SC_NOT_FOUND); resp.sendError(HttpServletResponse.SC_NOT_FOUND);

View File

@ -97,6 +97,11 @@ public abstract class AbstractAudioServletTest extends JavaTest {
return getHttpRequest(url).send(); return getHttpRequest(url).send();
} }
protected ContentResponse getHttpResponseWithAccept(AudioStream audioStream, String acceptHeader) throws Exception {
String url = serveStream(audioStream);
return getHttpRequest(url).header("Accept", acceptHeader).send();
}
protected String serveStream(AudioStream stream) throws Exception { protected String serveStream(AudioStream stream) throws Exception {
return serveStream(stream, null); return serveStream(stream, null);
} }

View File

@ -62,7 +62,7 @@ public class AudioServletTest extends AbstractAudioServletTest {
} }
@Test @Test
public void audioServletProcessesStreamFromWavFile() throws Exception { public void audioServletProcessesStreamFromWavFileWithoutAcceptHeader() throws Exception {
try (BundledSoundFileHandler fileHandler = new BundledSoundFileHandler()) { try (BundledSoundFileHandler fileHandler = new BundledSoundFileHandler()) {
AudioStream audioStream = new FileAudioStream(new File(fileHandler.wavFilePath())); AudioStream audioStream = new FileAudioStream(new File(fileHandler.wavFilePath()));
@ -74,6 +74,18 @@ public class AudioServletTest extends AbstractAudioServletTest {
} }
} }
@Test
public void audioServletProcessesStreamFromWavFileWithAcceptHeader() throws Exception {
try (BundledSoundFileHandler fileHandler = new BundledSoundFileHandler()) {
AudioStream audioStream = new FileAudioStream(new File(fileHandler.wavFilePath()));
ContentResponse response = getHttpResponseWithAccept(audioStream, "audio/invalid, audio/x-wav");
assertThat("The response status was not as expected", response.getStatus(), is(HttpStatus.OK_200));
assertThat("The response media type was not as expected", response.getMediaType(), is("audio/x-wav"));
}
}
@Test @Test
public void audioServletProcessesStreamFromOggContainer() throws Exception { public void audioServletProcessesStreamFromOggContainer() throws Exception {
AudioStream audioStream = getByteArrayAudioStream(testByteArray, AudioFormat.CONTAINER_OGG, AudioStream audioStream = getByteArrayAudioStream(testByteArray, AudioFormat.CONTAINER_OGG,