a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
359 lines
8.8 KiB
C#
359 lines
8.8 KiB
C#
//
|
|
// 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));
|
|
}
|
|
}
|
|
}
|