I'm looking for canonical way of changing scheme of a given System.Uri instance with System.UriBuilder without crappy string manipulations and magic constants. Say I have
var uri = new Uri("http://localhost/hello")
and I need to change it to 'https'. My issue is in limited UriBuilder
ctors and Uri.Port
defaulting to 80 (should we change it to 443? hardcoding?). The code must respect all Uri
properties such as possible basic auth credentials, query string, etc.
A URI is a compact representation of a resource available to your application on the intranet or internet. The Uri class defines the properties and methods for handling URIs, including parsing, comparing, and combining. The Uri class properties are read-only; to create a modifiable object, use the UriBuilder class.
A scheme is a systematic plan for a data structure. A URI does not contain a protocol but does contain a scheme [1]. A scheme can be associated with a protocol but does not have to. E.g. the http: scheme is associated with the HTTP/1.0 or 1.1 protocol [2] but the file: scheme is not associated with any protocol.
Uri(String, UriKind) Initializes a new instance of the Uri class with the specified URI. This constructor allows you to specify if the URI string is a relative URI, absolute URI, or is indeterminate. public: Uri(System::String ^ uriString, UriKind uriKind); C# Copy.
A URI is a string containing characters that identify a physical or logical resource. URI follows syntax rules to ensure uniformity. Moreover, it also maintains extensibility via a hierarchical naming scheme. The full form of URI is Uniform Resource Identifier.
Ended up with this one:
var uriBuilder = new UriBuilder(requestUrl)
{
Scheme = Uri.UriSchemeHttps,
Port = -1 // default port for scheme
};
var uri = uriBuilder.Uri;
UserControl's answer works fine unless you have to make sure non-default ports are preserved in the URI.
For instance, http://localhost:12345/hello
should become https://localhost:12345/hello
instead of https://localhost/hello
.
Here's how to do that easily:
public static string ForceHttps(string requestUrl)
{
var uri = new UriBuilder(requestUrl);
var hadDefaultPort = uri.Uri.IsDefaultPort;
uri.Scheme = Uri.UriSchemeHttps;
uri.Port = hadDefaultPort ? -1 : uri.Port;
return uri.ToString();
}
Note that we have to read uri.Uri.IsDefaultPort
before setting uri.Scheme
.
Here is a working example: https://dotnetfiddle.net/pDrF7s
Another iteration on Good Night Nerd Pride's answer, as an extension:
public static Uri RewriteHttps(this Uri originalUri)
{
return new UriBuilder(originalUri)
{
Scheme = Uri.UriSchemeHttps,
Port = originalUri.IsDefaultPort ? -1 : originalUri.Port // -1 => default port for scheme
}.Uri;
}
I prefer to pass the desired https port number into the ForceHttps method if you want to use a custom one otherwise omit the https port or use -1 to use the standard one (implicitly). I don't really bother with the port that is already on the url because http and https can never use the same port on the same server.
In the event that the url is already https, it will pass through unchanged leaving whatever port is there in place.
private static string ForceHttps(string requestUrl, int? httpsPort = null)
{
var uri = new UriBuilder(requestUrl);
// Handle https: let the httpsPort value override existing port if specified
if (uri.Uri.Scheme.Equals(Uri.UriSchemeHttps)) {
if (httpsPort.HasValue)
uri.Port = httpsPort.Value;
return uri.Uri.AbsoluteUri;
}
// Handle http: override the scheme and use either the specified https port or the default https port
uri.Scheme = Uri.UriSchemeHttps;
uri.Port = httpsPort.HasValue ? httpsPort.Value : -1;
return uri.Uri.AbsoluteUri;
}
Usage:
ForceHttps("http://www.google.com/"); // https://www.google.com/
ForceHttps("http://www.google.com/", 225); // https://www.google.com:225/
ForceHttps("http://www.google.com/", 443); // https://www.google.com:443/
ForceHttps("https://www.google.com/"); // https://www.google.com/
ForceHttps("https://www.google.com:443/"); // https://www.google.com:443/
ForceHttps("https://www.google.com:443/", -1); // https://www.google.com/
ForceHttps("http://www.google.com:80/"); // https://www.google.com/
ForceHttps("http://www.google.com:3000/", 8080); // https://www.google.com:8080/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With