359 lines
8.8 KiB
C#
Raw Normal View History

//
// HttpContextInfo.cs
//
// Author:
// Atsushi Enomoto <atsushi@ximian.com>
//
// Copyright (C) 2010 Novell, Inc. http://www.novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Net;
using System.Security.Principal;
using System.ServiceModel;
using System.Text;
using System.Threading;
using System.Web;
namespace System.ServiceModel.Channels.Http
{
// Context
abstract class HttpContextInfo
{
public abstract HttpRequestInfo Request { get; }
public abstract HttpResponseInfo Response { get; }
public abstract string User { get; }
public abstract string Password { get; }
public abstract void ReturnUnauthorized ();
public void Abort ()
{
Response.Abort ();
OnContextClosed ();
}
public void Close ()
{
Response.Close ();
OnContextClosed ();
}
protected virtual void OnContextClosed ()
{
}
}
class HttpStandaloneContextInfo : HttpContextInfo
{
public HttpStandaloneContextInfo (HttpListenerContext ctx)
{
this.ctx = ctx;
request = new HttpStandaloneRequestInfo (ctx.Request);
response = new HttpStandaloneResponseInfo (ctx.Response);
}
HttpListenerContext ctx;
HttpStandaloneRequestInfo request;
HttpStandaloneResponseInfo response;
public HttpListenerContext Source {
get { return ctx; }
}
public override HttpRequestInfo Request {
get { return request; }
}
public override HttpResponseInfo Response {
get { return response; }
}
public override string User {
get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Name : null; }
}
public override string Password {
get { return ctx.User != null ? ((HttpListenerBasicIdentity) ctx.User.Identity).Password : null; }
}
public override void ReturnUnauthorized ()
{
ctx.Response.StatusCode = 401;
}
}
class AspNetHttpContextInfo : HttpContextInfo
{
public AspNetHttpContextInfo (SvcHttpHandler handler, HttpContext ctx)
{
this.ctx = ctx;
this.handler = handler;
this.request = new AspNetHttpRequestInfo (ctx.Request);
this.response = new AspNetHttpResponseInfo (ctx.Response);
}
HttpContext ctx;
SvcHttpHandler handler;
AspNetHttpRequestInfo request;
AspNetHttpResponseInfo response;
public HttpContext Source {
get { return ctx; }
}
public override HttpRequestInfo Request {
get { return request; }
}
public override HttpResponseInfo Response {
get { return response; }
}
public override string User {
get { return ctx.User != null ? ((GenericIdentity) ctx.User.Identity).Name : null; }
}
// FIXME: how to acquire this?
public override string Password {
get { return null; }
}
public override void ReturnUnauthorized ()
{
ctx.Response.StatusCode = 401;
}
protected override void OnContextClosed ()
{
handler.EndHttpRequest (ctx);
}
}
// Request
abstract class HttpRequestInfo
{
public abstract long ContentLength64 { get; }
public abstract NameValueCollection QueryString { get; }
public abstract NameValueCollection Headers { get; }
public abstract Uri Url { get; }
public abstract string ContentType { get; }
public abstract string HttpMethod { get; }
public abstract Stream InputStream { get; }
public abstract string ClientIPAddress { get; }
public abstract int ClientPort { get; }
}
class HttpStandaloneRequestInfo : HttpRequestInfo
{
public HttpStandaloneRequestInfo (HttpListenerRequest request)
{
this.req = request;
}
HttpListenerRequest req;
public override long ContentLength64 {
get { return req.ContentLength64; }
}
public override NameValueCollection QueryString {
get { return req.QueryString; }
}
public override NameValueCollection Headers {
get { return req.Headers; }
}
public override Uri Url {
get { return req.Url; }
}
public override string ContentType {
get { return req.ContentType; }
}
public override string HttpMethod {
get { return req.HttpMethod; }
}
public override Stream InputStream {
get { return req.InputStream; }
}
public override string ClientIPAddress {
get { return req.RemoteEndPoint.Address.ToString (); }
}
public override int ClientPort {
get { return req.RemoteEndPoint.Port; }
}
}
class AspNetHttpRequestInfo : HttpRequestInfo
{
public AspNetHttpRequestInfo (HttpRequest request)
{
this.req = request;
}
HttpRequest req;
public override long ContentLength64 {
get { return req.ContentLength; }
}
public override NameValueCollection QueryString {
get { return req.QueryString; }
}
public override NameValueCollection Headers {
get { return req.Headers; }
}
public override Uri Url {
get { return req.Url; }
}
public override string ContentType {
get { return req.ContentType; }
}
public override string HttpMethod {
get { return req.HttpMethod; }
}
public override Stream InputStream {
get { return req.InputStream; }
}
public override string ClientIPAddress {
get { return req.UserHostAddress; }
}
public override int ClientPort {
get { return -1; } // cannot retrieve
}
}
// Response
abstract class HttpResponseInfo
{
public abstract string ContentType { get; set; }
public abstract NameValueCollection Headers { get; }
public abstract Stream OutputStream { get; }
public abstract int StatusCode { get; set; }
public abstract string StatusDescription { get; set; }
public abstract void Abort ();
public abstract void Close ();
public abstract void SetLength (long value);
public virtual bool SuppressContent { get; set; }
}
class HttpStandaloneResponseInfo : HttpResponseInfo
{
public HttpStandaloneResponseInfo (HttpListenerResponse response)
{
this.res = response;
}
HttpListenerResponse res;
public override string ContentType {
get { return res.ContentType; }
set { res.ContentType = value; }
}
public override NameValueCollection Headers {
get { return res.Headers; }
}
public override int StatusCode {
get { return res.StatusCode; }
set { res.StatusCode = value; }
}
public override string StatusDescription {
get { return res.StatusDescription; }
set { res.StatusDescription = value; }
}
public override Stream OutputStream {
get { return res.OutputStream; }
}
public override void Abort ()
{
res.Abort ();
}
public override void Close ()
{
res.Close ();
}
public override void SetLength (long value)
{
res.ContentLength64 = value;
}
}
class AspNetHttpResponseInfo : HttpResponseInfo
{
public AspNetHttpResponseInfo (HttpResponse response)
{
this.res = response;
}
HttpResponse res;
public override bool SuppressContent {
get { return res.SuppressContent; }
set { res.SuppressContent = value; }
}
public override string ContentType {
get { return res.ContentType; }
set { res.ContentType = value; }
}
public override NameValueCollection Headers {
get { return res.Headers; }
}
public override int StatusCode {
get { return res.StatusCode; }
set { res.StatusCode = value; }
}
public override string StatusDescription {
get { return res.StatusDescription; }
set { res.StatusDescription = value; }
}
public override Stream OutputStream {
get { return res.OutputStream; }
}
public override void Abort ()
{
res.End ();
}
public override void Close ()
{
// We must not close the response here, as everything is taking place in the
// HttpApplication's pipeline context and the output is sent to the client
// _after_ we leave this method. Closing the response here will stop any
// output from reaching the client.
}
public override void SetLength (long value)
{
res.AddHeader ("Content-Length", value.ToString (CultureInfo.InvariantCulture));
}
}
}