HttpFetcher.java
/*
* Copyright 2024 The Sigstore Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package dev.sigstore.tuf;
import com.google.api.client.http.GenericUrl;
import com.google.api.client.json.gson.GsonFactory;
import dev.sigstore.http.HttpClients;
import dev.sigstore.http.HttpParams;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
public class HttpFetcher implements Fetcher {
private final URL mirror;
private HttpFetcher(URL mirror) {
this.mirror = mirror;
}
public static HttpFetcher newFetcher(URL mirror) throws MalformedURLException {
if (mirror.toString().endsWith("/")) {
return new HttpFetcher(mirror);
}
return new HttpFetcher(new URL(mirror.toExternalForm() + "/"));
}
@Override
public String getSource() {
return mirror.toString();
}
@Override
public byte[] fetchResource(String filename, int maxLength)
throws IOException, FileExceedsMaxLengthException {
GenericUrl fileUrl = new GenericUrl(mirror + filename);
var req =
HttpClients.newHttpTransport(HttpParams.builder().build())
.createRequestFactory(
request ->
request.setParser(GsonFactory.getDefaultInstance().createJsonObjectParser()))
.buildGetRequest(fileUrl);
req.getHeaders().setAccept("application/json; api-version=2.0");
req.getHeaders().setContentType("application/json");
req.setThrowExceptionOnExecuteError(false);
var resp = req.execute();
if (resp.getStatusCode() == 404) {
return null;
}
if (resp.getStatusCode() != 200) {
throw new TufException(
String.format(
Locale.ROOT,
"Unexpected return from mirror(%s). Status code: %s, status message: %s",
mirror,
resp.getStatusCode(),
resp.getStatusMessage()));
}
byte[] roleBytes = resp.getContent().readNBytes(maxLength);
if (roleBytes.length == maxLength && resp.getContent().read() != -1) {
throw new FileExceedsMaxLengthException(fileUrl.toString(), maxLength);
}
return roleBytes;
}
}