private string GetReasonPhrase(int statusCode) { string reasonPhrase = ReasonPhrase; if (string.IsNullOrWhiteSpace(reasonPhrase)) { // If the user hasn't set this then it is generated on the fly if possible. reasonPhrase = HttpReasonPhrase.Get(statusCode) ?? string.Empty; } return(reasonPhrase); }
public Task <Stream> UpgradeAsync() { if (!IsUpgradableRequest) { throw new InvalidOperationException("This request cannot be upgraded, it is incompatible."); } if (Response.HasStarted) { throw new InvalidOperationException("This request cannot be upgraded, the response has already started."); } // Set the status code and reason phrase Response.StatusCode = StatusCodes.Status101SwitchingProtocols; Response.ReasonPhrase = HttpReasonPhrase.Get(StatusCodes.Status101SwitchingProtocols); Response.SendOpaqueUpgrade(); // TODO: Async Request.SwitchToOpaqueMode(); Response.SwitchToOpaqueMode(); var opaqueStream = new OpaqueStream(Request.Body, Response.Body); return(Task.FromResult <Stream>(opaqueStream)); }
internal unsafe void SendError(ulong requestId, int httpStatusCode, IList <string> authChallenges = null) { HttpApiTypes.HTTP_RESPONSE_V2 httpResponse = new HttpApiTypes.HTTP_RESPONSE_V2(); httpResponse.Response_V1.Version = new HttpApiTypes.HTTP_VERSION(); httpResponse.Response_V1.Version.MajorVersion = (ushort)1; httpResponse.Response_V1.Version.MinorVersion = (ushort)1; List <GCHandle> pinnedHeaders = null; GCHandle gcHandle; try { // Copied from the multi-value headers section of SerializeHeaders if (authChallenges != null && authChallenges.Count > 0) { pinnedHeaders = new List <GCHandle>(); HttpApiTypes.HTTP_RESPONSE_INFO[] knownHeaderInfo = null; knownHeaderInfo = new HttpApiTypes.HTTP_RESPONSE_INFO[1]; gcHandle = GCHandle.Alloc(knownHeaderInfo, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); httpResponse.pResponseInfo = (HttpApiTypes.HTTP_RESPONSE_INFO *)gcHandle.AddrOfPinnedObject(); knownHeaderInfo[httpResponse.ResponseInfoCount].Type = HttpApiTypes.HTTP_RESPONSE_INFO_TYPE.HttpResponseInfoTypeMultipleKnownHeaders; knownHeaderInfo[httpResponse.ResponseInfoCount].Length = (uint)Marshal.SizeOf <HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS>(); HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS header = new HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS(); header.HeaderId = HttpApiTypes.HTTP_RESPONSE_HEADER_ID.Enum.HttpHeaderWwwAuthenticate; header.Flags = HttpApiTypes.HTTP_RESPONSE_INFO_FLAGS.PreserveOrder; // The docs say this is for www-auth only. HttpApiTypes.HTTP_KNOWN_HEADER[] nativeHeaderValues = new HttpApiTypes.HTTP_KNOWN_HEADER[authChallenges.Count]; gcHandle = GCHandle.Alloc(nativeHeaderValues, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); header.KnownHeaders = (HttpApiTypes.HTTP_KNOWN_HEADER *)gcHandle.AddrOfPinnedObject(); for (int headerValueIndex = 0; headerValueIndex < authChallenges.Count; headerValueIndex++) { // Add Value string headerValue = authChallenges[headerValueIndex]; byte[] bytes = HeaderEncoding.GetBytes(headerValue); nativeHeaderValues[header.KnownHeaderCount].RawValueLength = (ushort)bytes.Length; gcHandle = GCHandle.Alloc(bytes, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); nativeHeaderValues[header.KnownHeaderCount].pRawValue = (byte *)gcHandle.AddrOfPinnedObject(); header.KnownHeaderCount++; } // This type is a struct, not an object, so pinning it causes a boxed copy to be created. We can't do that until after all the fields are set. gcHandle = GCHandle.Alloc(header, GCHandleType.Pinned); pinnedHeaders.Add(gcHandle); knownHeaderInfo[0].pInfo = (HttpApiTypes.HTTP_MULTIPLE_KNOWN_HEADERS *)gcHandle.AddrOfPinnedObject(); httpResponse.ResponseInfoCount = 1; } httpResponse.Response_V1.StatusCode = (ushort)httpStatusCode; string statusDescription = HttpReasonPhrase.Get(httpStatusCode); uint dataWritten = 0; uint statusCode; byte[] byteReason = HeaderEncoding.GetBytes(statusDescription); fixed(byte *pReason = byteReason) { httpResponse.Response_V1.pReason = (byte *)pReason; httpResponse.Response_V1.ReasonLength = (ushort)byteReason.Length; byte[] byteContentLength = new byte[] { (byte)'0' }; fixed(byte *pContentLength = byteContentLength) { (&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].pRawValue = (byte *)pContentLength; (&httpResponse.Response_V1.Headers.KnownHeaders)[(int)HttpSysResponseHeader.ContentLength].RawValueLength = (ushort)byteContentLength.Length; httpResponse.Response_V1.Headers.UnknownHeaderCount = 0; statusCode = HttpApi.HttpSendHttpResponse( _requestQueue.Handle, requestId, 0, &httpResponse, null, &dataWritten, IntPtr.Zero, 0, SafeNativeOverlapped.Zero, IntPtr.Zero); } } if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { // if we fail to send a 401 something's seriously wrong, abort the request HttpApi.HttpCancelHttpRequest(_requestQueue.Handle, requestId, IntPtr.Zero); } } finally { if (pinnedHeaders != null) { foreach (GCHandle handle in pinnedHeaders) { if (handle.IsAllocated) { handle.Free(); } } } } }