codeowners update
[mono.git] / mcs / class / System.ServiceModel / HTTP_listener_notes.txt
1 * ASP.NET integration and HTTP standalone service process flow
2
3 WARNING: This document is now obsoleted for HTTP standalone listener.
4
5 This mostly explains what our WCF does, and does not explain what I think it really should do (though I write about them as long as I know).
6
7
8 ** Basic process flow
9
10 - ServiceHost opens a set of ChannelDispatchers for each Binding used in ServiceHost.Endpoints.
11   - When the same Binding instance is used in multiple service endpoints, they share the same ChannelDispatcher, only differentiating EndpointDispatcher.
12 - ChannelDispatcher builds an IChannelListener (such as HttpStandaloneChannelListener`1 or AspNetChannelListener`1) based on the corresponding ServiceEndpoint which contains a Binding that is used to build channel listeners).
13 - IChannelListener itself does not provide any service loop. Instead, the ChannelDispatcher starts a service loop.
14 -- IChannelListener only has methods for receiving requests that must be explicitly invoked for each request (i.e. to repeatedly process requests it must invoke receiver methods every time, unlike ServiceHost.Open() method).
15 - Inside the service loop, IChannelListener invokes [Begin]AcceptChannel() to get a channel such as HttpStandaloneReplyChannel or AspNetReplyChannel`1. Channels can be created as much as the service throttle limitation (ServiceThrottle) allows.
16 - Then the loop manager invokes the channel's [Begin]TryReceiveRequest().
17 - When WSDLs are enabled, ServiceMetadataExtension populates another ChannelDispatcher (yes, not just an EndpointDispatcher) that serves HTTP requests to WSDLs.
18   - It is because ServiceMetadataExtension typically uses a Binding returned by corresponding method in MetadataExchangeBindings.
19 -- It is important to understand that if multiple ChannelDispatchers have the identical endpoint URI, it populates HTTP channel listener onto the *same* port and even possibly onto the same target URL during this process, differentiating only by the request parameter (e.g. "?wsdl"). This causes a lot of complication on both IHttpHandler (for ASP.NET) and HttpListener (for non-ASP.NET).
20 - Inside HttpStandaloneChannelListener or AspNetChannelListener, it internally has HttpListenerManager (NOTE: in different namespaces and different code) which manages the actual HTTP listeners.
21 -- These men in the middle are required to manage HTTP listeners across the actual channel listeners because more than one channel listeners might use the identical HTTP listener; only one HttpListener can listen to a specific URI prefix, while (as explained above) WSDL support dispatcher may listen to the same URI only differentiating the query parameter.
22 - While building ChannelDispatcher inside ServiceHostBase, we have a tricky code that sets ChannelDispatcher to HttpChannelListener. It is to make sure to apply ServiceMetadataExtension to the listener internals. Without that info, it is not possible to handle wsdl requests precisely (or if you have any simpler idea to achieve this safely, we would glad to hear it).
23
24
25 ** non-ASP.NET-specific process flow
26
27 - HttpStandaloneChannelListener`1 implements IChannelListener`1, HttpStandaloneReplyChannel implements IReplyChannel`1, and HttpStandaloneRequestContext extends RequestContext.
28 - HttpStandaloneChannelListener`1 internally creates System.ServiceModel.Channels.Http.HttpListenerManager that manages HttpListeners. The management here includes sharing HttpListeners between the channel listeners that have the identical Uri (see WSDL section above).
29 - HttpListenerManager start HttpListener's listening loop when a ChannelDispatcher is registered as a channel candidate. If a ChannelDispatcher is unregistered and there is no more listening channel, then the HttpListener is disposed.
30 - When a ChannelDispatcher is registered, the dispatchers for the same HttpListener are sorted by the "ChannelDispatcher with the highest priority in Endpoints" order.
31 - When an HttpListenerContext is arrived, each ChannelDispatcher (in order) examines if it "matches" and processes if it does. Matching is checked by EndpointDispatchers' filtering.
32
33
34 ** ASP.NET-specific process flow
35
36 - An IHttpHandler manages one ServiceHost. IChannelListener is bound to a ChannelDispatcher. Hence, IChannelListener has a ServiceHost to which it is bound.
37 - HttpListener is designed to explicitly call [Begin]GetContext() method for each request processing. i.e. it is pull-based process.
38 - ASP.NET processing (IHttpHandler.ProcessRequest() method) is designed to be invoked by the ASP.NET runtime i.e. it is push-based process.
39 -- while WCF channels must be created by ChannelDispatcher, the ASP.NET channels must not be instantiated and returned immediately by IHttpHandler.ProcessRequest(), but have to wait for calls to IChannelListener.[Begin]AcceptChannel() at first.
40 -- Then, AspNetChannelListener`1 retrieves HttpContext. It has to wait for one if there is no HttpContext in the IHttpHandler)
41 -- Due to the process flow explained above, the IHttpHandler cannot handle the request when it receives a request. Instead, it has to store the HttpContext for IChannelListers' use.
42 -- Note that when there is WSDL extension, there is *another* IChannelListener that could be mapped to the identical URL i.e. which could be mapped to the identical IHttpHandler instance.
43
44
45 ** Call process flow and locking
46
47 - IHttpHandler.ProcessRequest()
48   - optionally create ServiceHost and
49   - calls ServiceHost.Open()
50   - ChannelDispatcher.StartLoop()
51   - AspNetChannelListener.[Begin]AcceptChannel() when throttling allows.
52   - AspNetReplyChannel.[Begin]TryReceiveRequest()
53
54 locking: TBD
55
56
57 ** Some notes
58
59 - WebHttpBinding creates HTTP channel listeners that share an identical endpoint URI, which could also be mapped by ServiceMetadataExtension. It brings problem on dispatching HTTP request to correct listener. FilterPriority is used to resolve the issue (possibly to some extent) that requests to wsdl/mex are treated in lower priority.
60 - While multiple channel dispatchers' endpoints could indicate an identical HTTP URI, it is not allowed to use the same HTTP URI across more than one ServiceHostBase and attempt to create such endpoints will result in InvalidOperationException for conflict with existing listeners.
61 - Actually, .NET rejects duplicate listen URI at HttpChannelListener level (precisely to say, equivalent to that of mono, ones from HttpTransportBindingElement.BuildChannelListener()). It does not happen if the service endpoints share the same Binding (as described above).
62
63
64 ** Bugs
65
66 There is not a few bugs on service implementations and there often are reasons:
67
68 - ASP.NET listener ends up to dump ThreadAbort during its shutdown. It's mostly harmless though.
69