Initial working implementation of HLS proxy
This commit is contained in:
107
src/main/java/com/backend/hls/proxy/service/FetchService.java
Normal file
107
src/main/java/com/backend/hls/proxy/service/FetchService.java
Normal file
@ -0,0 +1,107 @@
|
||||
package com.backend.hls.proxy.service;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.time.Duration;
|
||||
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.backend.hls.proxy.exception.FetchFailException;
|
||||
import com.backend.hls.proxy.model.SimpleResponse;
|
||||
|
||||
@Service
|
||||
public class FetchService {
|
||||
private final HttpClient httpClient;
|
||||
|
||||
public FetchService(HttpClient httpClient) {
|
||||
this.httpClient = httpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch text content from URL
|
||||
*
|
||||
* @throws FetchFailException
|
||||
*/
|
||||
@Cacheable("hlsPlaylistContent")
|
||||
public String fetchTextContent(String url) throws IOException, InterruptedException, FetchFailException {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
|
||||
if (response.statusCode() != 200) {
|
||||
throw new FetchFailException("Failed to fetch content from " + url + ", status: " + response.statusCode(),
|
||||
response);
|
||||
}
|
||||
|
||||
return response.body();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch binary content from URL
|
||||
*
|
||||
* @throws FetchFailException
|
||||
*/
|
||||
@Cacheable("playlistSegmentContent")
|
||||
public SimpleResponse<byte[]> fetchBinaryContent(String url)
|
||||
throws IOException, InterruptedException, FetchFailException {
|
||||
return fetchBinaryContent(url, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch binary content from URL
|
||||
*
|
||||
* @throws FetchFailException
|
||||
*/
|
||||
@Cacheable("playlistSegmentContent")
|
||||
public SimpleResponse<byte[]> fetchBinaryContent(String url, String rangeHeader)
|
||||
throws IOException, InterruptedException, FetchFailException {
|
||||
HttpRequest.Builder builder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url));
|
||||
|
||||
if (rangeHeader != null && !rangeHeader.isEmpty()) {
|
||||
builder.header("Range", rangeHeader);
|
||||
}
|
||||
|
||||
HttpResponse<byte[]> response = httpClient.send(builder.build(), HttpResponse.BodyHandlers.ofByteArray());
|
||||
|
||||
if (response.statusCode() >= 400) {
|
||||
throw new FetchFailException("Failed to fetch content from " + url + ", status: " + response.statusCode(),
|
||||
response);
|
||||
}
|
||||
|
||||
return new SimpleResponse<byte[]>(response.body(), response.headers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch content length
|
||||
*
|
||||
* @throws FetchFailException
|
||||
*/
|
||||
public long getContentLength(String url)
|
||||
throws IOException, InterruptedException, FetchFailException {
|
||||
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(url))
|
||||
.method("HEAD", HttpRequest.BodyPublishers.noBody())
|
||||
.timeout(Duration.ofSeconds(10))
|
||||
.build();
|
||||
|
||||
HttpResponse<Void> response = httpClient.send(request,
|
||||
HttpResponse.BodyHandlers.discarding());
|
||||
|
||||
if (response.statusCode() >= 400) {
|
||||
throw new FetchFailException("HTTP " + response.statusCode(), response);
|
||||
}
|
||||
|
||||
return response.headers()
|
||||
.firstValueAsLong("Content-Length")
|
||||
.orElse(-1L);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user