[asp.net] Implemented CustomErrorsRedirectMode
[mono.git] / mcs / class / System.Web.Services / System.Web.Services.Protocols / WebServiceHandlerFactory.cs
1 // 
2 // System.Web.Services.Protocols.WebServiceHandlerFactory.cs
3 //
4 // Authors:
5 //      Tim Coleman (tim@timcoleman.com)
6 //      Dave Bettin (dave@opendotnet.com)
7 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
8 //      Lluis Sanchez Gual (lluis@ximian.com)
9 //
10 // Copyright (C) Tim Coleman, 2002
11 // Copyright (c) 2003 Ximian, Inc. (http://www.ximian.com)
12 //
13
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System.IO;
36 using System.Net;
37 using System.Web.Compilation;
38 using System.Web.Services;
39 using System.Web.Services.Configuration;
40 using System.Web.SessionState;
41 using System.Web.UI;
42 using System.Collections.Specialized;
43 #if NET_2_0
44 using WSConfig = System.Web.Services.Configuration.WebServicesSection;
45 using WSProtocol = System.Web.Services.Configuration.WebServiceProtocols;
46 #endif
47
48 namespace System.Web.Services.Protocols
49 {
50         class SessionWrapperHandler : IHttpHandler, IRequiresSessionState
51         {
52                 IHttpHandler handler;
53
54                 public SessionWrapperHandler (IHttpHandler handler)
55                 {
56                         this.handler = handler;
57                 }
58                 
59                 public bool IsReusable {
60                         get { return handler.IsReusable; }
61                 }
62
63                 public void ProcessRequest (HttpContext context)
64                 {
65                         handler.ProcessRequest (context);
66                 }
67         }
68
69         class ReadOnlySessionWrapperHandler : IHttpHandler, IRequiresSessionState, IReadOnlySessionState
70         {
71                 IHttpHandler handler;
72
73                 public ReadOnlySessionWrapperHandler (IHttpHandler handler)
74                 {
75                         this.handler = handler;
76                 }
77                 
78                 public bool IsReusable {
79                         get { return handler.IsReusable; }
80                 }
81
82                 public void ProcessRequest (HttpContext context)
83                 {
84                         handler.ProcessRequest (context);
85                 }
86         }
87         public class WebServiceHandlerFactory : IHttpHandlerFactory
88         {
89
90                 #region Constructors
91
92                 public WebServiceHandlerFactory () 
93                 {
94                 }
95                 
96                 #endregion // Constructors
97
98                 #region Methods
99
100                 public IHttpHandler GetHandler (HttpContext context, string verb, string url, string filePath)
101                 {
102 #if TARGET_J2EE
103                         string fp = url;
104 #else
105                         string fp = filePath != null ? filePath.Replace (HttpRuntime.AppDomainAppPath, "/").Replace (Path.DirectorySeparatorChar, '/') : null;
106 #endif
107
108                         Type type;
109 #if NET_2_0 && !TARGET_JVM
110                         type = BuildManager.GetCompiledType (url);
111 #else
112                         type = WebServiceParser.GetCompiledType (fp, context);
113 #endif
114
115                         WSProtocol protocol = GuessProtocol (context, verb);
116 #if NET_2_0
117                         context.Items ["WebServiceSoapVersion"] =
118                                 protocol == WSProtocol.HttpSoap12 ?
119                                 SoapProtocolVersion.Soap12 :
120                                 SoapProtocolVersion.Default;
121 #endif
122                         bool supported = false;
123                         IHttpHandler handler = null;
124
125                         supported = WSConfig.IsSupported (protocol);
126                         if (!supported) {
127                                 switch (protocol) {
128 #if NET_2_0
129                                         default:
130                                                 if (((protocol & WSProtocol.AnyHttpSoap) != WSProtocol.Unknown) &&
131                                                         (WSConfig.Current.EnabledProtocols & WSProtocol.AnyHttpSoap) != WSProtocol.Unknown)
132                                                         throw new InvalidOperationException ("Possible SOAP version mismatch.");
133                                                 break;
134 #endif
135                                         case WSProtocol.HttpPost:
136                                                 if (WSConfig.IsSupported (WSProtocol.HttpPostLocalhost)) {
137 #if NET_2_0
138                                                         supported = context.Request.IsLocal;
139 #else
140                                                         string localAddr = context.Request.ServerVariables ["LOCAL_ADDR"];
141
142                                                         supported = localAddr != null &&
143                                                                 (localAddr == context.Request.ServerVariables ["REMOTE_ADDR"] ||
144                                                                 IPAddress.IsLoopback (IPAddress.Parse (localAddr)));
145 #endif
146                                                 }
147                                                 break;
148                                 }
149                         }
150                         if (!supported)
151                                 throw new InvalidOperationException ("Unsupported request format.");
152
153                         switch (protocol) {
154                         case WSProtocol.HttpSoap12:
155                         case WSProtocol.HttpSoap:
156                                 handler = GetTypeHandler (context, new HttpSoapWebServiceHandler (type));
157                                 break;
158                         case WSProtocol.HttpPost:
159                         case WSProtocol.HttpGet:
160                                 handler = GetTypeHandler (context, new HttpSimpleWebServiceHandler (type, protocol.ToString ()));
161                                 break;
162                         case WSProtocol.Documentation:
163                                 SoapDocumentationHandler soapHandler;
164                                 soapHandler = new SoapDocumentationHandler (type, context);
165                                 if (soapHandler.PageHandler is IRequiresSessionState) {
166                                         if (soapHandler.PageHandler is IReadOnlySessionState)
167                                                 handler = new ReadOnlySessionWrapperHandler (soapHandler);
168                                         else
169                                                 handler = new SessionWrapperHandler (soapHandler);
170                                 } else {
171                                         handler = soapHandler;
172                                 }
173                                 break;
174                         }
175
176                         return handler;
177                 }
178                 
179                 IHttpHandler GetTypeHandler (HttpContext context, WebServiceHandler handler)
180                 {
181                         MethodStubInfo method = handler.GetRequestMethod (context);
182                         if (method == null) return null;
183
184                         int cache_duration = method.MethodInfo.CacheDuration;
185                         if (cache_duration > 0)
186                                 context.Response.ExpiresAbsolute = DateTime.Now.AddSeconds (cache_duration);
187                         if (method.MethodInfo.EnableSession)
188                                 return new SessionWrapperHandler (handler);
189                         else
190                                 return handler;
191                 }
192
193                 static WSProtocol GuessProtocol (HttpContext context, string verb)
194                 {
195                         if (context.Request.PathInfo == null || context.Request.PathInfo == "")
196                         {
197                                 if (context.Request.RequestType == "GET")
198                                         return WSProtocol.Documentation;
199                                 else
200 #if NET_2_0
201                                         return context.Request.Headers ["SOAPAction"] != null ?
202                                                 WSProtocol.HttpSoap : WSProtocol.HttpSoap12;
203 #else
204                                         return WSProtocol.HttpSoap;
205 #endif
206                         }
207                         else
208                         {
209                                 if (context.Request.RequestType == "GET")
210                                         return WSProtocol.HttpGet;
211                                 else
212                                         return WSProtocol.HttpPost;
213                         }
214                 }
215
216                 public void ReleaseHandler (IHttpHandler handler)
217                 {
218                 }
219
220                 #endregion // Methods
221         }
222 }