public async Task Request_MultiplePrefixes(string requestUri, string expectedPathBase, string expectedPath) { // TODO: We're just doing this to get a dynamic port. This can be removed later when we add support for hot-adding prefixes. string root; var server = Utilities.CreateHttpServerReturnRoot("/", out root); server.Dispose(); server = new WebListener(); using (server) { var uriBuilder = new UriBuilder(root); foreach (string path in new[] { "/", "/11", "/2/3", "/2", "/11/2" }) { server.UrlPrefixes.Add(UrlPrefix.Create(uriBuilder.Scheme, uriBuilder.Host, uriBuilder.Port, path)); } server.Start(); Task <string> responseTask = SendRequestAsync(root + requestUri); var context = await server.GetContextAsync(); var request = context.Request; Assert.Equal(expectedPath, request.Path); Assert.Equal(expectedPathBase, request.PathBase); context.Dispose(); string response = await responseTask; Assert.Equal(string.Empty, response); } }
internal static WebListener CreateDynamicHttpServer(string basePath, out string root, out string baseAddress) { lock (PortLock) { while (NextPort < MaxPort) { var port = NextPort++; var prefix = UrlPrefix.Create("http", "localhost", port, basePath); root = prefix.Scheme + "://" + prefix.Host + ":" + prefix.Port; baseAddress = prefix.ToString(); var listener = new WebListener(); listener.UrlPrefixes.Add(prefix); try { listener.Start(); return(listener); } catch (WebListenerException) { listener.Dispose(); } } NextPort = BasePort; } throw new Exception("Failed to locate a free port."); }
internal static WebListener CreateServer(string scheme, string host, int port, string path) { WebListener listener = new WebListener(); listener.UrlPrefixes.Add(UrlPrefix.Create(scheme, host, port, path)); listener.Start(); return(listener); }
/// <summary> /// http://msdn.microsoft.com/en-us/library/windows/desktop/aa364698(v=vs.85).aspx /// </summary> /// <param name="scheme">http or https. Will be normalized to lower case.</param> /// <param name="host">+, *, IPv4, [IPv6], or a dns name. Http.Sys does not permit punycode (xn--), use Unicode instead.</param> /// <param name="port">If empty, the default port for the given scheme will be used (80 or 443).</param> /// <param name="path">Should start and end with a '/', though a missing trailing slash will be added. This value must be un-escaped.</param> public static UrlPrefix Create(string scheme, string host, string port, string path) { int?portValue = null; if (!string.IsNullOrWhiteSpace(port)) { portValue = int.Parse(port, NumberStyles.None, CultureInfo.InvariantCulture); } return(UrlPrefix.Create(scheme, host, portValue, path)); }
public static UrlPrefix Create(string prefix) { string scheme = null; string host = null; int? port = null; string path = null; string whole = prefix ?? string.Empty; int delimiterStart1 = whole.IndexOf("://", StringComparison.Ordinal); if (delimiterStart1 < 0) { int aPort; if (int.TryParse(whole, NumberStyles.None, CultureInfo.InvariantCulture, out aPort)) { return(UrlPrefix.Create("http", "localhost", aPort, "/")); } throw new FormatException("Invalid prefix, missing scheme separator: " + prefix); } int delimiterEnd1 = delimiterStart1 + "://".Length; int delimiterStart3 = whole.IndexOf("/", delimiterEnd1, StringComparison.Ordinal); if (delimiterStart3 < 0) { delimiterStart3 = whole.Length; } int delimiterStart2 = whole.LastIndexOf(":", delimiterStart3 - 1, delimiterStart3 - delimiterEnd1, StringComparison.Ordinal); int delimiterEnd2 = delimiterStart2 + ":".Length; if (delimiterStart2 < 0) { delimiterStart2 = delimiterStart3; delimiterEnd2 = delimiterStart3; } scheme = whole.Substring(0, delimiterStart1); string portString = whole.Substring(delimiterEnd2, delimiterStart3 - delimiterEnd2); int portValue; if (int.TryParse(portString, NumberStyles.Integer, CultureInfo.InvariantCulture, out portValue)) { host = whole.Substring(delimiterEnd1, delimiterStart2 - delimiterEnd1); port = portValue; } else { host = whole.Substring(delimiterEnd1, delimiterStart3 - delimiterEnd1); } path = whole.Substring(delimiterStart3); return(UrlPrefix.Create(scheme, host, port, path)); }
internal unsafe Request(RequestContext httpContext, NativeRequestContext memoryBlob) { // TODO: Verbose log _requestContext = httpContext; _nativeRequestContext = memoryBlob; _contentBoundaryType = BoundaryType.None; // Set up some of these now to avoid refcounting on memory blob later. _requestId = memoryBlob.RequestBlob->RequestId; _connectionId = memoryBlob.RequestBlob->ConnectionId; _contextId = memoryBlob.RequestBlob->UrlContext; _sslStatus = memoryBlob.RequestBlob->pSslInfo == null ? SslStatus.Insecure : memoryBlob.RequestBlob->pSslInfo->SslClientCertNegotiated == 0 ? SslStatus.NoClientCert : SslStatus.ClientCert; if (memoryBlob.RequestBlob->pRawUrl != null && memoryBlob.RequestBlob->RawUrlLength > 0) { _rawUrl = Marshal.PtrToStringAnsi((IntPtr)memoryBlob.RequestBlob->pRawUrl, memoryBlob.RequestBlob->RawUrlLength); } UnsafeNclNativeMethods.HttpApi.HTTP_COOKED_URL cookedUrl = memoryBlob.RequestBlob->CookedUrl; if (cookedUrl.pHost != null && cookedUrl.HostLength > 0) { _cookedUrlHost = Marshal.PtrToStringUni((IntPtr)cookedUrl.pHost, cookedUrl.HostLength / 2); } if (cookedUrl.pAbsPath != null && cookedUrl.AbsPathLength > 0) { _cookedUrlPath = Marshal.PtrToStringUni((IntPtr)cookedUrl.pAbsPath, cookedUrl.AbsPathLength / 2); } if (cookedUrl.pQueryString != null && cookedUrl.QueryStringLength > 0) { _cookedUrlQuery = Marshal.PtrToStringUni((IntPtr)cookedUrl.pQueryString, cookedUrl.QueryStringLength / 2); } UrlPrefix prefix = httpContext.Server.UrlPrefixes.GetPrefix((int)_contextId); string originalPath = RequestPath; // These paths are both unescaped already. if (originalPath.Length == prefix.Path.Length - 1) { // They matched exactly except for the trailing slash. _pathBase = originalPath; _path = string.Empty; } else { // url: /base/path, prefix: /base/, base: /base, path: /path // url: /, prefix: /, base: , path: / _pathBase = originalPath.Substring(0, prefix.Path.Length - 1); _path = originalPath.Substring(prefix.Path.Length - 1); } int major = memoryBlob.RequestBlob->Version.MajorVersion; int minor = memoryBlob.RequestBlob->Version.MinorVersion; if (major == 1 && minor == 1) { _httpVersion = Constants.V1_1; } else if (major == 1 && minor == 0) { _httpVersion = Constants.V1_0; } else { _httpVersion = new Version(major, minor); } _httpMethod = UnsafeNclNativeMethods.HttpApi.GetVerb(RequestBuffer, OriginalBlobAddress); _headers = new HeaderCollection(new RequestHeaders(_nativeRequestContext)); var requestV2 = (UnsafeNclNativeMethods.HttpApi.HTTP_REQUEST_V2 *)memoryBlob.RequestBlob; _user = AuthenticationManager.GetUser(requestV2->pRequestInfo, requestV2->RequestInfoCount); GetTlsTokenBindingInfo(); // TODO: Verbose log parameters }