docs: public URL generatePresignedUrl(GeneratePresignedUrlRequest request) {
          checkNotNull(request, "The request parameter must be specified when generating a pre-signed URL");
  
          HttpMethodName httpMethod = HttpMethodName.valueOf(request.getMethod().toString());
  
          // If the key starts with a slash character itself, the following method
          // will actually add another slash before the resource path to prevent
          // the HttpClient mistakenly treating the slash as a path delimiter.
          // For presigned request, we need to remember to remove this extra slash
          // before generating the URL.
          String bucketName = ((BosClientConfiguration) this.config).isCnameEnabled() ? null : request.getBucketName();
          InternalRequest internalRequest = new InternalRequest(httpMethod, HttpUtils
                  .appendUri(this.getEndpoint(), URL_PREFIX, bucketName, request.getKey()));
          internalRequest.setCredentials(request.getRequestCredentials());
          SignOptions options = new SignOptions();
          options.setExpirationInSeconds(request.getExpiration());
  
          for (Entry<String, String> entry : request.getRequestHeaders().entrySet()) {
              if (entry.getValue() == null) {
                  internalRequest.addHeader(entry.getKey(), "");
              } else {
                  internalRequest.addHeader(entry.getKey(), entry.getValue());
              }
          }
  
          for (Entry<String, String> entry : request.getRequestParameters().entrySet()) {
              if (entry.getValue() == null) {
                  internalRequest.addParameter(entry.getKey(), "");
              } else {
                  internalRequest.addParameter(entry.getKey(), entry.getValue());
              }
          }
  
          if (request.getContentType() != null) {
              internalRequest.addHeader(Headers.CONTENT_TYPE, request.getContentType());
          }
  
          if (request.getContentMd5() != null) {
              internalRequest.addHeader(Headers.CONTENT_MD5, request.getContentMd5());
          }
  
          addResponseHeaderParameters(internalRequest, request.getResponseHeaders());
  
          Signer signer = new BceV1Signer();
          signer.sign(internalRequest, this.config.getCredentials(), options);
  
          // Remove the leading slash (if any) in the resource-path
          return convertRequestToUrl(internalRequest);
      }