public static HeaderSection CreateNew(string headersString) { headersString = HeaderField.CorrectObsFolding(headersString); var hs = new HeaderSection(); if (headersString.EndsWith(CRLF + CRLF)) { headersString = headersString.TrimEnd(CRLF, StringComparison.Ordinal); } using (var reader = new StringReader(headersString)) { while (true) { var field = reader.ReadLine(strictCRLF: true); if (field == null) { break; } else { hs.Fields.Add(HeaderField.CreateNew(field)); } } ValidateAndCorrectHeaders(hs); return(hs); } }
public static HeaderSection CreateNew(HttpHeaders headers) { var hs = new HeaderSection(); var message = new HttpRequestMessage(); foreach (var header in headers) { hs.Fields.Add(new HeaderField(header.Key, string.Join(",", header.Value))); } // -- Start [SECTION] Crazy VS2017/.NET Core 1.1 bug --- // The following if branch is needed as is to avoid the craziest VS2017/.NET Core 1.1 bug I have ever seen! // If this section is not added the Content-Length header will not be set unless... // - I put a break point at the start of the function // - And I explicitly expand the "headers" variable if (headers is HttpContentHeaders) { if (((HttpContentHeaders)headers).ContentLength != null) { if (hs.Fields.All(x => x.Name != "Content-Length")) { hs.Fields.Add(new HeaderField("Content-Length", ((HttpContentHeaders)headers).ContentLength.ToString())); } } } // -- End [SECTION] Crazy VS2017/.NET Core 1.1 bug --- return(hs); }
private static void ValidateAndCorrectHeaders(HeaderSection hs) { // https://tools.ietf.org/html/rfc7230#section-5.4 // Since the Host field - value is critical information for handling a // request, a user agent SHOULD generate Host as the first header field // following the request - line. HeaderField hostToCorrect = null; foreach (var f in hs.Fields) { // if we find host if (f.Name == "Host") { // if host is not first if (hs.Fields.First().Name != "Host") { // then correct host hostToCorrect = f; break; } } } if (hostToCorrect != null) { hs.Fields.Remove(hostToCorrect); hs.Fields.Insert(0, hostToCorrect); } // https://tools.ietf.org/html/rfc7230#section-3.3.2 // If a message is received that has multiple Content-Length header // fields with field-values consisting of the same decimal value, or a // single Content-Length header field with a field value containing a // list of identical decimal values(e.g., "Content-Length: 42, 42"), // indicating that duplicate Content-Length header fields have been // generated or combined by an upstream message processor, then the // recipient MUST either reject the message as invalid or replace the // duplicated field - values with a single valid Content - Length field // containing that decimal value prior to determining the message body // length or forwarding the message. var allParts = new HashSet <string>(); foreach (var field in hs.Fields) { if (field.Name == "Content-Length") { var parts = field.Value.Trim().Split(','); foreach (var part in parts) { allParts.Add(part.Trim()); } } } if (allParts.Count > 0) // then has Content-Length field { if (allParts.Count > 1) { throw new InvalidDataException("Invalid Content-Length."); } hs.Fields.RemoveAll(x => x.Name == "Content-Length"); hs.Fields.Add(new HeaderField("Content-Length", allParts.First())); } }