com.volcengine.tos.internal.RequestBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ve-tos-java-sdk Show documentation
Show all versions of ve-tos-java-sdk Show documentation
The VolcEngine TOS SDK for Java
package com.volcengine.tos.internal;
import com.volcengine.tos.TosClientException;
import com.volcengine.tos.auth.Signer;
import com.volcengine.tos.comm.TosHeader;
import com.volcengine.tos.internal.model.HttpRange;
import com.volcengine.tos.internal.util.StringUtils;
import com.volcengine.tos.internal.util.TosUtils;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.channels.FileChannel;
import java.time.Duration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import static com.volcengine.tos.internal.Consts.*;
public class RequestBuilder {
private Signer signer;
private String scheme;
private String host;
private int port;
private String bucket;
private String object;
private int urlMode = URL_MODE_DEFAULT;
private long contentLength = -1;
private HttpRange range;
private Map headers = new HashMap<>(1);
private Map query;
private boolean autoRecognizeContentType = true;
private String preHashCrc64ecma;
private boolean disableEncodingMeta;
private boolean skipTryResolveContentLength;
public RequestBuilder(){}
@Deprecated
public RequestBuilder(Signer signer, String scheme, String host, String bucket, String object,
int urlMode, Map headers, Map query){
Objects.requireNonNull(bucket, "bucket is null");
Objects.requireNonNull(object, "object is null");
this.signer = signer;
this.scheme = scheme;
this.host = host;
this.bucket = bucket;
this.object = object;
this.urlMode = urlMode;
this.headers = headers;
this.query = query;
}
public RequestBuilder(String bucket, String object, String scheme, String host, Signer signer){
Objects.requireNonNull(scheme, "scheme is null");
Objects.requireNonNull(host, "host is null");
// bucket can be null
// Objects.requireNonNull(bucket, "bucket is null");
this.bucket = bucket;
this.object = object;
this.scheme = scheme;
this.host = host;
this.signer = signer;
}
public RequestBuilder setHeaders(Map headers) {
this.headers = headers;
return this;
}
public Map getQuery() {
return query;
}
public RequestBuilder setQuery(Map query) {
this.query = query;
return this;
}
public HttpRange getRange() {
return range;
}
void setRange(HttpRange range) {
this.range = range;
}
public RequestBuilder withQuery(String key, String value){
if (StringUtils.isEmpty(key) || value == null) {
return this;
}
if (this.query == null) {
this.query = new HashMap<>(1);
}
this.query.put(key, value);
return this;
}
public RequestBuilder withHeader(String key, String value){
if(value != null && value.length() != 0){
this.headers.put(key, value);
}
return this;
}
public Map getHeaders() {
return headers;
}
public boolean isAutoRecognizeContentType() {
return autoRecognizeContentType;
}
public void setAutoRecognizeContentType(boolean autoRecognizeContentType) {
this.autoRecognizeContentType = autoRecognizeContentType;
}
public long getContentLength() {
return this.contentLength;
}
public RequestBuilder withContentLength(long length){
this.contentLength = length;
return this;
}
public String getHost() {
return host;
}
public RequestBuilder setHost(String host) {
this.host = host;
return this;
}
public int getUrlMode() {
return urlMode;
}
public RequestBuilder setUrlMode(int urlMode) {
this.urlMode = urlMode;
return this;
}
public int getPort() {
return port;
}
public RequestBuilder setPort(int port) {
this.port = port;
return this;
}
public String getPreHashCrc64ecma() {
return preHashCrc64ecma;
}
public RequestBuilder setPreHashCrc64ecma(String preHashCrc64ecma) {
this.preHashCrc64ecma = preHashCrc64ecma;
return this;
}
public RequestBuilder setDisableEncodingMeta(boolean disableEncodingMeta) {
this.disableEncodingMeta = disableEncodingMeta;
return this;
}
public RequestBuilder setSkipTryResolveContentLength(boolean skipTryResolveContentLength) {
this.skipTryResolveContentLength = skipTryResolveContentLength;
return this;
}
private TosRequest build(String method, InputStream stream) throws IOException {
TosRequest request = genTosRequest(method, stream);
if (this.skipTryResolveContentLength) {
request.setContentLength(this.contentLength);
} else if (request.getContent() != null) {
tryResolveContentLength(request);
}
Map headers = request.getHeaders();
if (headers != null && headers.size() > 0) {
tryEncodeHeaders(headers);
}
return request;
}
private void tryResolveContentLength(TosRequest request) {
if (this.contentLength >= 0) {
request.setContentLength(contentLength);
} else if (StringUtils.isNotEmpty(headers.get(TosHeader.HEADER_CONTENT_LENGTH))) {
try{
long cl = Long.parseLong(headers.get(TosHeader.HEADER_CONTENT_LENGTH));
request.setContentLength(cl >= 0 ? cl : -1L);
} catch (NumberFormatException e) {
TosUtils.getLogger().debug("tos: try to get content length from header failed, ", e);
request.setContentLength(-1L);
}
} else {
request.setContentLength(-1L);
}
if (request.getContent() instanceof FileInputStream && request.getContentLength() <= 0) {
// 文件流,尝试获取文件长度
try {
FileChannel channel = ((FileInputStream) request.getContent()).getChannel();
request.setContentLength(channel.size());
} catch (IOException e) {
TosUtils.getLogger().debug("tos: try to get content length from file failed, ", e);
request.setContentLength(-1L);
}
}
}
private void tryEncodeHeaders(Map headers) {
Map encodedHeaders = new HashMap<>();
Iterator> iterator = headers.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = iterator.next();
String key = entry.getKey();
String value = entry.getValue();
// 在此统一处理 header 的编码
if (StringUtils.isNotEmpty(key) && key.startsWith(TosHeader.HEADER_META_PREFIX)) {
if (this.disableEncodingMeta) {
encodedHeaders.put(key, value);
} else {
// 对于自定义元数据,对 key/value 包含的中文汉字进行 URL 编码
encodedHeaders.put(TosUtils.encodeHeader(key), TosUtils.encodeHeader(value));
}
iterator.remove();
} else if (StringUtils.equals(key, TosHeader.HEADER_CONTENT_DISPOSITION)) {
if (this.disableEncodingMeta) {
encodedHeaders.put(key, value);
} else {
// 对于 Content-Disposition 头,对 value 包含的中文汉字进行 URL 编码
encodedHeaders.put(key, TosUtils.encodeChinese(value));
}
iterator.remove();
}
}
headers.putAll(encodedHeaders);
}
private TosRequest genTosRequest(String method, InputStream stream) {
String[] hostAndPath = hostPath();
TosRequest request = new TosRequest(scheme, method, hostAndPath[0], hostAndPath[1], stream, query, headers);
if (this.port != 0) {
request.setPort(this.port);
}
return request;
}
private String[] hostPath(){
String[] hostAndPath = new String[]{"", ""};
if (urlMode == URL_MODE_CUSTOM_DOMAIN) {
hostAndPath[0] = this.host;
hostAndPath[1] = "/" + this.object;
} else if (urlMode == URL_MODE_PATH) {
hostAndPath[0] = this.host;
hostAndPath[1] = "/" + this.bucket + "/" + this.object;
} else if (StringUtils.isEmpty(this.bucket)){
hostAndPath[0] = this.host;
hostAndPath[1] = "/";
} else {
hostAndPath[0] = this.bucket+"."+this.host;
hostAndPath[1] = "/"+this.object;
}
return hostAndPath;
}
public TosRequest buildRequest(String method, InputStream stream) throws TosClientException {
TosRequest request;
try{
request = build(method, stream);
} catch (IOException e) {
throw new TosClientException("build tos request failed", e);
}
if(signer != null){
Map signed = this.signer.signHeader(request);
for (String key : signed.keySet()){
request.getHeaders().put(key, signed.get(key));
}
}
return request;
}
public TosRequest buildPreSignedUrlRequest(String method, long ttl) throws TosClientException {
TosRequest request = genTosRequest(method, null);
if (this.signer != null){
Map query = this.signer.signQuery(request, Duration.ofSeconds(ttl));
if (request.getQuery() == null) {
request.setQuery(new HashMap<>());
}
for (String key : query.keySet()){
request.getQuery().put(key, query.get(key));
}
}
return request;
}
public TosRequest buildRequestWithCopySource(String method, String srcBucket, String srcObject) throws TosClientException {
TosRequest request;
try{
request = build(method, null);
} catch (IOException e){
throw new TosClientException("build tos request failed", e);
}
String versionID = null;
if (request.getQuery() != null) {
versionID = request.getQuery().get("versionId");
request.getQuery().remove("versionId");
}
String cpSrcHeader = "";
try{
cpSrcHeader = copySource(srcBucket, srcObject, versionID);
} catch (UnsupportedEncodingException e) {
throw new TosClientException("object key encode exception", e);
}
request.getHeaders().put(TosHeader.HEADER_COPY_SOURCE, cpSrcHeader);
if(signer != null){
Map signed = this.signer.signHeader(request);
for (String key : signed.keySet()){
request.getHeaders().put(key, signed.get(key));
}
}
return request;
}
private String copySource(String bucket, String object, String versionID) throws UnsupportedEncodingException {
if (StringUtils.isEmpty(versionID)) {
return "/" + bucket + "/" + URLEncoder.encode(object, "UTF-8");
}
return "/" + bucket + "/" + URLEncoder.encode(object, "UTF-8") + "?versionId=" + versionID;
}
@Deprecated
public String preSignedURL(String method, Duration ttl) throws TosClientException {
TosRequest request;
try{
request = build(method, null);
} catch (IOException e){
throw new TosClientException("build tos request failed", e);
}
if (this.signer != null){
Map query = this.signer.signQuery(request, ttl);
for (String key : query.keySet()){
request.getQuery().put(key, query.get(key));
}
}
return request.toURL().toString();
}
}