e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
207 lines
8.0 KiB
C#
207 lines
8.0 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="HttpHeaderCollection.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
/*
|
|
* Collection of headers with write through to IIS for Set, Add, and Remove
|
|
*
|
|
* Copyright (c) 2000 Microsoft Corporation
|
|
*/
|
|
|
|
namespace System.Web {
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Globalization;
|
|
using System.Security.Permissions;
|
|
using System.Runtime.Serialization;
|
|
using System.Web.Hosting;
|
|
using System.Web.Util;
|
|
|
|
[Serializable()]
|
|
internal class HttpHeaderCollection : HttpValueCollection {
|
|
private HttpRequest _request;
|
|
private HttpResponse _response;
|
|
private IIS7WorkerRequest _iis7WorkerRequest;
|
|
|
|
|
|
// This constructor creates the header collection for request headers.
|
|
// Try to preallocate the base collection with a size that should be sufficient
|
|
// to store the headers for most requests.
|
|
internal HttpHeaderCollection(HttpWorkerRequest wr, HttpRequest request, int capacity) : base(capacity) {
|
|
|
|
// if this is an IIS7WorkerRequest, then the collection will be writeable and we will
|
|
// call into IIS7 to update the header blocks when changes are made.
|
|
_iis7WorkerRequest = wr as IIS7WorkerRequest;
|
|
|
|
_request = request;
|
|
}
|
|
|
|
// This constructor creates the header collection for response headers.
|
|
// Try to preallocate the base collection with a size that should be sufficient
|
|
// to store the headers for most requests.
|
|
internal HttpHeaderCollection(HttpWorkerRequest wr, HttpResponse response, int capacity) : base(capacity) {
|
|
|
|
// if this is an IIS7WorkerRequest, then the collection will be writeable and we will
|
|
// call into IIS7 to update the header blocks when changes are made.
|
|
_iis7WorkerRequest = wr as IIS7WorkerRequest;
|
|
|
|
_response = response;
|
|
}
|
|
|
|
// This copy constructor is used by the granular request validation feature. Since these collections are immutable
|
|
// once created, it's ok for us to have two collections containing the same data.
|
|
internal HttpHeaderCollection(HttpHeaderCollection col)
|
|
: base(col) {
|
|
|
|
_request = col._request;
|
|
_response = col._response;
|
|
_iis7WorkerRequest = col._iis7WorkerRequest;
|
|
}
|
|
|
|
[SecurityPermissionAttribute(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)]
|
|
public override void GetObjectData(SerializationInfo info, StreamingContext context) {
|
|
// WOS 127340: Request.Headers and Response.Headers are no longer serializable
|
|
base.GetObjectData(info, context);
|
|
// create an instance of HttpValueCollection since HttpHeaderCollection is tied to the request
|
|
info.SetType(typeof(HttpValueCollection));
|
|
}
|
|
|
|
public override void Add(String name, String value) {
|
|
if (_iis7WorkerRequest == null) {
|
|
throw new PlatformNotSupportedException();
|
|
}
|
|
// append to existing value
|
|
SetHeader(name, value, false /*replace*/);
|
|
}
|
|
|
|
public override void Clear() {
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
internal void ClearInternal() {
|
|
// clear is only supported for response headers
|
|
if (_request != null) {
|
|
throw new NotSupportedException();
|
|
}
|
|
base.Clear();
|
|
}
|
|
|
|
public override void Set(String name, String value) {
|
|
if (_iis7WorkerRequest == null) {
|
|
throw new PlatformNotSupportedException();
|
|
}
|
|
// set new value
|
|
SetHeader(name, value, true /*replace*/);
|
|
}
|
|
|
|
internal void SetHeader(String name, String value, bool replace) {
|
|
Debug.Assert(_iis7WorkerRequest != null, "_iis7WorkerRequest != null");
|
|
|
|
if (name == null) {
|
|
throw new ArgumentNullException("name");
|
|
}
|
|
|
|
if (value == null) {
|
|
throw new ArgumentNullException("value");
|
|
}
|
|
|
|
if (_request != null) {
|
|
_iis7WorkerRequest.SetRequestHeader(name, value, replace);
|
|
}
|
|
else {
|
|
if (_response.HeadersWritten) {
|
|
throw new HttpException(SR.GetString(SR.Cannot_append_header_after_headers_sent));
|
|
}
|
|
|
|
// IIS7 integrated pipeline mode needs to call the header encoding routine explicitly since it
|
|
// doesn't go through HttpResponse.WriteHeaders().
|
|
string encodedName = name;
|
|
string encodedValue = value;
|
|
if (HttpRuntime.EnableHeaderChecking) {
|
|
HttpEncoder.Current.HeaderNameValueEncode(name, value, out encodedName, out encodedValue);
|
|
}
|
|
|
|
// set the header encoding to the selected encoding
|
|
_iis7WorkerRequest.SetHeaderEncoding(_response.HeaderEncoding);
|
|
|
|
_iis7WorkerRequest.SetResponseHeader(encodedName, encodedValue, replace);
|
|
|
|
if (_response.HasCachePolicy && StringUtil.EqualsIgnoreCase("Set-Cookie", name)) {
|
|
_response.Cache.SetHasSetCookieHeader();
|
|
}
|
|
}
|
|
|
|
// update managed copy of header
|
|
if (replace) {
|
|
base.Set(name, value);
|
|
}
|
|
else {
|
|
base.Add(name, value);
|
|
}
|
|
|
|
if (_request != null) {
|
|
// update managed copy of server variable
|
|
string svValue = replace ? value : base.Get(name);
|
|
HttpServerVarsCollection serverVars = _request.ServerVariables as HttpServerVarsCollection;
|
|
if (serverVars != null) {
|
|
serverVars.SynchronizeServerVariable("HTTP_" + name.ToUpper(CultureInfo.InvariantCulture).Replace('-', '_'), svValue, ensurePopulated: false);
|
|
}
|
|
|
|
// invalidate Params collection
|
|
_request.InvalidateParams();
|
|
}
|
|
}
|
|
|
|
// updates managed copy of header with current value from native header block
|
|
internal void SynchronizeHeader(String name, String value) {
|
|
if (name == null) {
|
|
throw new ArgumentNullException("name");
|
|
}
|
|
|
|
if (value != null) {
|
|
base.Set(name, value);
|
|
}
|
|
else {
|
|
base.Remove(name);
|
|
}
|
|
|
|
if (_request != null) {
|
|
_request.InvalidateParams();
|
|
}
|
|
}
|
|
|
|
public override void Remove(String name) {
|
|
if (_iis7WorkerRequest == null) {
|
|
throw new PlatformNotSupportedException();
|
|
}
|
|
|
|
if (name == null) {
|
|
throw new ArgumentNullException("name");
|
|
}
|
|
|
|
if (_request != null) {
|
|
// delete by sending null value
|
|
_iis7WorkerRequest.SetRequestHeader(name, null /*value*/, false /*replace*/);
|
|
}
|
|
else {
|
|
_iis7WorkerRequest.SetResponseHeader(name, null /*value*/, false /*replace*/);
|
|
}
|
|
|
|
base.Remove(name);
|
|
if (_request != null) {
|
|
// update managed copy of server variable
|
|
HttpServerVarsCollection serverVars = _request.ServerVariables as HttpServerVarsCollection;
|
|
if (serverVars != null) {
|
|
serverVars.SynchronizeServerVariable("HTTP_" + name.ToUpper(CultureInfo.InvariantCulture).Replace('-', '_'), null, ensurePopulated: false);
|
|
}
|
|
|
|
// invalidate Params collection
|
|
_request.InvalidateParams();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|