annotate Net/HTTP.cs @ 101:04c56f31db37

Merge
author Ivo Smits <Ivo@UCIS.nl>
date Mon, 29 Sep 2014 01:36:27 +0200
parents 2b5e7bb9b979 be17dd3f6927
children a03e6ad0051f
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
1 ???using System;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
2 using System.Collections.Generic;
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
3 using System.IO;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
4 using System.Net;
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
5 using System.Net.Security;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
6 using System.Net.Sockets;
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
7 using System.Security.Cryptography.X509Certificates;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
8 using System.Text;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
9 using UCIS.Util;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
10 using HTTPHeader = System.Collections.Generic.KeyValuePair<string, string>;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
11
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
12 namespace UCIS.Net.HTTP {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
13 public class HTTPServer : TCPServer.IModule, IDisposable {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
14 public IHTTPContentProvider ContentProvider { get; set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
15 public Boolean ServeFlashPolicyFile { get; set; }
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
16 public X509Certificate SSLCertificate { get; set; }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
17 private Socket Listener = null;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
18
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
19 public HTTPServer() { }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
20
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
21 public void Listen(int port) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
22 Listen(new IPEndPoint(IPAddress.Any, port));
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
23 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
24
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
25 public void Listen(EndPoint localep) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
26 if (Listener != null) throw new InvalidOperationException("A listener exists");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
27 Listener = new Socket(localep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
28 Listener.Bind(localep);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
29 Listener.Listen(5);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
30 Listener.BeginAccept(AcceptCallback, null);
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
31 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
32
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
33 private void AcceptCallback(IAsyncResult ar) {
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
34 Socket socket = null;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
35 try {
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
36 socket = Listener.EndAccept(ar);
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
37 HandleClient(socket);
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
38 } catch {
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
39 if (socket != null) socket.Close();
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
40 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
41 try {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
42 Listener.BeginAccept(AcceptCallback, null);
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
43 } catch { }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
44 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
45
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
46 private void SslAuthenticationCallback(IAsyncResult ar) {
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
47 Object[] args = (Object[])ar.AsyncState;
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
48 Socket socket = (Socket)args[0];
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
49 SslStream ssl = (SslStream)args[1];
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
50 try {
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
51 ssl.EndAuthenticateAsServer(ar);
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
52 new HTTPContext(this, ssl, socket);
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
53 } catch {
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
54 socket.Close();
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
55 }
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
56 }
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
57
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
58 public void Dispose() {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
59 if (Listener != null) Listener.Close();
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
60 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
61
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
62 public void HandleClient(Socket socket, Stream streamwrapper) {
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
63 if (streamwrapper == null) streamwrapper = new NetworkStream(socket, true);
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
64 if (SSLCertificate != null) {
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
65 SslStream ssl = new SslStream(streamwrapper);
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
66 ssl.BeginAuthenticateAsServer(SSLCertificate, SslAuthenticationCallback, new Object[] { socket, ssl });
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
67 } else {
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
68 new HTTPContext(this, streamwrapper, socket);
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
69 }
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
70 }
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
71
45
8df7f4dc5615 HTTP Server: enable KeepAlive option on TCP sockets
Ivo Smits <Ivo@UCIS.nl>
parents: 16
diff changeset
72 public void HandleClient(Socket client) {
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
73 HandleClient(client, null);
45
8df7f4dc5615 HTTP Server: enable KeepAlive option on TCP sockets
Ivo Smits <Ivo@UCIS.nl>
parents: 16
diff changeset
74 }
8df7f4dc5615 HTTP Server: enable KeepAlive option on TCP sockets
Ivo Smits <Ivo@UCIS.nl>
parents: 16
diff changeset
75
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
76 bool TCPServer.IModule.Accept(TCPStream stream) {
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
77 HandleClient(stream.Socket, stream);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
78 return false;
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
79 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
80 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
81
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
82 public enum HTTPResponseStreamMode {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
83 None = -1,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
84 Direct = 0,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
85 Buffered = 1,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
86 Chunked = 2,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
87 Hybrid = 3,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
88 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
89
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
90 public class HTTPContext {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
91 public HTTPServer Server { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
92 public EndPoint LocalEndPoint { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
93 public EndPoint RemoteEndPoint { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
94
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
95 public String RequestMethod { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
96 public String RequestPath { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
97 public String RequestQuery { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
98 public int HTTPVersion { get; set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
99
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
100 public Socket Socket { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
101 public Boolean SuppressStandardHeaders { get; set; }
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
102 public TCPStream TCPStream { get; private set; }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
103
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
104 private StreamWriter Writer;
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
105 private PrebufferingStream Reader;
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
106 private List<HTTPHeader> RequestHeaders = null;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
107 private HTTPConnectionState State = HTTPConnectionState.Starting;
94
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
108 private KeyValuePair<String, String>[] QueryParameters = null, PostParameters = null, Cookies = null;
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
109 private HTTPOutputStream ResponseStream = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
110 private HTTPInputStream RequestStream = null;
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
111
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
112 private enum HTTPConnectionState {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
113 Starting = 0,
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
114 ReceivingRequest = 1,
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
115 ProcessingRequest = 2,
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
116 SendingHeaders = 3,
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
117 SendingContent = 4,
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
118 Completed = 5,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
119 Closed = 6,
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
120 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
121
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
122 private class HTTPOutputStream : Stream {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
123 public HTTPResponseStreamMode Mode { get; private set; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
124 public HTTPContext Context { get; private set; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
125 private Stream OutputStream = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
126 private MemoryStream Buffer = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
127 private long BytesWritten = 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
128 private long MaxLength;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
129
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
130 public HTTPOutputStream(HTTPContext context, HTTPResponseStreamMode mode) : this(context, mode, -1) { }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
131 public HTTPOutputStream(HTTPContext context, HTTPResponseStreamMode mode, long length) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
132 this.Context = context;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
133 this.Mode = mode;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
134 this.MaxLength = length;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
135 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
136 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
137 if (MaxLength != -1) Context.SendHeader("Content-Length", MaxLength.ToString());
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
138 OutputStream = Context.BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
139 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
140 case HTTPResponseStreamMode.Chunked:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
141 Context.SendHeader("Transfer-Encoding", "chunked");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
142 OutputStream = Context.BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
143 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
144 case HTTPResponseStreamMode.Buffered:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
145 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
146 if (Context.State != HTTPConnectionState.ProcessingRequest && Context.State != HTTPConnectionState.SendingHeaders) throw new InvalidOperationException("The response stream can not be created in the current state");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
147 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
148 default: throw new InvalidOperationException("Response stream mode is not supported");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
149 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
150 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
151
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
152 private void WriteBuffered(byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
153 if (Buffer == null) Buffer = new MemoryStream();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
154 Buffer.Write(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
155 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
156 private void WriteChunked(byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
157 Byte[] lb = Encoding.ASCII.GetBytes(count.ToString("X") + "\r\n");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
158 OutputStream.Write(lb, 0, lb.Length);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
159 if (count != 0) OutputStream.Write(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
160 OutputStream.Write(new Byte[] { (Byte)'\r', (Byte)'\n' }, 0, 2);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
161 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
162 private void HybridSwitchToChunked() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
163 MemoryStream oldbuffer = Buffer;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
164 Buffer = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
165 Context.SendHeader("Transfer-Encoding", "chunked");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
166 OutputStream = Context.BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
167 Mode = HTTPResponseStreamMode.Chunked;
84
146a8d224d86 Added ArrayUtil.Remove, fixed some exceptons
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
168 if (oldbuffer != null) oldbuffer.WriteTo(this);
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
169 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
170
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
171 public override void Write(byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
172 if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentOutOfRangeException("buffer", "Offset and count arguments exceed the buffer dimensions");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
173 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
174 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
175 if (MaxLength != -1 && BytesWritten + count > MaxLength) throw new InvalidOperationException("The write operation exceeds the transfer length");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
176 OutputStream.Write(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
177 BytesWritten += count;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
178 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
179 case HTTPResponseStreamMode.Buffered:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
180 WriteBuffered(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
181 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
182 case HTTPResponseStreamMode.Chunked:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
183 if (count != 0) WriteChunked(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
184 BytesWritten += count;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
185 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
186 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
187 if (count > 1024 || (Buffer != null && Buffer.Length + count > 1024)) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
188 HybridSwitchToChunked();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
189 if (count != 0) WriteChunked(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
190 } else {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
191 WriteBuffered(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
192 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
193 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
194 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
195 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
196 class CompletedAsyncResult : AsyncResultBase {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
197 public CompletedAsyncResult(AsyncCallback callback, Object state) : base(callback, state) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
198 SetCompleted(true, null);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
199 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
200 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
201 public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
202 if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentOutOfRangeException("buffer", "Offset and count arguments exceed the buffer dimensions");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
203 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
204 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
205 if (MaxLength != -1 && BytesWritten + count > MaxLength) throw new InvalidOperationException("The write operation exceeds the transfer length");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
206 BytesWritten += count;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
207 return OutputStream.BeginWrite(buffer, offset, count, callback, state);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
208 case HTTPResponseStreamMode.Buffered:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
209 case HTTPResponseStreamMode.Chunked:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
210 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
211 Write(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
212 return new CompletedAsyncResult(callback, state);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
213 default: return null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
214 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
215 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
216 public override void EndWrite(IAsyncResult asyncResult) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
217 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
218 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
219 OutputStream.EndWrite(asyncResult);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
220 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
221 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
222 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
223 public override void SetLength(long value) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
224 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
225 case HTTPResponseStreamMode.Buffered:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
226 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
227 if (value != 0) throw new InvalidOperationException("The length can only be set to zero using this method");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
228 Buffer = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
229 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
230 default: throw new InvalidOperationException("The operation is not supported in the current mode");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
231 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
232 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
233 public override long Length {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
234 get { return MaxLength == -1 ? Position : MaxLength; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
235 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
236 public override long Position {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
237 get { return (Buffer == null) ? BytesWritten : BytesWritten + Buffer.Length; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
238 set { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
239 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
240 public override void Flush() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
241 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
242 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
243 HybridSwitchToChunked();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
244 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
245 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
246 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
247 public override bool CanWrite {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
248 get { return Context.State != HTTPConnectionState.Completed && Context.State != HTTPConnectionState.Closed && (OutputStream == null || OutputStream.CanWrite); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
249 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
250 protected override void Dispose(bool disposing) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
251 base.Dispose(disposing);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
252 if (disposing) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
253 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
254 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
255 /*if (MaxLength != -1 && MaxLength > BytesWritten) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
256 long left = MaxLength - BytesWritten;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
257 Byte[] dummy = new Byte[Math.Min(left, 1024)];
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
258 for (; left > 0; left -= dummy.Length) OutputStream.Write(dummy, 0, (int)Math.Min(left, dummy.Length));
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
259 }*/
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
260 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
261 case HTTPResponseStreamMode.Chunked:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
262 WriteChunked(null, 0, 0);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
263 Mode = HTTPResponseStreamMode.None;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
264 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
265 case HTTPResponseStreamMode.Buffered:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
266 case HTTPResponseStreamMode.Hybrid:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
267 long length = (Buffer == null) ? 0 : Buffer.Length;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
268 Context.SendHeader("Content-Length", length.ToString());
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
269 OutputStream = Context.BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
270 if (Buffer != null) Buffer.WriteTo(OutputStream);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
271 Buffer = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
272 Mode = HTTPResponseStreamMode.None;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
273 break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
274 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
275 Context.EndResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
276 if (MaxLength != -1 && MaxLength > BytesWritten) Context.Close();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
277 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
278 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
279 public override bool CanTimeout {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
280 get { return OutputStream == null ? true : OutputStream.CanTimeout; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
281 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
282 public override int WriteTimeout {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
283 get { return OutputStream == null ? 0 : OutputStream.WriteTimeout; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
284 set { if (OutputStream != null) OutputStream.WriteTimeout = value; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
285 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
286
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
287 public override bool CanRead { get { return false; } }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
288 public override bool CanSeek { get { return false; } }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
289
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
290 public override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
291 public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
292 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
293 private class HTTPInputStream : Stream {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
294 public HTTPResponseStreamMode Mode { get; private set; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
295 private Stream InputStream = null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
296 private long BytesRead = 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
297 private long BytesLeft = 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
298 public HTTPInputStream(HTTPContext context) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
299 String TransferEncoding = context.GetRequestHeader("Transfer-Encoding");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
300 String ContentLength = context.GetRequestHeader("Content-Length");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
301 InputStream = context.Reader;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
302 if (TransferEncoding != null && TransferEncoding.StartsWith("chunked", StringComparison.InvariantCultureIgnoreCase)) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
303 Mode = HTTPResponseStreamMode.Chunked;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
304 } else if (ContentLength != null) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
305 Mode = HTTPResponseStreamMode.Direct;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
306 if (!long.TryParse(ContentLength, out BytesLeft)) BytesLeft = 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
307 } else {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
308 Mode = HTTPResponseStreamMode.None;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
309 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
310 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
311 private int ReadDirect(Byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
312 if (count > BytesLeft) count = (int)BytesLeft;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
313 if (count == 0) return 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
314 int read = InputStream.Read(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
315 if (read >= 0) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
316 BytesRead += read;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
317 BytesLeft -= read;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
318 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
319 return read;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
320 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
321 public override int Read(byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
322 if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentOutOfRangeException("buffer", "Offset and count arguments exceed the buffer dimensions");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
323 switch (Mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
324 case HTTPResponseStreamMode.None:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
325 return 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
326 case HTTPResponseStreamMode.Direct:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
327 return ReadDirect(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
328 case HTTPResponseStreamMode.Chunked:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
329 if (BytesLeft == 0) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
330 String length = ReadLine(InputStream);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
331 if (!long.TryParse(length, out BytesLeft)) BytesLeft = 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
332 if (BytesLeft == 0) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
333 while (true) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
334 String line = ReadLine(InputStream);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
335 if (line == null || line.Length == 0) break;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
336 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
337 Mode = HTTPResponseStreamMode.None;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
338 return 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
339 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
340 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
341 return ReadDirect(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
342 default:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
343 return 0;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
344 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
345 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
346 class CompletedAsyncResult : AsyncResultBase {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
347 public int Count { get; private set; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
348 public CompletedAsyncResult(AsyncCallback callback, Object state, int count)
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
349 : base(callback, state) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
350 this.Count = count;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
351 SetCompleted(true, null);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
352 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
353 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
354 public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
355 if (BytesLeft > 0) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
356 if (count > BytesLeft) count = (int)BytesLeft;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
357 if (count == 0) return new CompletedAsyncResult(callback, state, 0);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
358 return InputStream.BeginRead(buffer, offset, count, callback, state);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
359 } else {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
360 int ret = Read(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
361 return new CompletedAsyncResult(callback, state, ret);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
362 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
363 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
364 public override int EndRead(IAsyncResult asyncResult) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
365 CompletedAsyncResult car = asyncResult as CompletedAsyncResult;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
366 if (car != null) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
367 return car.Count;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
368 } else {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
369 return InputStream.EndRead(asyncResult);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
370 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
371 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
372 public override long Length {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
373 get { return BytesRead + BytesLeft; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
374 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
375 public override long Position {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
376 get { return BytesRead; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
377 set { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
378 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
379 public override bool CanRead {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
380 get { return (BytesLeft > 0 || Mode == HTTPResponseStreamMode.Chunked) && InputStream.CanRead; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
381 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
382 public override bool CanTimeout {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
383 get { return InputStream.CanTimeout; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
384 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
385 public override int ReadTimeout {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
386 get { return InputStream.ReadTimeout; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
387 set { InputStream.ReadTimeout = value; }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
388 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
389 protected override void Dispose(bool disposing) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
390 base.Dispose(disposing);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
391 Byte[] dummy = new Byte[1024];
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
392 while (Read(dummy, 0, dummy.Length) != 0) ;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
393 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
394
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
395 public override bool CanSeek { get { return false; } }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
396 public override bool CanWrite { get { return false; } }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
397 public override void Flush() { }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
398 public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
399 public override void SetLength(long value) { throw new NotSupportedException(); }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
400 public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
401 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
402
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
403 public HTTPContext(HTTPServer server, TCPStream stream) : this(server, stream, stream.Socket) { }
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
404 public HTTPContext(HTTPServer server, Socket socket) : this(server, null, socket) { }
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
405 public HTTPContext(HTTPServer server, Stream stream, Socket socket) {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
406 this.Server = server;
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
407 this.Socket = socket;
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
408 if (socket != null) {
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
409 this.LocalEndPoint = socket.LocalEndPoint;
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
410 this.RemoteEndPoint = socket.RemoteEndPoint;
45
8df7f4dc5615 HTTP Server: enable KeepAlive option on TCP sockets
Ivo Smits <Ivo@UCIS.nl>
parents: 16
diff changeset
411 if (socket.ProtocolType == ProtocolType.Tcp) socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
10
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
412 if (stream == null) stream = new NetworkStream(socket, true);
7269e91c6e26 HTTPServer: added support for HTTPS
Ivo Smits <Ivo@UCIS.nl>
parents: 7
diff changeset
413 }
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
414 Init(stream);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
415 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
416
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
417 private void Init(Stream Stream) {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
418 Writer = new StreamWriter(Stream, Encoding.ASCII);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
419 Writer.NewLine = "\r\n";
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
420 Writer.AutoFlush = true;
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
421 Reader = new PrebufferingStream(Stream);
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
422 Reader.BeginPrebuffering(PrebufferCallback, null);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
423 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
424
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
425 private static String ReadLine(Stream stream) {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
426 StringBuilder s = new StringBuilder();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
427 while (true) {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
428 int b = stream.ReadByte();
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
429 if (b == -1) {
4
9e2e6433f57a Small fix for HTTP Server - Flash Cross Domain Policy File support
Ivo Smits <Ivo@UCIS.nl>
parents: 3
diff changeset
430 if (s.Length == 0) return null;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
431 break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
432 } else if (b == 13) {
4
9e2e6433f57a Small fix for HTTP Server - Flash Cross Domain Policy File support
Ivo Smits <Ivo@UCIS.nl>
parents: 3
diff changeset
433 } else if (b == 10 || b == 0) {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
434 break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
435 } else {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
436 s.Append((Char)b);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
437 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
438 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
439 return s.ToString();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
440 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
441 private String ReadLine() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
442 return ReadLine(Reader);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
443 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
444
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
445 private void PrebufferCallback(IAsyncResult ar) {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
446 State = HTTPConnectionState.ReceivingRequest;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
447 try {
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
448 Reader.EndPrebuffering(ar);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
449 String line = ReadLine();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
450 if (line == null) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
451 Close();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
452 return;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
453 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
454 if (Server.ServeFlashPolicyFile && line[0] == '<') { //<policy-file-request/>
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
455 Writer.WriteLine("<cross-domain-policy><allow-access-from domain=\"*\" to-ports=\"*\" /></cross-domain-policy>");
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
456 Reader.WriteByte(0);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
457 Close();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
458 return;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
459 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
460 String[] request = line.Split(' ');
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
461 if (request.Length != 3) goto SendError400AndClose;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
462 RequestMethod = request[0];
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
463 String RequestAddress = request[1];
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
464 switch (request[2]) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
465 case "HTTP/1.0": HTTPVersion = 10; break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
466 case "HTTP/1.1": HTTPVersion = 11; break;
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
467 default: goto SendError505AndClose;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
468 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
469 request = RequestAddress.Split(new Char[] { '?' });
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
470 RequestPath = Uri.UnescapeDataString(request[0]);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
471 RequestQuery = request.Length > 1 ? request[1] : null;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
472 RequestHeaders = new List<HTTPHeader>();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
473 while (true) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
474 line = ReadLine();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
475 if (line == null) goto SendError400AndClose;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
476 if (line.Length == 0) break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
477 request = line.Split(new String[] { ": " }, 2, StringSplitOptions.None);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
478 if (request.Length != 2) goto SendError400AndClose;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
479 RequestHeaders.Add(new HTTPHeader(request[0], request[1]));
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
480 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
481 IHTTPContentProvider content = Server.ContentProvider;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
482 if (content == null) goto SendError500AndClose;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
483 State = HTTPConnectionState.ProcessingRequest;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
484 content.ServeRequest(this);
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
485 Close();
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
486 } catch (Exception ex) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
487 Console.Error.WriteLine(ex);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
488 switch (State) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
489 case HTTPConnectionState.ProcessingRequest: goto SendError500AndClose;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
490 default:
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
491 Close();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
492 break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
493 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
494 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
495 return;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
496
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
497 SendError400AndClose:
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
498 State = HTTPConnectionState.ProcessingRequest;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
499 SendErrorAndClose(400);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
500 return;
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
501 SendError500AndClose:
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
502 State = HTTPConnectionState.ProcessingRequest;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
503 SendErrorAndClose(500);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
504 return;
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
505 SendError505AndClose:
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
506 State = HTTPConnectionState.ProcessingRequest;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
507 SendErrorAndClose(400);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
508 return;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
509 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
510
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
511 public String GetRequestHeader(String name) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
512 if (State != HTTPConnectionState.ProcessingRequest && State != HTTPConnectionState.SendingHeaders && State != HTTPConnectionState.SendingContent) throw new InvalidOperationException();
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
513 if (RequestHeaders == null) return null;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
514 foreach (HTTPHeader h in RequestHeaders) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
515 if (name.Equals(h.Key, StringComparison.OrdinalIgnoreCase)) return h.Value;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
516 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
517 return null;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
518 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
519 public String[] GetRequestHeaders(String name) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
520 if (State != HTTPConnectionState.ProcessingRequest && State != HTTPConnectionState.SendingHeaders && State != HTTPConnectionState.SendingContent) throw new InvalidOperationException();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
521 String[] items = new String[0];
100
2b5e7bb9b979 HTTP: Small fixes in server SSL support
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
522 if (RequestHeaders == null) return items;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
523 foreach (HTTPHeader h in RequestHeaders) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
524 if (name.Equals(h.Key, StringComparison.OrdinalIgnoreCase)) ArrayUtil.Add(ref items, h.Value);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
525 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
526 return items;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
527 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
528
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
529 private static String UnescapeUrlDataString(String text) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
530 return Uri.UnescapeDataString(text.Replace('+', ' '));
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
531 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
532 private static KeyValuePair<String, String>[] DecodeUrlEncodedFields(String data) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
533 List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
534 foreach (String arg in data.Split('&')) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
535 String[] parts = arg.Split(new Char[] { '=' }, 2);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
536 String key = UnescapeUrlDataString(parts[0]);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
537 String value = (parts.Length > 1) ? UnescapeUrlDataString(parts[1]) : String.Empty;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
538 list.Add(new KeyValuePair<string, string>(key, value));
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
539 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
540 return list.ToArray();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
541 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
542
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
543 public String GetQueryParameter(String name) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
544 foreach (KeyValuePair<String, String> kvp in GetQueryParameters()) if (kvp.Key == name) return kvp.Value;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
545 return null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
546 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
547 public String[] GetQueryParameters(String name) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
548 List<String> list = new List<string>();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
549 foreach (KeyValuePair<String, String> kvp in GetQueryParameters()) if (kvp.Key == name) list.Add(kvp.Value);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
550 return list.ToArray();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
551 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
552 public KeyValuePair<String, String>[] GetQueryParameters() {
94
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
553 if (RequestQuery == null) return new KeyValuePair<String, String>[0];
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
554 if (QueryParameters == null) QueryParameters = DecodeUrlEncodedFields(RequestQuery);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
555 return QueryParameters;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
556 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
557
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
558 public String GetPostParameter(String name) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
559 foreach (KeyValuePair<String, String> kvp in GetPostParameters()) if (kvp.Key == name) return kvp.Value;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
560 return null;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
561 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
562 public String[] GetPostParameters(String name) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
563 List<String> list = new List<string>();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
564 foreach (KeyValuePair<String, String> kvp in GetPostParameters()) if (kvp.Key == name) list.Add(kvp.Value);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
565 return list.ToArray();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
566 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
567 public KeyValuePair<String, String>[] GetPostParameters() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
568 if (PostParameters == null) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
569 if (RequestMethod == "POST" && GetRequestHeader("Content-Type") == "application/x-www-form-urlencoded") {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
570 String data;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
571 using (StreamReader reader = new StreamReader(OpenRequestStream(), Encoding.UTF8)) data = reader.ReadToEnd();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
572 PostParameters = DecodeUrlEncodedFields(data);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
573 } else {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
574 PostParameters = new KeyValuePair<string, string>[0];
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
575 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
576 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
577 return PostParameters;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
578 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
579
94
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
580 public String GetCookie(String name) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
581 foreach (KeyValuePair<String, String> kvp in GetCookies()) if (kvp.Key == name) return kvp.Value;
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
582 return null;
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
583 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
584 public String[] GetCookies(String name) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
585 List<String> list = new List<string>();
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
586 foreach (KeyValuePair<String, String> kvp in GetCookies()) if (kvp.Key == name) list.Add(kvp.Value);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
587 return list.ToArray();
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
588 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
589 public KeyValuePair<String, String>[] GetCookies() {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
590 if (Cookies == null) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
591 String cookie = GetRequestHeader("Cookie");
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
592 List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
593 if (cookie != null) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
594 foreach (String part in cookie.Split(';', ',')) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
595 String[] subparts = part.Split('=');
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
596 String key = subparts[0].Trim(' ', '\t', '"');
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
597 String value = (subparts.Length < 2) ? null : subparts[1].Trim(' ', '\t', '"');
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
598 list.Add(new KeyValuePair<string, string>(key, value));
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
599 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
600 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
601 Cookies = list.ToArray();
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
602 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
603 return Cookies;
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
604 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
605
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
606 public void SetCookie(String name, String value) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
607 SendHeader("Set-Cookie", String.Format("{0}={1}", name, value));
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
608 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
609 public void SetCookie(String name, String value, DateTime expire) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
610 SendHeader("Set-Cookie", String.Format("{0}={1}; Expires={2:R}", name, value, expire));
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
611 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
612 public void SetCookie(String name, String value, DateTime? expire, String path, String domain, Boolean secure, Boolean httponly) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
613 StringBuilder sb = new StringBuilder();
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
614 sb.Append(name);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
615 sb.Append("=");
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
616 sb.Append(value);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
617 if (expire != null) sb.AppendFormat("; Expires={0:R}", expire.Value.ToUniversalTime());
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
618 if (path != null) sb.AppendFormat("; Path={0}", path);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
619 if (domain != null) sb.AppendFormat("; Domain={0}", domain);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
620 if (secure) sb.Append("; Secure");
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
621 if (httponly) sb.Append("; HttpOnly");
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
622 SendHeader("Set-Cookie", sb.ToString());
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
623 }
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
624
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
625 public Stream OpenRequestStream() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
626 if (RequestStream == null) RequestStream = new HTTPInputStream(this);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
627 return RequestStream;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
628 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
629
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
630 private static String GetMessageForStatus(int code) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
631 switch (code) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
632 case 101: return "Switching Protocols";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
633 case 200: return "OK";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
634 case 301: return "Moved Permanently";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
635 case 302: return "Found";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
636 case 303: return "See Other";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
637 case 304: return "Not Modified";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
638 case 307: return "Temporary Redirect";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
639 case 400: return "Bad Request";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
640 case 401: return "Access denied";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
641 case 403: return "Forbidden";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
642 case 404: return "Not Found";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
643 case 500: return "Internal Server Error";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
644 case 505: return "HTTP Version Not Supported";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
645 default: return "Unknown Status";
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
646 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
647 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
648
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
649 public void SendStatus(int code) {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
650 String message = GetMessageForStatus(code);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
651 SendStatus(code, message);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
652 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
653 public void SendStatus(int code, String message) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
654 if (State != HTTPConnectionState.ProcessingRequest) throw new InvalidOperationException();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
655 StringBuilder sb = new StringBuilder();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
656 sb.Append("HTTP/");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
657 switch (HTTPVersion) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
658 case 10: sb.Append("1.0"); break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
659 case 11: sb.Append("1.1"); break;
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
660 default: sb.Append("1.0"); break;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
661 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
662 sb.Append(" ");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
663 sb.Append(code);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
664 sb.Append(" ");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
665 sb.Append(message);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
666 Writer.WriteLine(sb.ToString());
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
667 State = HTTPConnectionState.SendingHeaders;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
668 if (!SuppressStandardHeaders) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
669 SendHeader("Expires", "Expires: Sun, 1 Jan 2000 00:00:00 GMT");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
670 SendHeader("Cache-Control", "no-store, no-cache, must-revalidate");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
671 SendHeader("Cache-Control", "post-check=0, pre-check=0");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
672 SendHeader("Pragma", "no-cache");
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
673 SendHeader("Server", "UCIS Embedded Webserver");
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
674 SendHeader("Connection", "Close");
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
675 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
676 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
677 public void SendHeader(String name, String value) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
678 if (State == HTTPConnectionState.ProcessingRequest) SendStatus(200);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
679 if (State != HTTPConnectionState.SendingHeaders) throw new InvalidOperationException();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
680 Writer.WriteLine(name + ": " + value);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
681 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
682 public void SendErrorResponse(int state) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
683 String message = GetMessageForStatus(state);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
684 try {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
685 SendStatus(state, message);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
686 SendHeader("Content-Type", "text/plain");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
687 WriteResponseData(Encoding.ASCII.GetBytes(String.Format("Error {0}: {1}", state, message)));
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
688 } catch (Exception ex) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
689 Console.Error.WriteLine(ex);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
690 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
691 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
692 public Stream OpenResponseStream(HTTPResponseStreamMode mode) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
693 if (ResponseStream != null) throw new InvalidOperationException("The response stream has already been opened");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
694 return ResponseStream = new HTTPOutputStream(this, mode);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
695 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
696 public Stream OpenResponseStream(long length) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
697 if (ResponseStream != null) throw new InvalidOperationException("The response stream has already been opened");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
698 if (length < 0) throw new ArgumentException("Response length can not be negative", "length");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
699 return ResponseStream = new HTTPOutputStream(this, HTTPResponseStreamMode.Direct, length);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
700 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
701 public void WriteResponseData(Byte[] buffer) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
702 WriteResponseData(buffer, 0, buffer.Length);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
703 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
704 public void WriteResponseData(Byte[] buffer, int offset, int count) {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
705 if (offset < 0 || count < 0 || offset + count > buffer.Length) throw new ArgumentOutOfRangeException("buffer", "Offset and count arguments exceed the buffer dimensions");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
706 SendHeader("Content-Length", count.ToString());
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
707 Stream stream = BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
708 stream.Write(buffer, offset, count);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
709 EndResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
710 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
711 private Stream BeginResponseData() {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
712 if (State == HTTPConnectionState.ProcessingRequest) SendStatus(200);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
713 if (State == HTTPConnectionState.SendingHeaders) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
714 Writer.WriteLine();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
715 State = HTTPConnectionState.SendingContent;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
716 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
717 if (State != HTTPConnectionState.SendingContent) throw new InvalidOperationException("The response stream can not be opened in the current state");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
718 return Reader;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
719 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
720 private void EndResponseData() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
721 if (State == HTTPConnectionState.Completed || State == HTTPConnectionState.Closed) return;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
722 OpenRequestStream().Close();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
723 if (State != HTTPConnectionState.SendingContent) WriteResponseData(new Byte[0]);
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
724 State = HTTPConnectionState.Completed;
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
725 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
726
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
727 public Stream GetDirectStream() {
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
728 if (State == HTTPConnectionState.Closed) throw new InvalidOperationException("The context has been closed");
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
729 BeginResponseData();
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
730 State = HTTPConnectionState.Closed;
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
731 return Reader;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
732 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
733
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
734 private void SendErrorAndClose(int code) {
99
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
735 try {
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
736 SendErrorResponse(code);
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
737 } catch (IOException) {
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
738 } catch (SocketException) {
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
739 } catch (ObjectDisposedException) {
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
740 } finally {
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
741 Close();
be17dd3f6927 Small fixes in HTTP server and libusb1 backend
Ivo Smits <Ivo@UCIS.nl>
parents: 95
diff changeset
742 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
743 }
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
744 private void Close() {
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
745 if (State == HTTPConnectionState.Closed) return;
6
5ce7a138fdba Improvements in HTTP server
Ivo Smits <Ivo@UCIS.nl>
parents: 4
diff changeset
746 Reader.Close();
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
747 State = HTTPConnectionState.Closed;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
748 }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
749 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
750
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
751 public interface IHTTPContentProvider {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
752 void ServeRequest(HTTPContext context);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
753 }
12
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
754 public delegate void HTTPContentProviderDelegate(HTTPContext context);
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
755 public class HTTPContentProviderFunction : IHTTPContentProvider {
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
756 public HTTPContentProviderDelegate Handler { get; private set; }
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
757 public HTTPContentProviderFunction(HTTPContentProviderDelegate handler) {
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
758 this.Handler = handler;
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
759 }
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
760 public void ServeRequest(HTTPContext context) {
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
761 Handler(context);
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
762 }
ba8f94212c6e Added WebSocket support
Ivo Smits <Ivo@UCIS.nl>
parents: 10
diff changeset
763 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
764 public class HTTPPathSelector : IHTTPContentProvider {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
765 private List<KeyValuePair<String, IHTTPContentProvider>> Prefixes;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
766 private StringComparison PrefixComparison;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
767 public HTTPPathSelector() : this(false) { }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
768 public HTTPPathSelector(Boolean caseSensitive) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
769 Prefixes = new List<KeyValuePair<string, IHTTPContentProvider>>();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
770 PrefixComparison = caseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
771 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
772 public void AddPrefix(String prefix, IHTTPContentProvider contentProvider) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
773 Prefixes.Add(new KeyValuePair<string, IHTTPContentProvider>(prefix, contentProvider));
94
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
774 Prefixes.Sort(delegate(KeyValuePair<String, IHTTPContentProvider> a, KeyValuePair<String, IHTTPContentProvider> b) {
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
775 return -String.CompareOrdinal(a.Key, b.Key);
3c1bba376dca HTTP: Added support for cookies, improved prefix selector
Ivo Smits <Ivo@UCIS.nl>
parents: 75
diff changeset
776 });
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
777 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
778 public void DeletePrefix(String prefix) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
779 Prefixes.RemoveAll(delegate(KeyValuePair<string, IHTTPContentProvider> item) { return prefix.Equals(item.Key, PrefixComparison); });
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
780 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
781 public void ServeRequest(HTTPContext context) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
782 KeyValuePair<string, IHTTPContentProvider> c = Prefixes.Find(delegate(KeyValuePair<string, IHTTPContentProvider> item) { return context.RequestPath.StartsWith(item.Key, PrefixComparison); });
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
783 if (c.Value != null) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
784 c.Value.ServeRequest(context);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
785 } else {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
786 context.SendErrorResponse(404);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
787 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
788 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
789 }
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
790 public class HTTPStaticContent : IHTTPContentProvider {
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
791 public ArraySegment<Byte> ContentBuffer { get; set; }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
792 public String ContentType { get; set; }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
793 public HTTPStaticContent() : this(new ArraySegment<Byte>()) { }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
794 public HTTPStaticContent(ArraySegment<Byte> content) : this(content, "application/octet-stream") { }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
795 public HTTPStaticContent(String content, String contentType) : this(Encoding.UTF8.GetBytes(content), contentType) { }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
796 public HTTPStaticContent(String contentType) : this(new ArraySegment<Byte>(), contentType) { }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
797 public HTTPStaticContent(Byte[] content, String contentType) : this(new ArraySegment<Byte>(content), contentType) { }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
798 public HTTPStaticContent(ArraySegment<Byte> content, String contentType) {
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
799 this.ContentBuffer = content;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
800 this.ContentType = contentType;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
801 }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
802 public void SetContent(Byte[] bytes) { ContentBuffer = new ArraySegment<byte>(bytes); }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
803 public void SetContent(Byte[] bytes, int offset, int count) { ContentBuffer = new ArraySegment<byte>(bytes, offset, count); }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
804 public void SetContent(String content, Encoding encoding) { SetContent(encoding.GetBytes(content)); }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
805 public void SetContent(String content) { SetContent(content, Encoding.UTF8); }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
806 public void ServeRequest(HTTPContext context) {
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
807 ArraySegment<Byte> content = ContentBuffer;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
808 if (content.Array == null) {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
809 context.SendErrorResponse(404);
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
810 return;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
811 }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
812 String contentType = ContentType;
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
813 context.SendStatus(200);
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
814 if (contentType != null) context.SendHeader("Content-Type", contentType);
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
815 context.WriteResponseData(content.Array, content.Offset, content.Count);
7
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
816 }
4b78cc5f116b Fixes and improvements (some untested)
Ivo Smits <Ivo@UCIS.nl>
parents: 6
diff changeset
817 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
818 public class HTTPFileProvider : IHTTPContentProvider {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
819 public String FileName { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
820 public String ContentType { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
821 public HTTPFileProvider(String fileName) : this(fileName, "application/octet-stream") { }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
822 public HTTPFileProvider(String fileName, String contentType) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
823 this.FileName = fileName;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
824 this.ContentType = contentType;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
825 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
826 public void ServeRequest(HTTPContext context) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
827 if (File.Exists(FileName)) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
828 using (FileStream fs = File.OpenRead(FileName)) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
829 context.SendStatus(200);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
830 context.SendHeader("Content-Type", ContentType);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
831 long left = fs.Length;
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
832 Stream response = context.OpenResponseStream(fs.Length);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
833 byte[] buffer = new byte[1024 * 10];
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
834 while (fs.CanRead) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
835 int len = fs.Read(buffer, 0, buffer.Length);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
836 if (len <= 0) break;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
837 left -= len;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
838 response.Write(buffer, 0, len);
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
839 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
840 response.Close();
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
841 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
842 } else {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
843 context.SendErrorResponse(404);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
844 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
845 }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
846 }
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
847 public class HTTPUnTarchiveProvider : IHTTPContentProvider {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
848 public String TarFileName { get; private set; }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
849 public HTTPUnTarchiveProvider(String tarFile) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
850 this.TarFileName = tarFile;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
851 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
852 public void ServeRequest(HTTPContext context) {
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
853 if (!File.Exists(TarFileName)) {
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
854 context.SendErrorResponse(404);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
855 return;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
856 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
857 String reqname1 = context.RequestPath;
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
858 if (reqname1.StartsWith("/")) reqname1 = reqname1.Substring(1);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
859 String reqname2 = reqname1;
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
860 if (reqname2.Length > 0 && !reqname2.EndsWith("/")) reqname2 += "/";
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
861 reqname2 += "index.htm";
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
862 foreach (TarchiveEntry file in new TarchiveReader(TarFileName)) {
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
863 if (!file.IsFile) continue;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
864 if (!reqname1.Equals(file.Name, StringComparison.OrdinalIgnoreCase) && !reqname2.Equals(file.Name, StringComparison.OrdinalIgnoreCase)) continue;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
865 context.SendStatus(200);
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
866 String ctype = null;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
867 switch (Path.GetExtension(file.Name).ToLowerInvariant()) {
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
868 case ".txt": ctype = "text/plain"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
869 case ".htm":
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
870 case ".html": ctype = "text/html"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
871 case ".css": ctype = "text/css"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
872 case ".js": ctype = "application/x-javascript"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
873 case ".png": ctype = "image/png"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
874 case ".jpg":
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
875 case ".jpeg": ctype = "image/jpeg"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
876 case ".gif": ctype = "image/gif"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
877 case ".ico": ctype = "image/x-icon"; break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
878 }
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
879 if (ctype != null) context.SendHeader("Content-Type", ctype);
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
880 using (Stream response = context.OpenResponseStream(file.Size), source = file.GetStream()) {
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
881 byte[] buffer = new byte[Math.Min(source.Length, 1024 * 10)];
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
882 while (source.CanRead) {
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
883 int len = source.Read(buffer, 0, buffer.Length);
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
884 if (len <= 0) break;
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
885 response.Write(buffer, 0, len);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
886 }
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
887 }
54
ba4e2cb031e0 Added general purpose tar archive reader class
Ivo Smits <Ivo@UCIS.nl>
parents: 45
diff changeset
888 return;
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
889 }
75
50d4aed66c67 Improved HTTP classes
Ivo Smits <Ivo@UCIS.nl>
parents: 54
diff changeset
890 context.SendErrorResponse(404);
3
0cc7be03775f Improved HTTP Server components
Ivo Smits <Ivo@UCIS.nl>
parents: 0
diff changeset
891 }
0
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
892 }
3ab940a0c7a0 Initial commit
Ivo Smits <Ivo@UCIS.nl>
parents:
diff changeset
893 }