You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
4.8 KiB
129 lines
4.8 KiB
/*
|
|
* MinIO .NET Library for Amazon S3 Compatible Cloud Storage, (C) 2017 MinIO, Inc.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
using System.Globalization;
|
|
using System.Text.RegularExpressions;
|
|
using System.Web;
|
|
using Minio.Exceptions;
|
|
|
|
namespace Minio.Helper;
|
|
|
|
internal static class RequestUtil
|
|
{
|
|
internal static Uri GetEndpointURL(string endPoint, bool secure)
|
|
{
|
|
if (endPoint.Contains(':', StringComparison.Ordinal))
|
|
{
|
|
var parts = endPoint.Split(':');
|
|
var host = parts[0];
|
|
//var port = parts[1];
|
|
if (!S3utils.IsValidIP(host) && !IsValidEndpoint(host))
|
|
throw new InvalidEndpointException("Endpoint: " + endPoint +
|
|
" does not follow ip address or domain name standards.");
|
|
}
|
|
else
|
|
{
|
|
if (!S3utils.IsValidIP(endPoint) && !IsValidEndpoint(endPoint))
|
|
throw new InvalidEndpointException("Endpoint: " + endPoint +
|
|
" does not follow ip address or domain name standards.");
|
|
}
|
|
|
|
var uri = TryCreateUri(endPoint, secure);
|
|
ValidateEndpoint(uri, endPoint);
|
|
return uri;
|
|
}
|
|
|
|
internal static Uri MakeTargetURL(string endPoint, bool secure, string bucketName = null, string region = null,
|
|
bool usePathStyle = true)
|
|
{
|
|
// For Amazon S3 endpoint, try to fetch location based endpoint.
|
|
var host = endPoint;
|
|
if (S3utils.IsAmazonEndPoint(endPoint) && !string.IsNullOrEmpty(region))
|
|
host = $"s3.{region}.amazonaws.com";
|
|
|
|
if (!usePathStyle)
|
|
{
|
|
var suffix = bucketName is not null ? bucketName + "/" : "";
|
|
host = host + "/" + suffix;
|
|
}
|
|
|
|
var scheme = secure ? "https" : "http";
|
|
var endpointURL = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", scheme, host);
|
|
return new Uri(endpointURL, UriKind.Absolute);
|
|
}
|
|
|
|
internal static Uri TryCreateUri(string endpoint, bool secure)
|
|
{
|
|
var scheme = secure ? HttpUtility.UrlEncode("https") : HttpUtility.UrlEncode("http");
|
|
|
|
// This is the actual url pointed to for all HTTP requests
|
|
var endpointURL = string.Format(CultureInfo.InvariantCulture, "{0}://{1}", scheme, endpoint);
|
|
Uri uri;
|
|
try
|
|
{
|
|
uri = new Uri(endpointURL);
|
|
}
|
|
catch (UriFormatException e)
|
|
{
|
|
throw new InvalidEndpointException(e.Message);
|
|
}
|
|
|
|
return uri;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validates URI to check if it is well formed. Otherwise cry foul.
|
|
/// </summary>
|
|
internal static void ValidateEndpoint(Uri uri, string endpoint)
|
|
{
|
|
if (string.IsNullOrEmpty(uri.OriginalString)) throw new InvalidEndpointException("Endpoint cannot be empty.");
|
|
|
|
if (!IsValidEndpoint(uri.Host)) throw new InvalidEndpointException(endpoint, "Invalid endpoint.");
|
|
if (!uri.AbsolutePath.Equals("/", StringComparison.OrdinalIgnoreCase))
|
|
throw new InvalidEndpointException(endpoint, "No path allowed in endpoint.");
|
|
|
|
if (!string.IsNullOrEmpty(uri.Query))
|
|
throw new InvalidEndpointException(endpoint, "No query parameter allowed in endpoint.");
|
|
if (!uri.Scheme.ToUpperInvariant().Equals("https", StringComparison.OrdinalIgnoreCase) &&
|
|
!uri.Scheme.ToUpperInvariant().Equals("http", StringComparison.OrdinalIgnoreCase))
|
|
throw new InvalidEndpointException(endpoint, "Invalid scheme detected in endpoint.");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validate Url endpoint
|
|
/// </summary>
|
|
/// <param name="endpoint"></param>
|
|
/// <returns>true/false</returns>
|
|
internal static bool IsValidEndpoint(string endpoint)
|
|
{
|
|
// endpoint may be a hostname
|
|
// refer https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
|
|
// why checks are as shown below.
|
|
if (endpoint.Length is < 1 or > 253) return false;
|
|
|
|
foreach (var label in endpoint.Split('.'))
|
|
{
|
|
if (label.Length is < 1 or > 63) return false;
|
|
|
|
var validLabel = new Regex("^[a-zA-Z0-9]([A-Za-z0-9-_]*[a-zA-Z0-9])?$", RegexOptions.ExplicitCapture,
|
|
TimeSpan.FromHours(1));
|
|
|
|
if (!validLabel.IsMatch(label)) return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|