55using System . Text . RegularExpressions ;
66using System . Web ;
77
8- class SimpleHttpServer
8+ public class SimpleHttpServer
99{
10- static string port = "8000" ;
11- static string host = "+" ;
12- static string root = "./" ;
13- static string prefix = null ;
10+ private static string s_root = "./" ;
11+ private static string s_prefix = null ;
1412
15- static void Main ( string [ ] args )
13+ public static void Main ( string [ ] args )
1614{
17- ParseOptions ( args ) ;
18- if ( prefix == null )
19- {
20- prefix = string . Format ( "http://{0}:{1}/" , host , port ) ;
21- }
2215try
2316{
17+ ParseOptions ( args ) ;
2418string prefixPath = WebUtility . UrlDecode (
25- Regex . Replace ( prefix , @"https?://[^/]*" , "" ) ) ;
19+ Regex . Replace ( s_prefix , @"https?://[^/]*" , "" ) ) ;
20+
2621using ( var listener = new HttpListener ( ) )
2722{
28- listener . Prefixes . Add ( prefix ) ;
23+ listener . Prefixes . Add ( s_prefix ) ;
2924listener . Start ( ) ;
30- Console . WriteLine ( "Listening on " + prefix ) ;
25+ Console . WriteLine ( "Listening on " + s_prefix ) ;
26+
3127while ( true )
3228{
3329var context = listener . GetContext ( ) ;
3430var request = context . Request ;
31+
3532using ( var response = context . Response )
3633{
3734string rawPath = WebUtility . UrlDecode (
3835Regex . Replace ( request . RawUrl , "[?;].*$" , "" ) ) ;
36+
3937if ( 0 < prefixPath . Length && rawPath . StartsWith ( prefixPath ) )
4038{
4139rawPath = rawPath . Substring ( prefixPath . Length - 1 ) ;
4240}
43- string path = ( root + rawPath ) . Replace ( "//" , "/" ) . Replace ( "/" , @"\" ) ;
41+
42+ string path = ( s_root + rawPath )
43+ . Replace ( "//" , "/" ) . Replace ( "/" , @"\" ) ;
44+
4445if ( path . EndsWith ( @"\" ) && File . Exists ( path + "index.html" ) )
4546{
4647path += "index.html" ;
4748}
49+
4850byte [ ] content = null ;
51+
4952if ( ! request . HttpMethod . Equals ( "GET" ) )
5053{
51- response . StatusCode = ( int ) HttpStatusCode . NotImplemented ; //501
54+ response . StatusCode = 501 ; //NotImplemented
5255}
5356else if ( path . Contains ( @"\..\" ) || path . EndsWith ( @"\.." ) )
5457{
55- response . StatusCode = ( int ) HttpStatusCode . BadRequest ; //400
58+ response . StatusCode = 400 ; //BadRequest
5659}
5760else if ( path . EndsWith ( @"\" )
5861&& Directory . Exists ( path . Substring ( 0 , path . Length - 1 ) ) )
5962{
60- string indexPage = CreateIndexPage ( path , rawPath ) ;
61- content = Encoding . UTF8 . GetBytes ( indexPage ) ;
62- response . ContentType = "text/html" ;
63- response . OutputStream . Write ( content , 0 , content . Length ) ;
63+ string indexPage = CreateIndexPage ( path , rawPath ) ;
64+ content = Encoding . UTF8 . GetBytes ( indexPage ) ;
65+ response . ContentType = "text/html" ;
66+ response . OutputStream . Write ( content , 0 , content . Length ) ;
6467}
6568else if ( Directory . Exists ( path ) )
6669{
67- var hosts = request . Headers . GetValues ( "Host" ) ;
68- var thisHost = ( hosts != null ) ? hosts [ 0 ] : request . UserHostAddress ;
70+ string [ ] hosts = request . Headers . GetValues ( "Host" ) ;
71+ string thisHost = ( hosts != null )
72+ ? hosts [ 0 ]
73+ : request . UserHostAddress ;
6974response . Headers . Set (
7075"Location" ,
7176string . Format ( "http://{0}{1}/" , thisHost , request . RawUrl ) ) ;
72- response . StatusCode = ( int ) HttpStatusCode . MovedPermanently ; //301
77+ response . StatusCode = 301 ; //MovedPermanently
7378}
7479else if ( ! File . Exists ( path ) )
7580{
76- response . StatusCode = ( int ) HttpStatusCode . NotFound ; //404
81+ response . StatusCode = 404 ; //NotFound
7782}
7883else
7984{
@@ -86,14 +91,17 @@ static void Main(string[] args)
8691catch ( Exception e )
8792{
8893Console . Error . WriteLine ( e ) ;
89- response . StatusCode = ( int ) HttpStatusCode . Forbidden ; //403
94+ response . StatusCode = 403 ; //Forbidden
9095}
9196}
97+
9298Console . WriteLine (
9399string . Format ( "{0} - - [{1}]\" {2} {3} HTTP/{4}\" {5} {6}" ,
94100request . RemoteEndPoint . Address ,
95101DateTime . Now . ToString ( "yyyy-MM-dd HH:mm:ss K" ) ,
96- request . HttpMethod , request . RawUrl , request . ProtocolVersion ,
102+ request . HttpMethod ,
103+ request . RawUrl ,
104+ request . ProtocolVersion ,
97105response . StatusCode ,
98106( content == null ? 0 : content . Length ) ) ) ;
99107}
@@ -106,15 +114,18 @@ static void Main(string[] args)
106114}
107115}
108116
109- static void ParseOptions ( string [ ] args )
117+ private static void ParseOptions ( string [ ] args )
110118{
119+ string port = "8000" ;
120+ string host = "+" ;
121+
111122for ( var i = 0 ; i < args . Length ; i ++ )
112123{
113- if ( args [ i ] . Equals ( "-t" ) ) prefix = "http://+:80/Temporary_Listen_Addresses/" ;
114- else if ( args [ i ] . Equals ( "-p" ) && i + 1 < args . Length ) port = args [ ++ i ] ;
115- else if ( args [ i ] . Equals ( "-b" ) && i + 1 < args . Length ) host = args [ ++ i ] ;
116- else if ( args [ i ] . Equals ( "-r" ) && i + 1 < args . Length ) root = args [ ++ i ] ;
117- else if ( args [ i ] . Equals ( "-P" ) && i + 1 < args . Length ) prefix = args [ ++ i ] ;
124+ if ( args [ i ] . Equals ( "-t" ) ) { s_prefix = "http://+:80/Temporary_Listen_Addresses/" ; }
125+ else if ( args [ i ] . Equals ( "-p" ) && i + 1 < args . Length ) { port = args [ ++ i ] ; }
126+ else if ( args [ i ] . Equals ( "-b" ) && i + 1 < args . Length ) { host = args [ ++ i ] ; }
127+ else if ( args [ i ] . Equals ( "-r" ) && i + 1 < args . Length ) { s_root = args [ ++ i ] ; }
128+ else if ( args [ i ] . Equals ( "-P" ) && i + 1 < args . Length ) { s_prefix = args [ ++ i ] ; }
118129else
119130{
120131Console . Error . WriteLine (
@@ -124,20 +135,28 @@ static void ParseOptions(string[] args)
124135Environment . Exit ( 0 ) ;
125136}
126137}
138+
139+ if ( s_prefix == null )
140+ {
141+ s_prefix = string . Format ( "http://{0}:{1}/" , host , port ) ;
142+ }
127143}
128144
129- static string CreateIndexPage ( string path , string urlPath )
145+ private static string CreateIndexPage ( string path , string urlPath )
130146{
131147string [ ] files = Directory . GetFileSystemEntries ( path ) ;
132148string indexPage = string . Format (
133149"<html><head><meta charset=\" UTF-8\" /></head>\n " +
134150"<body><h1>List of {0}</h1><ul>\n " ,
135151WebUtility . HtmlEncode ( urlPath ) ) ;
152+
136153if ( urlPath != "/" )
137154{
138155indexPage += "<li><a href=\" ..\" >..</a></li>\n " ;
139156}
140- foreach ( string file in files ) {
157+
158+ foreach ( string file in files )
159+ {
141160string basename = Path . GetFileName ( file ) ;
142161string link = string . Format (
143162"<li><a href=\" {0}{2}\" >{1}{2}</a></li>\n " ,
@@ -146,6 +165,7 @@ static string CreateIndexPage(string path, string urlPath)
146165Directory . Exists ( file ) ? "/" : "" ) ;
147166indexPage += link ;
148167}
168+
149169indexPage += "</ul></body></html>\n " ;
150170return indexPage ;
151171}