Reputation:
Protocol-relative URLs aren't what I'm looking for. I'm looking for a way of absolutely specifying a protocol (http vs https) while keeping the host name of the url relative.
Given a relative URL such as "/SearchForStuff" I want to be able to specify a different protocol "https vs. http" etc. without having to specify a host/domain name.
Our site has a header partial view which we display across the top of every page on our site. Some pages on the site are http and some are https. The header contains a textbox and button for site-wide search. The site search results page is always provided using http, so we want the form action to point to a relative path, "/find". However, we want the same header to work on our many internal test servers (10.10.10.123 etc.) as well as our public facing server ("www.publicfacingserver.com"), ideally without changing the content of the header partial view. So essentially what I'm looking for is a way of specifying a protocol for the search action while keeping the server/host name relative.
Currently, to ensure that it is not possible for a user to link from a secured page to a secured page of site search results, we hard-code the absolute url of the action used for site search, complete with the protocol and host name, such as "http://www.publicsite.com/find". The problem is that clicking on that action on a test server redirects you back to our public-facing site. So for testing, we make manual edits to our hosts file for the test server's IP address to equal our public facing site name. This puts a bit of cognitive burden on ourselves as developers, and also requires us to visit the computer of any non-coding person who we wish to test our site to configure their hosts file prior to testing, and after testing to de-configure the changes to their hosts file.
The code below is the best solution I have come up with. Does anyone know of a better way? If my solution is adequate, does it create any security vulnerabilities? I don't see how it could, since if a malicious user were to forge a request to our public facing IP address X but with a host name in the host header which did not match that IP address, this would only result in wonky URLs being provided back to the same user. In other words, I don't see how anyone could use this to create an XSRF exploit by posting a URL in a message board on another site, or anything similar:
public static string CurrentHostName(this UrlHelper helper, HttpProtocol protocol)
{
var result = string.Empty;
if (protocol == HttpProtocol.Secure) result += "https://";
if (protocol == HttpProtocol.UnSecure) result += "http://";
if (protocol == HttpProtocol.Current) result += HttpContext.Current.Request.Url.Scheme;
result += HttpContext.Current.Request.Url.Host;
if (HttpContext.Current.Request.Url.Port != 80) result += ":" + HttpContext.Current.Request.Url.Port.ToString();
return result;
}
HttpProtocol is an enum that I created myself.
Thanks!
Upvotes: 11
Views: 6310
Reputation: 2528
BLUF (TL;DR;): Do it server side or with javascript as modern web needs to protect you.
The need for "specifying a protocol (http vs https) while keeping the host name of the url relative" was a common in the past, not sure how long ago. Today wikipedia shows this as valid and has been there since 2015. I have successfully done this for Chrome and other browsers in the past. But as of Chrome Version 130.0.6723.70 it results in a about:blank#blocked .
IAW RFC 1808 §2.2. BNF for Relative URLs it should be supported. It states:
generic-RL = scheme ":" relativeURL` relativeURL = ... | rel_path rel_path = [ path ] [ ";" params ] [ "?" query ]
Notes:
§2.3. Specific Schemes and their Syntactic Categories
We recommend that new schemes be designed to be parsable via the generic-RL syntax if they are intended to be used with relative URLs.
While RFC 1808 was happy with the scheme in a relative URL, a slightly older RFC 1630 was not:
The rules for the use of a partial name relative to the URI of the context are:
If the scheme parts are different, the whole absolute URI must be given. Otherwise, the scheme is omitted ...
Now RFC 1808 is obsoleted, and RFC 2396 §3.1. Scheme Component conflicts the previous BNF and generic-RL syntax recommendation when it states:
Relative URI references are distinguished from absolute URI in that they do not begin with a scheme name.
While the RFC details the specific intended changes from previous RFCs, these enumerations in §G.2. Modifications from both RFC 1738 and RFC 1808 and §G.4. Modifications from RFC 1808, do not explain why the ability to have a scheme name in a relative is now disallowed. We can even see a typical use case for allowing it in §1.2.3. Hierarchical Identifiers when it states:
It is often the case that a group or "tree" of documents has been constructed to serve a common purpose, wherein the vast majority of URI references in these documents point to resources within the tree rather than outside it. Similarly, documents located at a particular site are much more likely to refer to other resources at that site than to resources at remote sites. Relative referencing of URIs allows document trees to be partially independent of their location [e.g. authority] and access scheme. For instance, it is possible for a single set of hypertext documents to be simultaneously accessible and traversable via each of the "file", "http", and "ftp" schemes if the documents refer to each other with relative references.
Notes:
The most recent RFC 3986 §5.4.2. Abnormal Examples mentions the scheme SHOULD not be used in a relative context.
Some parsers allow the scheme name to be present in a relative reference if it is the same as the base URI scheme. This is considered to be a loophole in prior specifications of partial URI RFC1630. Its use should be avoided but is allowed for backward compatibility.
Lastly, this RFC seals the deal by disallowing scheme within a relative URI, and therefore relative URLs in Appendix A. Collected ABNF for URI
URI-reference = URI / relative-ref URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] relative-ref = relative-part [ "?" query ] [ "#" fragment ] relative-part = "//" authority path-abempty / path-absolute / path-noscheme / path-empty
In my opinion, the only compelling reason to no longer support this is not due to parsing, but for user safety. Ill quote §7. Security Considerations:
A URI does not in itself pose a security threat. ... care must be taken to properly interpret the data within a URI ... prevent ... data that should not be revealed in plain text
This is already addressed with solution like HSTS and is not a good reason to wholesale disallow scheme switching. The browser authors should be lobbied to support the RFC 1808 scheme switching relative URLs. Good reason to allow this are that client side processing (JavaScript) is wasteful and server side is contrary to CDN architectures.
Upvotes: 0
Reputation: 13
Warning: http:/path/filename gets interpreted differently on different browsers.
Firefox interprets the path as a path, but other browsers interpret 'path' as a servername.
Upvotes: 0
Reputation: 57085
I think you're asking for a URL format that's host relative rather that protocol relative. I don't think that's possible using any standard url formatting. For instance, http:/path/filename does not work for this.
Upvotes: 1