| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- //Copyright 2010 Microsoft Corporation
- //
- //Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
- //You may obtain a copy of the License at
- //
- //http://www.apache.org/licenses/LICENSE-2.0
- //
- //Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
- //"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- //See the License for the specific language governing permissions and limitations under the License.
- namespace System.Data.Services.Http
- {
- #region Namespaces.
- using System;
- using System.Globalization;
- using System.IO;
- using System.Text;
- using System.Threading;
- using System.Windows.Browser;
- using System.Diagnostics;
- #endregion Namespaces.
- internal sealed class XHRHttpWebRequest : System.Data.Services.Http.HttpWebRequest
- {
- #region Private fields.
- private bool aborted;
- private HttpWebRequestAsyncResult asyncRequestResult;
- private HttpWebRequestAsyncResult asyncResponseResult;
- private NonClosingMemoryStream contentStream;
- private System.Data.Services.Http.XHRWebHeaderCollection headers;
- private bool invoked;
- private string method;
- private System.Data.Services.Http.HttpWebResponse response;
- private ScriptXmlHttpRequest underlyingRequest;
- private Uri uri;
- #endregion Private fields.
- internal XHRHttpWebRequest(Uri uri)
- {
- Debug.Assert(uri != null, "uri != null");
- this.uri = uri;
- }
- public override string Accept
- {
- get
- {
- return this.headers[System.Data.Services.Http.HttpRequestHeader.Accept];
- }
- set
- {
- this.headers.SetSpecialHeader("accept", value);
- }
- }
- public override long ContentLength
- {
- set
- {
- this.headers[System.Data.Services.Http.HttpRequestHeader.ContentLength] = value.ToString(CultureInfo.InvariantCulture);
- }
- }
- public override bool AllowReadStreamBuffering
- {
- get { return true; }
- set { }
- }
- public override string ContentType
- {
- get
- {
- return this.headers[System.Data.Services.Http.HttpRequestHeader.ContentType];
- }
- set
- {
- this.headers.SetSpecialHeader("content-type", value);
- }
- }
- public override System.Data.Services.Http.WebHeaderCollection Headers
- {
- get
- {
- if (this.headers == null)
- {
- this.headers = new System.Data.Services.Http.XHRWebHeaderCollection(System.Data.Services.Http.WebHeaderCollectionType.HttpWebRequest);
- }
- return this.headers;
- }
- }
- public override string Method
- {
- get { return this.method; }
- set { this.method = value; }
- }
- public override Uri RequestUri
- {
- get { return this.uri; }
- }
- public static bool IsAvailable()
- {
- try
- {
- ScriptXmlHttpRequest request = new ScriptXmlHttpRequest();
- return (null != request);
- }
- catch (WebException)
- {
- return false;
- }
- }
- public override void Abort()
- {
- this.aborted = true;
- if (this.underlyingRequest != null)
- {
- this.underlyingRequest.Abort();
- this.underlyingRequest.Dispose();
- this.underlyingRequest = null;
- }
- if (this.response != null)
- {
- ((XHRHttpWebResponse)this.response).InternalRequest = null;
- this.response = null;
- }
- this.Close();
- }
- public override IAsyncResult BeginGetRequestStream(AsyncCallback callback, object state)
- {
- if (this.aborted)
- {
- throw CreateAbortException();
- }
- if (this.contentStream == null)
- {
- this.contentStream = new NonClosingMemoryStream();
- }
- else
- {
- this.contentStream.Seek(0L, SeekOrigin.Begin);
- }
-
- HttpWebRequestAsyncResult asyncResult = new HttpWebRequestAsyncResult(callback, state);
- this.asyncRequestResult = asyncResult;
- this.asyncRequestResult.CompletedSynchronously = true;
- if (asyncResult != null)
- {
- asyncResult.SetCompleted();
- asyncResult.Callback(asyncResult);
- }
-
- return asyncResult;
- }
- public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
- {
- HttpWebRequestAsyncResult asyncResult = new HttpWebRequestAsyncResult(callback, state);
- try
- {
- asyncResult.InsideBegin = true;
- this.asyncResponseResult = asyncResult;
- this.InvokeRequest();
- }
- finally
- {
- asyncResult.InsideBegin = false;
- }
- return asyncResult;
- }
- public override Stream EndGetRequestStream(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- {
- throw new ArgumentNullException("asyncResult");
- }
-
- if (this.asyncRequestResult != asyncResult)
- {
- throw new InvalidOperationException(
- System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebRequest.EndGetRequestStream"));
- }
-
- if (this.asyncRequestResult.EndCalled)
- {
- throw new InvalidOperationException(
- System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebRequest.EndGetRequestStream.2"));
- }
-
- if (this.aborted)
- {
- throw CreateAbortException();
- }
- this.asyncRequestResult.EndCalled = true;
- this.asyncRequestResult.Dispose();
- this.asyncRequestResult = null;
- return this.contentStream;
- }
- public override System.Data.Services.Http.WebResponse EndGetResponse(IAsyncResult asyncResult)
- {
- if (asyncResult == null)
- {
- throw new ArgumentNullException("asyncResult");
- }
- if (this.asyncResponseResult != asyncResult)
- {
- throw new InvalidOperationException(
- System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebRequest.EndGetResponse"));
- }
-
- if (this.asyncResponseResult.EndCalled)
- {
- throw new InvalidOperationException(
- System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebRequest.EndGetResponse.2"));
- }
-
- if (this.aborted)
- {
- throw CreateAbortException();
- }
- this.asyncResponseResult.EndCalled = true;
- this.CreateResponse();
- this.asyncResponseResult.Dispose();
- this.asyncResponseResult = null;
- return this.response;
- }
- public override System.Net.WebHeaderCollection CreateEmptyWebHeaderCollection()
- {
- return System.Net.WebRequest.Create(this.RequestUri).Headers;
- }
- internal void Close()
- {
- this.Dispose(true);
- }
- internal Stream ReadResponse(IDisposable connection)
- {
- Debug.Assert(connection != null, "connection != null");
- if ((this.response.ContentType == null) ||
- this.response.ContentType.Contains("json") ||
- this.response.ContentType.Contains("xml") ||
- this.response.ContentType.Contains("text") ||
- this.response.ContentType.Contains("multipart"))
- {
- string buffer = this.underlyingRequest.ReadResponseAsString();
- return (!string.IsNullOrEmpty(buffer) ? new DisposingMemoryStream(connection, Encoding.UTF8.GetBytes(buffer)) : null);
- }
- throw WebException.CreateInternal("HttpWebRequest.ReadResponse");
- }
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this.contentStream != null)
- {
- this.contentStream.InternalDispose();
- this.contentStream = null;
- }
- }
- }
- private static System.Data.Services.Http.WebException CreateAbortException()
- {
- return new System.Data.Services.Http.WebException(System.Data.Services.Client.Strings.HttpWebRequest_Aborted);
- }
- private void CreateResponse()
- {
- int statusCode;
- this.underlyingRequest.GetResponseStatus(out statusCode);
- if (statusCode != -1)
- {
- string responseHeaders = this.underlyingRequest.GetResponseHeaders();
- this.response = new System.Data.Services.Http.XHRHttpWebResponse(this, statusCode, responseHeaders);
- }
- }
- private void ReadyStateChanged()
- {
- if (this.underlyingRequest.IsCompleted && (this.asyncResponseResult != null))
- {
- try
- {
- if (this.asyncResponseResult.InsideBegin)
- {
- this.asyncResponseResult.CompletedSynchronously = true;
- }
- this.asyncResponseResult.SetCompleted();
- this.asyncResponseResult.Callback(this.asyncResponseResult);
- }
- finally
- {
- this.underlyingRequest.Dispose();
- }
- }
- }
- private void InvokeRequest()
- {
- if (this.aborted)
- {
- throw CreateAbortException();
- }
- if (this.invoked)
- {
- throw new InvalidOperationException(
- System.Data.Services.Client.Strings.HttpWeb_Internal("HttpWebRequest.InvokeRequest"));
- }
- this.invoked = true;
- this.underlyingRequest = new ScriptXmlHttpRequest();
- this.underlyingRequest.Open(this.uri.AbsoluteUri, this.Method, (Action)this.ReadyStateChanged);
- if ((this.headers != null) && (this.headers.Count != 0))
- {
- foreach (string header in this.headers.AllKeys)
- {
- string value = this.headers[header];
- this.underlyingRequest.SetRequestHeader(header, value);
- }
- }
- string content = null;
- if (this.contentStream != null)
- {
- byte[] buf = this.contentStream.GetBuffer();
- if (buf != null)
- {
- int bufferSize = checked((int)this.contentStream.Position);
- content = Encoding.UTF8.GetString(buf, 0, bufferSize);
- this.underlyingRequest.SetRequestHeader("content-length", bufferSize.ToString(CultureInfo.InvariantCulture));
- }
- }
- this.underlyingRequest.Send(content);
- }
- private sealed class HttpWebRequestAsyncResult : IAsyncResult, IDisposable
- {
- private AsyncCallback callback;
- private bool completed;
- private bool completedSynchronously;
- private bool endCalled;
- private object state;
- private ManualResetEvent waitHandle;
- public HttpWebRequestAsyncResult(AsyncCallback callback, object state)
- {
- this.callback = callback;
- this.state = state;
- }
- public object AsyncState
- {
- get { return this.state; }
- }
- public WaitHandle AsyncWaitHandle
- {
- get
- {
- if (this.waitHandle == null)
- {
- this.waitHandle = new ManualResetEvent(false);
- }
- return this.waitHandle;
- }
- }
- public AsyncCallback Callback
- {
- get { return this.callback; }
- }
- public bool CompletedSynchronously
- {
- get
- {
- return this.completedSynchronously;
- }
- internal set
- {
- this.completedSynchronously = value;
- }
- }
- public bool EndCalled
- {
- get { return this.endCalled; }
- set { this.endCalled = value; }
- }
- public bool IsCompleted
- {
- get { return this.completed; }
- }
- public bool InsideBegin
- {
- get;
- set;
- }
- public void Dispose()
- {
- if (this.waitHandle != null)
- {
- ((IDisposable)this.waitHandle).Dispose();
- }
- }
- public void SetCompleted()
- {
- this.completed = true;
- if (this.waitHandle != null)
- {
- this.waitHandle.Set();
- }
- }
- }
- private sealed class DisposingMemoryStream : MemoryStream
- {
- private readonly IDisposable disposable;
- internal DisposingMemoryStream(IDisposable disposable, byte[] buffer) : base(buffer)
- {
- Debug.Assert(disposable != null, "disposable != null");
- this.disposable = disposable;
- }
- protected override void Dispose(bool disposing)
- {
- this.disposable.Dispose();
- base.Dispose(disposing);
- }
- }
- private sealed class NonClosingMemoryStream : MemoryStream
- {
- public override void Close()
- {
-
- }
- internal void InternalDispose()
- {
- base.Dispose();
- }
- protected override void Dispose(bool disposing)
- {
- }
- }
- }
- }
|